From 7ecd23528e29736312a1849b359321c5ff9b9a05 Mon Sep 17 00:00:00 2001 From: toji Date: Fri, 8 Mar 2024 21:50:41 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20=20@=20ad7d0?= =?UTF-8?q?67d3a658c730561b4955ab14187835e8ef3=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/font/ya-hei-ascii-msdf.json | 1 + assets/font/ya-hei-ascii.png | Bin 0 -> 107021 bytes main.js | 20 + main.js.map | 2 +- sample/textRenderingMsdf/index.html | 27 + sample/textRenderingMsdf/main.js | 3193 ++++++++++++++++++++++++ sample/textRenderingMsdf/main.js.map | 1 + sample/textRenderingMsdf/main.ts | 327 +++ sample/textRenderingMsdf/meta.ts | 18 + sample/textRenderingMsdf/msdfText.ts | 513 ++++ sample/textRenderingMsdf/msdfText.wgsl | 79 + samples/textRenderingMsdf/index.html | 9 + 12 files changed, 4189 insertions(+), 1 deletion(-) create mode 100644 assets/font/ya-hei-ascii-msdf.json create mode 100644 assets/font/ya-hei-ascii.png create mode 100644 sample/textRenderingMsdf/index.html create mode 100644 sample/textRenderingMsdf/main.js create mode 100644 sample/textRenderingMsdf/main.js.map create mode 100644 sample/textRenderingMsdf/main.ts create mode 100644 sample/textRenderingMsdf/meta.ts create mode 100644 sample/textRenderingMsdf/msdfText.ts create mode 100644 sample/textRenderingMsdf/msdfText.wgsl create mode 100644 samples/textRenderingMsdf/index.html diff --git a/assets/font/ya-hei-ascii-msdf.json b/assets/font/ya-hei-ascii-msdf.json new file mode 100644 index 00000000..2cbc9910 --- /dev/null +++ b/assets/font/ya-hei-ascii-msdf.json @@ -0,0 +1 @@ +{"pages":["ya-hei-ascii.png"],"chars":[{"id":124,"index":98,"char":"|","width":8,"height":49,"xoffset":2,"yoffset":1,"xadvance":11,"chnl":15,"x":0,"y":0,"page":0},{"id":106,"index":80,"char":"j","width":16,"height":48,"xoffset":-6,"yoffset":3,"xadvance":11,"chnl":15,"x":0,"y":50,"page":0},{"id":87,"index":61,"char":"W","width":46,"height":36,"xoffset":-1,"yoffset":4,"xadvance":43,"chnl":15,"x":9,"y":0,"page":0},{"id":81,"index":55,"char":"Q","width":35,"height":45,"xoffset":0,"yoffset":4,"xadvance":34,"chnl":15,"x":0,"y":99,"page":0},{"id":36,"index":10,"char":"$","width":22,"height":44,"xoffset":1,"yoffset":0,"xadvance":25,"chnl":15,"x":17,"y":37,"page":0},{"id":40,"index":14,"char":"(","width":14,"height":43,"xoffset":1,"yoffset":4,"xadvance":14,"chnl":15,"x":0,"y":145,"page":0},{"id":41,"index":15,"char":")","width":15,"height":43,"xoffset":-2,"yoffset":4,"xadvance":14,"chnl":15,"x":0,"y":189,"page":0},{"id":91,"index":65,"char":"[","width":12,"height":43,"xoffset":2,"yoffset":4,"xadvance":14,"chnl":15,"x":15,"y":145,"page":0},{"id":93,"index":67,"char":"]","width":12,"height":43,"xoffset":-1,"yoffset":4,"xadvance":14,"chnl":15,"x":0,"y":233,"page":0},{"id":123,"index":97,"char":"{","width":15,"height":43,"xoffset":0,"yoffset":4,"xadvance":14,"chnl":15,"x":0,"y":277,"page":0},{"id":125,"index":99,"char":"}","width":15,"height":43,"xoffset":-1,"yoffset":4,"xadvance":14,"chnl":15,"x":13,"y":233,"page":0},{"id":47,"index":21,"char":"/","width":23,"height":41,"xoffset":-3,"yoffset":4,"xadvance":18,"chnl":15,"x":16,"y":189,"page":0},{"id":92,"index":66,"char":"\\","width":23,"height":41,"xoffset":-3,"yoffset":4,"xadvance":17,"chnl":15,"x":28,"y":145,"page":0},{"id":12385,"index":28668,"char":"ち","width":33,"height":41,"xoffset":3,"yoffset":2,"xadvance":42,"chnl":15,"x":36,"y":82,"page":0},{"id":64,"index":38,"char":"@","width":40,"height":40,"xoffset":2,"yoffset":4,"xadvance":43,"chnl":15,"x":40,"y":37,"page":0},{"id":12435,"index":28718,"char":"ん","width":39,"height":38,"xoffset":1,"yoffset":3,"xadvance":42,"chnl":15,"x":0,"y":321,"page":0},{"id":37,"index":11,"char":"%","width":38,"height":37,"xoffset":0,"yoffset":4,"xadvance":37,"chnl":15,"x":16,"y":277,"page":0},{"id":98,"index":72,"char":"b","width":25,"height":38,"xoffset":2,"yoffset":2,"xadvance":27,"chnl":15,"x":29,"y":231,"page":0},{"id":100,"index":74,"char":"d","width":25,"height":38,"xoffset":0,"yoffset":2,"xadvance":27,"chnl":15,"x":40,"y":187,"page":0},{"id":102,"index":76,"char":"f","width":18,"height":38,"xoffset":-1,"yoffset":2,"xadvance":15,"chnl":15,"x":52,"y":124,"page":0},{"id":103,"index":77,"char":"g","width":25,"height":38,"xoffset":0,"yoffset":13,"xadvance":27,"chnl":15,"x":70,"y":78,"page":0},{"id":104,"index":78,"char":"h","width":23,"height":38,"xoffset":2,"yoffset":2,"xadvance":26,"chnl":15,"x":81,"y":0,"page":0},{"id":107,"index":81,"char":"k","width":23,"height":38,"xoffset":2,"yoffset":2,"xadvance":23,"chnl":15,"x":81,"y":39,"page":0},{"id":108,"index":82,"char":"l","width":8,"height":38,"xoffset":2,"yoffset":2,"xadvance":11,"chnl":15,"x":0,"y":360,"page":0},{"id":112,"index":86,"char":"p","width":25,"height":38,"xoffset":2,"yoffset":13,"xadvance":27,"chnl":15,"x":0,"y":399,"page":0},{"id":113,"index":87,"char":"q","width":25,"height":38,"xoffset":0,"yoffset":13,"xadvance":27,"chnl":15,"x":9,"y":360,"page":0},{"id":12399,"index":28682,"char":"は","width":38,"height":38,"xoffset":3,"yoffset":4,"xadvance":42,"chnl":15,"x":0,"y":438,"page":0},{"id":38,"index":12,"char":"&","width":37,"height":37,"xoffset":1,"yoffset":4,"xadvance":37,"chnl":15,"x":26,"y":399,"page":0},{"id":48,"index":22,"char":"0","width":25,"height":37,"xoffset":0,"yoffset":4,"xadvance":25,"chnl":15,"x":35,"y":360,"page":0},{"id":51,"index":25,"char":"3","width":23,"height":37,"xoffset":1,"yoffset":4,"xadvance":25,"chnl":15,"x":40,"y":315,"page":0},{"id":54,"index":28,"char":"6","width":24,"height":37,"xoffset":0,"yoffset":4,"xadvance":25,"chnl":15,"x":61,"y":353,"page":0},{"id":56,"index":30,"char":"8","width":24,"height":37,"xoffset":0,"yoffset":4,"xadvance":25,"chnl":15,"x":39,"y":437,"page":0},{"id":57,"index":31,"char":"9","width":24,"height":37,"xoffset":0,"yoffset":4,"xadvance":25,"chnl":15,"x":39,"y":475,"page":0},{"id":63,"index":37,"char":"?","width":19,"height":37,"xoffset":1,"yoffset":4,"xadvance":20,"chnl":15,"x":55,"y":226,"page":0},{"id":67,"index":41,"char":"C","width":28,"height":37,"xoffset":0,"yoffset":4,"xadvance":28,"chnl":15,"x":55,"y":264,"page":0},{"id":71,"index":45,"char":"G","width":30,"height":37,"xoffset":0,"yoffset":4,"xadvance":31,"chnl":15,"x":64,"y":302,"page":0},{"id":77,"index":51,"char":"M","width":37,"height":36,"xoffset":2,"yoffset":4,"xadvance":41,"chnl":15,"x":66,"y":163,"page":0},{"id":79,"index":53,"char":"O","width":34,"height":37,"xoffset":0,"yoffset":4,"xadvance":34,"chnl":15,"x":71,"y":117,"page":0},{"id":83,"index":57,"char":"S","width":24,"height":37,"xoffset":1,"yoffset":4,"xadvance":24,"chnl":15,"x":96,"y":78,"page":0},{"id":105,"index":79,"char":"i","width":9,"height":37,"xoffset":1,"yoffset":3,"xadvance":11,"chnl":15,"x":75,"y":200,"page":0},{"id":109,"index":83,"char":"m","width":37,"height":27,"xoffset":2,"yoffset":13,"xadvance":39,"chnl":15,"x":0,"y":477,"page":0},{"id":121,"index":95,"char":"y","width":26,"height":37,"xoffset":-2,"yoffset":13,"xadvance":22,"chnl":15,"x":84,"y":238,"page":0},{"id":12395,"index":28678,"char":"に","width":37,"height":37,"xoffset":3,"yoffset":4,"xadvance":42,"chnl":15,"x":85,"y":200,"page":0},{"id":33,"index":7,"char":"!","width":9,"height":36,"xoffset":2,"yoffset":4,"xadvance":13,"chnl":15,"x":56,"y":0,"page":0},{"id":49,"index":23,"char":"1","width":22,"height":36,"xoffset":2,"yoffset":4,"xadvance":25,"chnl":15,"x":104,"y":155,"page":0},{"id":50,"index":24,"char":"2","width":24,"height":36,"xoffset":0,"yoffset":4,"xadvance":25,"chnl":15,"x":106,"y":116,"page":0},{"id":52,"index":26,"char":"4","width":27,"height":36,"xoffset":-2,"yoffset":4,"xadvance":25,"chnl":15,"x":105,"y":0,"page":0},{"id":53,"index":27,"char":"5","width":22,"height":36,"xoffset":2,"yoffset":4,"xadvance":25,"chnl":15,"x":105,"y":37,"page":0},{"id":55,"index":29,"char":"7","width":25,"height":36,"xoffset":0,"yoffset":4,"xadvance":25,"chnl":15,"x":121,"y":74,"page":0},{"id":65,"index":39,"char":"A","width":33,"height":36,"xoffset":-2,"yoffset":4,"xadvance":30,"chnl":15,"x":128,"y":37,"page":0},{"id":66,"index":40,"char":"B","width":24,"height":36,"xoffset":2,"yoffset":4,"xadvance":26,"chnl":15,"x":133,"y":0,"page":0},{"id":68,"index":42,"char":"D","width":30,"height":36,"xoffset":2,"yoffset":4,"xadvance":32,"chnl":15,"x":158,"y":0,"page":0},{"id":69,"index":43,"char":"E","width":21,"height":36,"xoffset":2,"yoffset":4,"xadvance":23,"chnl":15,"x":64,"y":391,"page":0},{"id":70,"index":44,"char":"F","width":20,"height":36,"xoffset":2,"yoffset":4,"xadvance":22,"chnl":15,"x":64,"y":428,"page":0},{"id":72,"index":46,"char":"H","width":28,"height":36,"xoffset":2,"yoffset":4,"xadvance":32,"chnl":15,"x":64,"y":465,"page":0},{"id":73,"index":47,"char":"I","width":14,"height":36,"xoffset":-1,"yoffset":4,"xadvance":12,"chnl":15,"x":66,"y":0,"page":0},{"id":74,"index":48,"char":"J","width":16,"height":36,"xoffset":-2,"yoffset":4,"xadvance":17,"chnl":15,"x":85,"y":428,"page":0},{"id":75,"index":49,"char":"K","width":27,"height":36,"xoffset":2,"yoffset":4,"xadvance":27,"chnl":15,"x":93,"y":465,"page":0},{"id":76,"index":50,"char":"L","width":21,"height":36,"xoffset":2,"yoffset":4,"xadvance":22,"chnl":15,"x":86,"y":340,"page":0},{"id":78,"index":52,"char":"N","width":30,"height":36,"xoffset":2,"yoffset":4,"xadvance":34,"chnl":15,"x":86,"y":377,"page":0},{"id":80,"index":54,"char":"P","width":24,"height":36,"xoffset":2,"yoffset":4,"xadvance":26,"chnl":15,"x":102,"y":414,"page":0},{"id":82,"index":56,"char":"R","width":27,"height":36,"xoffset":2,"yoffset":4,"xadvance":27,"chnl":15,"x":121,"y":451,"page":0},{"id":84,"index":58,"char":"T","width":26,"height":36,"xoffset":-1,"yoffset":4,"xadvance":24,"chnl":15,"x":95,"y":276,"page":0},{"id":85,"index":59,"char":"U","width":28,"height":36,"xoffset":2,"yoffset":4,"xadvance":31,"chnl":15,"x":111,"y":238,"page":0},{"id":86,"index":60,"char":"V","width":32,"height":36,"xoffset":-2,"yoffset":4,"xadvance":28,"chnl":15,"x":123,"y":192,"page":0},{"id":88,"index":62,"char":"X","width":30,"height":36,"xoffset":-1,"yoffset":4,"xadvance":27,"chnl":15,"x":127,"y":153,"page":0},{"id":89,"index":63,"char":"Y","width":29,"height":36,"xoffset":-2,"yoffset":4,"xadvance":25,"chnl":15,"x":131,"y":111,"page":0},{"id":90,"index":64,"char":"Z","width":28,"height":36,"xoffset":-1,"yoffset":4,"xadvance":26,"chnl":15,"x":147,"y":74,"page":0},{"id":119,"index":93,"char":"w","width":36,"height":27,"xoffset":-1,"yoffset":13,"xadvance":33,"chnl":15,"x":162,"y":37,"page":0},{"id":116,"index":90,"char":"t","width":18,"height":34,"xoffset":-1,"yoffset":7,"xadvance":16,"chnl":15,"x":189,"y":0,"page":0},{"id":35,"index":9,"char":"#","width":29,"height":33,"xoffset":-1,"yoffset":4,"xadvance":27,"chnl":15,"x":108,"y":313,"page":0},{"id":59,"index":33,"char":";","width":11,"height":33,"xoffset":-1,"yoffset":13,"xadvance":10,"chnl":15,"x":122,"y":275,"page":0},{"id":12371,"index":28654,"char":"こ","width":32,"height":31,"xoffset":5,"yoffset":8,"xadvance":42,"chnl":15,"x":134,"y":275,"page":0},{"id":58,"index":32,"char":":","width":9,"height":28,"xoffset":0,"yoffset":13,"xadvance":10,"chnl":15,"x":108,"y":347,"page":0},{"id":97,"index":71,"char":"a","width":22,"height":28,"xoffset":0,"yoffset":13,"xadvance":23,"chnl":15,"x":117,"y":376,"page":0},{"id":99,"index":73,"char":"c","width":21,"height":28,"xoffset":0,"yoffset":13,"xadvance":21,"chnl":15,"x":118,"y":347,"page":0},{"id":101,"index":75,"char":"e","width":24,"height":28,"xoffset":0,"yoffset":13,"xadvance":24,"chnl":15,"x":138,"y":307,"page":0},{"id":111,"index":85,"char":"o","width":27,"height":28,"xoffset":0,"yoffset":13,"xadvance":27,"chnl":15,"x":140,"y":229,"page":0},{"id":115,"index":89,"char":"s","width":19,"height":28,"xoffset":0,"yoffset":13,"xadvance":19,"chnl":15,"x":156,"y":190,"page":0},{"id":110,"index":84,"char":"n","width":23,"height":27,"xoffset":2,"yoffset":13,"xadvance":26,"chnl":15,"x":158,"y":148,"page":0},{"id":114,"index":88,"char":"r","width":16,"height":27,"xoffset":2,"yoffset":13,"xadvance":16,"chnl":15,"x":161,"y":111,"page":0},{"id":117,"index":91,"char":"u","width":23,"height":27,"xoffset":1,"yoffset":13,"xadvance":26,"chnl":15,"x":127,"y":405,"page":0},{"id":118,"index":92,"char":"v","width":26,"height":27,"xoffset":-2,"yoffset":13,"xadvance":22,"chnl":15,"x":176,"y":65,"page":0},{"id":120,"index":94,"char":"x","width":24,"height":27,"xoffset":-1,"yoffset":13,"xadvance":21,"chnl":15,"x":199,"y":35,"page":0},{"id":122,"index":96,"char":"z","width":23,"height":27,"xoffset":-1,"yoffset":13,"xadvance":21,"chnl":15,"x":208,"y":0,"page":0},{"id":60,"index":34,"char":"<","width":23,"height":26,"xoffset":4,"yoffset":12,"xadvance":31,"chnl":15,"x":178,"y":93,"page":0},{"id":62,"index":36,"char":">","width":23,"height":26,"xoffset":4,"yoffset":12,"xadvance":31,"chnl":15,"x":178,"y":120,"page":0},{"id":126,"index":100,"char":"~","width":26,"height":11,"xoffset":3,"yoffset":19,"xadvance":31,"chnl":15,"x":158,"y":176,"page":0},{"id":43,"index":17,"char":"+","width":25,"height":25,"xoffset":3,"yoffset":12,"xadvance":31,"chnl":15,"x":182,"y":147,"page":0},{"id":61,"index":35,"char":"=","width":25,"height":17,"xoffset":3,"yoffset":17,"xadvance":31,"chnl":15,"x":127,"y":433,"page":0},{"id":94,"index":68,"char":"^","width":25,"height":23,"xoffset":3,"yoffset":4,"xadvance":31,"chnl":15,"x":121,"y":488,"page":0},{"id":95,"index":69,"char":"_","width":23,"height":7,"xoffset":-2,"yoffset":40,"xadvance":19,"chnl":15,"x":0,"y":505,"page":0},{"id":42,"index":16,"char":"*","width":20,"height":20,"xoffset":0,"yoffset":4,"xadvance":19,"chnl":15,"x":147,"y":488,"page":0},{"id":45,"index":19,"char":"-","width":16,"height":7,"xoffset":1,"yoffset":22,"xadvance":18,"chnl":15,"x":71,"y":155,"page":0},{"id":44,"index":18,"char":",","width":10,"height":15,"xoffset":-1,"yoffset":31,"xadvance":10,"chnl":15,"x":84,"y":276,"page":0},{"id":34,"index":8,"char":"\"","width":14,"height":14,"xoffset":2,"yoffset":4,"xadvance":18,"chnl":15,"x":36,"y":124,"page":0},{"id":39,"index":13,"char":"'","width":8,"height":14,"xoffset":1,"yoffset":4,"xadvance":11,"chnl":15,"x":66,"y":200,"page":0},{"id":96,"index":70,"char":"`","width":13,"height":11,"xoffset":0,"yoffset":2,"xadvance":12,"chnl":15,"x":52,"y":163,"page":0},{"id":46,"index":20,"char":".","width":9,"height":9,"xoffset":0,"yoffset":31,"xadvance":10,"chnl":15,"x":156,"y":219,"page":0},{"id":32,"index":3,"char":" ","width":0,"height":0,"xoffset":-2,"yoffset":36,"xadvance":12,"chnl":15,"x":26,"y":437,"page":0}],"info":{"face":"ya-hei-ascii","size":42,"bold":0,"italic":0,"charset":[" ","!","\"","#","$","%","&","'","(",")","*","+",",","-",".","/","0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?","@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","[","\\","]","^","_","`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","{","|","}","~","こ","ん","に","ち","は"],"unicode":1,"stretchH":100,"smooth":1,"aa":1,"padding":[2,2,2,2],"spacing":[0,0]},"common":{"lineHeight":45,"base":36,"scaleW":512,"scaleH":512,"pages":1,"packed":0,"alphaChnl":0,"redChnl":0,"greenChnl":0,"blueChnl":0},"distanceField":{"fieldType":"msdf","distanceRange":4},"kernings":[{"first":34,"second":114,"amount":-1},{"first":34,"second":115,"amount":-1},{"first":39,"second":114,"amount":-1},{"first":39,"second":115,"amount":-1},{"first":40,"second":106,"amount":5},{"first":42,"second":65,"amount":-4},{"first":42,"second":74,"amount":-3},{"first":42,"second":99,"amount":-2},{"first":42,"second":100,"amount":-2},{"first":42,"second":101,"amount":-2},{"first":42,"second":103,"amount":-2},{"first":42,"second":111,"amount":-2},{"first":42,"second":113,"amount":-2},{"first":65,"second":42,"amount":-3},{"first":65,"second":44,"amount":1},{"first":65,"second":59,"amount":1},{"first":65,"second":67,"amount":-1},{"first":65,"second":71,"amount":-1},{"first":65,"second":74,"amount":2},{"first":65,"second":79,"amount":-1},{"first":65,"second":84,"amount":-3},{"first":65,"second":85,"amount":-1},{"first":65,"second":86,"amount":-3},{"first":65,"second":87,"amount":-2},{"first":65,"second":89,"amount":-3},{"first":65,"second":90,"amount":1},{"first":65,"second":116,"amount":-1},{"first":65,"second":118,"amount":-1},{"first":65,"second":119,"amount":-1},{"first":65,"second":121,"amount":-1},{"first":66,"second":84,"amount":-2},{"first":66,"second":89,"amount":-1},{"first":67,"second":63,"amount":0},{"first":67,"second":67,"amount":-1},{"first":67,"second":71,"amount":-1},{"first":67,"second":79,"amount":-1},{"first":67,"second":81,"amount":-1},{"first":68,"second":44,"amount":-3},{"first":68,"second":46,"amount":-3},{"first":68,"second":65,"amount":-1},{"first":68,"second":84,"amount":-2},{"first":68,"second":88,"amount":-1},{"first":68,"second":90,"amount":-1},{"first":69,"second":65,"amount":0},{"first":69,"second":74,"amount":1},{"first":69,"second":84,"amount":0},{"first":69,"second":87,"amount":1},{"first":69,"second":88,"amount":0},{"first":70,"second":44,"amount":-3},{"first":70,"second":46,"amount":-3},{"first":70,"second":65,"amount":-3},{"first":70,"second":74,"amount":-1},{"first":70,"second":83,"amount":-1},{"first":70,"second":84,"amount":0},{"first":70,"second":97,"amount":-2},{"first":70,"second":102,"amount":0},{"first":71,"second":84,"amount":-1},{"first":71,"second":86,"amount":-1},{"first":71,"second":121,"amount":-1},{"first":74,"second":44,"amount":-2},{"first":74,"second":46,"amount":-2},{"first":74,"second":65,"amount":-1},{"first":74,"second":74,"amount":-1},{"first":74,"second":97,"amount":-1},{"first":75,"second":44,"amount":1},{"first":75,"second":59,"amount":1},{"first":75,"second":67,"amount":-2},{"first":75,"second":71,"amount":-2},{"first":75,"second":74,"amount":2},{"first":75,"second":79,"amount":-2},{"first":75,"second":81,"amount":-2},{"first":75,"second":88,"amount":1},{"first":75,"second":90,"amount":1},{"first":75,"second":99,"amount":-1},{"first":75,"second":100,"amount":-1},{"first":75,"second":101,"amount":-1},{"first":75,"second":103,"amount":-1},{"first":75,"second":111,"amount":-1},{"first":75,"second":113,"amount":-1},{"first":75,"second":116,"amount":-1},{"first":75,"second":118,"amount":-2},{"first":75,"second":119,"amount":-1},{"first":75,"second":121,"amount":-2},{"first":76,"second":42,"amount":-5},{"first":76,"second":63,"amount":-2},{"first":76,"second":65,"amount":1},{"first":76,"second":67,"amount":-1},{"first":76,"second":71,"amount":-1},{"first":76,"second":74,"amount":2},{"first":76,"second":79,"amount":-2},{"first":76,"second":81,"amount":-2},{"first":76,"second":84,"amount":-3},{"first":76,"second":85,"amount":-1},{"first":76,"second":86,"amount":-3},{"first":76,"second":87,"amount":-1},{"first":76,"second":89,"amount":-3},{"first":76,"second":90,"amount":1},{"first":76,"second":116,"amount":-1},{"first":76,"second":118,"amount":-2},{"first":76,"second":119,"amount":-1},{"first":76,"second":121,"amount":-2},{"first":79,"second":44,"amount":-2},{"first":79,"second":46,"amount":-2},{"first":79,"second":65,"amount":-1},{"first":79,"second":74,"amount":0},{"first":79,"second":84,"amount":-2},{"first":79,"second":88,"amount":-1},{"first":79,"second":89,"amount":-1},{"first":79,"second":90,"amount":-1},{"first":80,"second":44,"amount":-7},{"first":80,"second":46,"amount":-7},{"first":80,"second":65,"amount":-4},{"first":80,"second":71,"amount":0},{"first":80,"second":74,"amount":-3},{"first":80,"second":87,"amount":1},{"first":80,"second":88,"amount":-1},{"first":80,"second":97,"amount":-1},{"first":80,"second":99,"amount":-2},{"first":80,"second":100,"amount":-2},{"first":80,"second":101,"amount":-2},{"first":80,"second":103,"amount":-2},{"first":80,"second":111,"amount":-2},{"first":80,"second":113,"amount":-2},{"first":81,"second":44,"amount":-2},{"first":81,"second":46,"amount":-3},{"first":81,"second":65,"amount":-1},{"first":81,"second":84,"amount":-2},{"first":81,"second":88,"amount":-1},{"first":81,"second":89,"amount":0},{"first":81,"second":90,"amount":-1},{"first":82,"second":59,"amount":2},{"first":82,"second":67,"amount":-1},{"first":82,"second":71,"amount":-1},{"first":82,"second":74,"amount":1},{"first":82,"second":79,"amount":0},{"first":82,"second":81,"amount":0},{"first":82,"second":84,"amount":-1},{"first":82,"second":89,"amount":-1},{"first":82,"second":99,"amount":-1},{"first":82,"second":100,"amount":-1},{"first":82,"second":101,"amount":-1},{"first":82,"second":103,"amount":-1},{"first":82,"second":111,"amount":-1},{"first":82,"second":113,"amount":-1},{"first":83,"second":116,"amount":-1},{"first":83,"second":118,"amount":-1},{"first":83,"second":119,"amount":-1},{"first":83,"second":121,"amount":-1},{"first":84,"second":44,"amount":-3},{"first":84,"second":46,"amount":-4},{"first":84,"second":58,"amount":-1},{"first":84,"second":59,"amount":-1},{"first":84,"second":65,"amount":-3},{"first":84,"second":67,"amount":-2},{"first":84,"second":71,"amount":-2},{"first":84,"second":74,"amount":-3},{"first":84,"second":79,"amount":-2},{"first":84,"second":81,"amount":-2},{"first":84,"second":84,"amount":1},{"first":84,"second":86,"amount":1},{"first":84,"second":87,"amount":1},{"first":84,"second":88,"amount":0},{"first":84,"second":89,"amount":1},{"first":84,"second":97,"amount":-5},{"first":84,"second":99,"amount":-5},{"first":84,"second":100,"amount":-5},{"first":84,"second":101,"amount":-5},{"first":84,"second":102,"amount":-2},{"first":84,"second":103,"amount":-5},{"first":84,"second":109,"amount":-4},{"first":84,"second":110,"amount":-4},{"first":84,"second":111,"amount":-5},{"first":84,"second":112,"amount":-4},{"first":84,"second":113,"amount":-5},{"first":84,"second":114,"amount":-4},{"first":84,"second":115,"amount":-3},{"first":84,"second":117,"amount":-4},{"first":84,"second":118,"amount":-2},{"first":84,"second":119,"amount":-3},{"first":84,"second":120,"amount":-4},{"first":84,"second":121,"amount":-3},{"first":84,"second":122,"amount":-3},{"first":85,"second":65,"amount":-1},{"first":86,"second":44,"amount":-5},{"first":86,"second":46,"amount":-5},{"first":86,"second":65,"amount":-3},{"first":86,"second":67,"amount":-1},{"first":86,"second":71,"amount":-1},{"first":86,"second":74,"amount":-2},{"first":86,"second":79,"amount":0},{"first":86,"second":81,"amount":-1},{"first":86,"second":83,"amount":-1},{"first":86,"second":84,"amount":1},{"first":86,"second":97,"amount":-3},{"first":86,"second":99,"amount":-3},{"first":86,"second":100,"amount":-3},{"first":86,"second":101,"amount":-3},{"first":86,"second":103,"amount":-3},{"first":86,"second":109,"amount":-2},{"first":86,"second":110,"amount":-2},{"first":86,"second":111,"amount":-3},{"first":86,"second":112,"amount":-2},{"first":86,"second":113,"amount":-3},{"first":86,"second":114,"amount":-2},{"first":86,"second":115,"amount":-1},{"first":86,"second":117,"amount":-2},{"first":87,"second":44,"amount":-3},{"first":87,"second":46,"amount":-3},{"first":87,"second":65,"amount":-2},{"first":87,"second":84,"amount":1},{"first":87,"second":97,"amount":-2},{"first":87,"second":99,"amount":-1},{"first":87,"second":100,"amount":-1},{"first":87,"second":101,"amount":-1},{"first":87,"second":103,"amount":-1},{"first":87,"second":111,"amount":-1},{"first":87,"second":113,"amount":-1},{"first":88,"second":44,"amount":1},{"first":88,"second":46,"amount":1},{"first":88,"second":59,"amount":2},{"first":88,"second":67,"amount":-1},{"first":88,"second":71,"amount":-1},{"first":88,"second":74,"amount":2},{"first":88,"second":79,"amount":-1},{"first":88,"second":81,"amount":-1},{"first":88,"second":84,"amount":1},{"first":89,"second":44,"amount":-4},{"first":89,"second":46,"amount":-4},{"first":89,"second":65,"amount":-4},{"first":89,"second":67,"amount":-1},{"first":89,"second":71,"amount":-1},{"first":89,"second":74,"amount":-1},{"first":89,"second":79,"amount":-1},{"first":89,"second":81,"amount":-1},{"first":89,"second":83,"amount":-1},{"first":89,"second":84,"amount":1},{"first":89,"second":97,"amount":-4},{"first":89,"second":99,"amount":-4},{"first":89,"second":100,"amount":-4},{"first":89,"second":101,"amount":-4},{"first":89,"second":102,"amount":-1},{"first":89,"second":103,"amount":-4},{"first":89,"second":109,"amount":-3},{"first":89,"second":110,"amount":-3},{"first":89,"second":111,"amount":-4},{"first":89,"second":112,"amount":-3},{"first":89,"second":113,"amount":-4},{"first":89,"second":114,"amount":-3},{"first":89,"second":115,"amount":-3},{"first":89,"second":117,"amount":-3},{"first":90,"second":74,"amount":2},{"first":90,"second":84,"amount":1},{"first":90,"second":121,"amount":-1},{"first":91,"second":106,"amount":5},{"first":98,"second":97,"amount":-1},{"first":98,"second":102,"amount":0},{"first":98,"second":120,"amount":-1},{"first":99,"second":74,"amount":2},{"first":99,"second":84,"amount":-2},{"first":99,"second":89,"amount":-2},{"first":101,"second":34,"amount":-2},{"first":101,"second":39,"amount":-2},{"first":102,"second":41,"amount":3},{"first":102,"second":44,"amount":-3},{"first":102,"second":45,"amount":-2},{"first":102,"second":46,"amount":-3},{"first":102,"second":58,"amount":2},{"first":102,"second":59,"amount":2},{"first":102,"second":63,"amount":1},{"first":102,"second":93,"amount":3},{"first":102,"second":98,"amount":0},{"first":102,"second":104,"amount":0},{"first":102,"second":116,"amount":1},{"first":102,"second":118,"amount":1},{"first":102,"second":119,"amount":1},{"first":102,"second":120,"amount":0},{"first":102,"second":121,"amount":1},{"first":102,"second":125,"amount":2},{"first":103,"second":106,"amount":1},{"first":106,"second":106,"amount":1},{"first":107,"second":44,"amount":2},{"first":107,"second":45,"amount":-3},{"first":107,"second":46,"amount":2},{"first":107,"second":58,"amount":2},{"first":107,"second":59,"amount":2},{"first":107,"second":99,"amount":-1},{"first":107,"second":100,"amount":-1},{"first":107,"second":101,"amount":-1},{"first":107,"second":103,"amount":-1},{"first":107,"second":111,"amount":-1},{"first":107,"second":113,"amount":-1},{"first":107,"second":116,"amount":0},{"first":110,"second":34,"amount":-2},{"first":110,"second":39,"amount":-2},{"first":111,"second":34,"amount":-3},{"first":111,"second":39,"amount":-3},{"first":111,"second":97,"amount":-1},{"first":111,"second":102,"amount":-1},{"first":111,"second":120,"amount":-1},{"first":112,"second":97,"amount":-1},{"first":112,"second":102,"amount":-1},{"first":112,"second":120,"amount":-1},{"first":113,"second":106,"amount":2},{"first":114,"second":44,"amount":-4},{"first":114,"second":45,"amount":-3},{"first":114,"second":46,"amount":-4},{"first":114,"second":58,"amount":2},{"first":114,"second":59,"amount":2},{"first":114,"second":99,"amount":-1},{"first":114,"second":100,"amount":-1},{"first":114,"second":101,"amount":-1},{"first":114,"second":102,"amount":1},{"first":114,"second":103,"amount":-1},{"first":114,"second":109,"amount":0},{"first":114,"second":110,"amount":0},{"first":114,"second":111,"amount":-1},{"first":114,"second":113,"amount":-1},{"first":114,"second":115,"amount":0},{"first":114,"second":116,"amount":1},{"first":114,"second":118,"amount":2},{"first":114,"second":119,"amount":2},{"first":114,"second":120,"amount":1},{"first":114,"second":121,"amount":2},{"first":114,"second":122,"amount":1},{"first":116,"second":45,"amount":-3},{"first":116,"second":63,"amount":-1},{"first":116,"second":99,"amount":-1},{"first":116,"second":100,"amount":-1},{"first":116,"second":101,"amount":0},{"first":116,"second":103,"amount":0},{"first":116,"second":111,"amount":0},{"first":116,"second":113,"amount":0},{"first":116,"second":120,"amount":1},{"first":117,"second":34,"amount":-1},{"first":117,"second":39,"amount":-1},{"first":118,"second":44,"amount":-3},{"first":118,"second":46,"amount":-3},{"first":118,"second":97,"amount":-1},{"first":118,"second":99,"amount":0},{"first":118,"second":100,"amount":0},{"first":118,"second":101,"amount":0},{"first":118,"second":103,"amount":0},{"first":118,"second":111,"amount":0},{"first":118,"second":113,"amount":0},{"first":119,"second":44,"amount":-2},{"first":119,"second":46,"amount":-2},{"first":119,"second":99,"amount":0},{"first":119,"second":100,"amount":0},{"first":119,"second":101,"amount":0},{"first":119,"second":103,"amount":0},{"first":119,"second":111,"amount":0},{"first":119,"second":113,"amount":0},{"first":120,"second":99,"amount":0},{"first":120,"second":100,"amount":0},{"first":120,"second":101,"amount":0},{"first":120,"second":103,"amount":0},{"first":120,"second":111,"amount":0},{"first":120,"second":113,"amount":0},{"first":121,"second":34,"amount":1},{"first":121,"second":39,"amount":1},{"first":121,"second":44,"amount":-2},{"first":121,"second":46,"amount":-3},{"first":121,"second":63,"amount":-2},{"first":121,"second":99,"amount":0},{"first":121,"second":100,"amount":0},{"first":121,"second":101,"amount":0},{"first":121,"second":102,"amount":0},{"first":121,"second":103,"amount":0},{"first":121,"second":111,"amount":0},{"first":121,"second":113,"amount":0},{"first":121,"second":116,"amount":0},{"first":123,"second":106,"amount":4}]} \ No newline at end of file diff --git a/assets/font/ya-hei-ascii.png b/assets/font/ya-hei-ascii.png new file mode 100644 index 0000000000000000000000000000000000000000..a23980bb48a6bfb77754b5a18ccaa368bbfb9df8 GIT binary patch literal 107021 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

qho-gS|0Jn`;GT6 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 literal 0 HcmV?d00001 diff --git a/main.js b/main.js index 1ea5cc1f..7159c0c6 100644 --- a/main.js +++ b/main.js @@ -423,6 +423,25 @@ Source at https://github.com/toji/spookyball sources: [], }; +var textRenderingMsdf = { + name: 'Text Rendering - MSDF', + description: `This example uses multichannel signed distance fields (MSDF) to render text. MSDF +fonts are more complex to implement than using Canvas 2D to generate text, but the resulting +text looks smoother while using less memory than the Canvas 2D approach, especially at high +zoom levels. They can be used to render larger amounts of text efficiently. + +The font texture is generated using [Don McCurdy's MSDF font generation tool](https://msdf-bmfont.donmccurdy.com/)`, + filename: "sample/textRenderingMsdf", + sources: [ + { path: 'main.ts' }, + { path: 'msdfText.ts' }, + { path: 'msdfText.wgsl' }, + { path: '../../shaders/basic.vert.wgsl' }, + { path: '../../shaders/vertexPositionColor.frag.wgsl' }, + { path: '../../meshes/cube.ts' }, + ], +}; + var texturedCube = { name: 'Textured Cube', description: 'This example shows how to bind and sample textures.', @@ -536,6 +555,7 @@ const pageCategories = [ cornell, 'a-buffer': aBuffer, skinnedMesh, + textRenderingMsdf, }, }, // Samples that demonstrate how to integrate WebGPU and/or WebGPU render operations with other diff --git a/main.js.map b/main.js.map index 266fcc7f..d00c3be6 100644 --- a/main.js.map +++ b/main.js.map @@ -1 +1 @@ -{"version":3,"file":"main.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"} \ No newline at end of file +{"version":3,"file":"main.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"} \ No newline at end of file diff --git a/sample/textRenderingMsdf/index.html b/sample/textRenderingMsdf/index.html new file mode 100644 index 00000000..5c58503b --- /dev/null +++ b/sample/textRenderingMsdf/index.html @@ -0,0 +1,27 @@ + + + + + + webgpu-samples: textRenderingMsdf + + + + + + + + diff --git a/sample/textRenderingMsdf/main.js b/sample/textRenderingMsdf/main.js new file mode 100644 index 00000000..369083bc --- /dev/null +++ b/sample/textRenderingMsdf/main.js @@ -0,0 +1,3193 @@ +/* wgpu-matrix@2.5.1, license MIT */ +/* + * Copyright 2022 Gregg Tavares + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +let EPSILON = 0.000001; + +/* + * Copyright 2022 Gregg Tavares + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +/** + * + * Vec3 math functions. + * + * Almost all functions take an optional `dst` argument. If it is not passed in the + * functions will create a new `Vec3`. In other words you can do this + * + * const v = vec3.cross(v1, v2); // Creates a new Vec3 with the cross product of v1 x v2. + * + * or + * + * const v = vec3.create(); + * vec3.cross(v1, v2, v); // Puts the cross product of v1 x v2 in v + * + * The first style is often easier but depending on where it's used it generates garbage where + * as there is almost never allocation with the second style. + * + * It is always safe to pass any vector as the destination. So for example + * + * vec3.cross(v1, v2, v1); // Puts the cross product of v1 x v2 in v1 + * + */ +let VecType$1 = Float32Array; +/** + * Sets the type this library creates for a Vec3 + * @param ctor - the constructor for the type. Either `Float32Array`, `Float64Array`, or `Array` + * @returns previous constructor for Vec3 + */ +function setDefaultType$5(ctor) { + const oldType = VecType$1; + VecType$1 = ctor; + return oldType; +} +/** + * Creates a vec3; may be called with x, y, z to set initial values. + * @param x - Initial x value. + * @param y - Initial y value. + * @param z - Initial z value. + * @returns the created vector + */ +function create$4(x, y, z) { + const dst = new VecType$1(3); + if (x !== undefined) { + dst[0] = x; + if (y !== undefined) { + dst[1] = y; + if (z !== undefined) { + dst[2] = z; + } + } + } + return dst; +} +// This mess is because with Mat3 we have 3 unused elements. +// For Float32Array and Float64Array that's not an issue +// but for Array it's troublesome +const ctorMap = new Map([ + [Float32Array, () => new Float32Array(12)], + [Float64Array, () => new Float64Array(12)], + [Array, () => new Array(12).fill(0)], +]); +ctorMap.get(Float32Array); + +/* + * Copyright 2022 Gregg Tavares + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +/** + * Creates a vec3; may be called with x, y, z to set initial values. (same as create) + * @param x - Initial x value. + * @param y - Initial y value. + * @param z - Initial z value. + * @returns the created vector + */ +const fromValues$2 = create$4; +/** + * Sets the values of a Vec3 + * Also see {@link vec3.create} and {@link vec3.copy} + * + * @param x first value + * @param y second value + * @param z third value + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns A vector with its elements set. + */ +function set$3(x, y, z, dst) { + dst = dst || new VecType$1(3); + dst[0] = x; + dst[1] = y; + dst[2] = z; + return dst; +} +/** + * Applies Math.ceil to each element of vector + * @param v - Operand vector. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns A vector that is the ceil of each element of v. + */ +function ceil$1(v, dst) { + dst = dst || new VecType$1(3); + dst[0] = Math.ceil(v[0]); + dst[1] = Math.ceil(v[1]); + dst[2] = Math.ceil(v[2]); + return dst; +} +/** + * Applies Math.floor to each element of vector + * @param v - Operand vector. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns A vector that is the floor of each element of v. + */ +function floor$1(v, dst) { + dst = dst || new VecType$1(3); + dst[0] = Math.floor(v[0]); + dst[1] = Math.floor(v[1]); + dst[2] = Math.floor(v[2]); + return dst; +} +/** + * Applies Math.round to each element of vector + * @param v - Operand vector. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns A vector that is the round of each element of v. + */ +function round$1(v, dst) { + dst = dst || new VecType$1(3); + dst[0] = Math.round(v[0]); + dst[1] = Math.round(v[1]); + dst[2] = Math.round(v[2]); + return dst; +} +/** + * Clamp each element of vector between min and max + * @param v - Operand vector. + * @param max - Min value, default 0 + * @param min - Max value, default 1 + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns A vector that the clamped value of each element of v. + */ +function clamp$1(v, min = 0, max = 1, dst) { + dst = dst || new VecType$1(3); + dst[0] = Math.min(max, Math.max(min, v[0])); + dst[1] = Math.min(max, Math.max(min, v[1])); + dst[2] = Math.min(max, Math.max(min, v[2])); + return dst; +} +/** + * Adds two vectors; assumes a and b have the same dimension. + * @param a - Operand vector. + * @param b - Operand vector. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns A vector that is the sum of a and b. + */ +function add$2(a, b, dst) { + dst = dst || new VecType$1(3); + dst[0] = a[0] + b[0]; + dst[1] = a[1] + b[1]; + dst[2] = a[2] + b[2]; + return dst; +} +/** + * Adds two vectors, scaling the 2nd; assumes a and b have the same dimension. + * @param a - Operand vector. + * @param b - Operand vector. + * @param scale - Amount to scale b + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns A vector that is the sum of a + b * scale. + */ +function addScaled$1(a, b, scale, dst) { + dst = dst || new VecType$1(3); + dst[0] = a[0] + b[0] * scale; + dst[1] = a[1] + b[1] * scale; + dst[2] = a[2] + b[2] * scale; + return dst; +} +/** + * Returns the angle in radians between two vectors. + * @param a - Operand vector. + * @param b - Operand vector. + * @returns The angle in radians between the 2 vectors. + */ +function angle$1(a, b) { + const ax = a[0]; + const ay = a[1]; + const az = a[2]; + const bx = a[0]; + const by = a[1]; + const bz = a[2]; + const mag1 = Math.sqrt(ax * ax + ay * ay + az * az); + const mag2 = Math.sqrt(bx * bx + by * by + bz * bz); + const mag = mag1 * mag2; + const cosine = mag && dot$2(a, b) / mag; + return Math.acos(cosine); +} +/** + * Subtracts two vectors. + * @param a - Operand vector. + * @param b - Operand vector. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns A vector that is the difference of a and b. + */ +function subtract$2(a, b, dst) { + dst = dst || new VecType$1(3); + dst[0] = a[0] - b[0]; + dst[1] = a[1] - b[1]; + dst[2] = a[2] - b[2]; + return dst; +} +/** + * Subtracts two vectors. + * @param a - Operand vector. + * @param b - Operand vector. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns A vector that is the difference of a and b. + */ +const sub$2 = subtract$2; +/** + * Check if 2 vectors are approximately equal + * @param a - Operand vector. + * @param b - Operand vector. + * @returns true if vectors are approximately equal + */ +function equalsApproximately$3(a, b) { + return Math.abs(a[0] - b[0]) < EPSILON && + Math.abs(a[1] - b[1]) < EPSILON && + Math.abs(a[2] - b[2]) < EPSILON; +} +/** + * Check if 2 vectors are exactly equal + * @param a - Operand vector. + * @param b - Operand vector. + * @returns true if vectors are exactly equal + */ +function equals$3(a, b) { + return a[0] === b[0] && a[1] === b[1] && a[2] === b[2]; +} +/** + * Performs linear interpolation on two vectors. + * Given vectors a and b and interpolation coefficient t, returns + * a + t * (b - a). + * @param a - Operand vector. + * @param b - Operand vector. + * @param t - Interpolation coefficient. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns The linear interpolated result. + */ +function lerp$2(a, b, t, dst) { + dst = dst || new VecType$1(3); + dst[0] = a[0] + t * (b[0] - a[0]); + dst[1] = a[1] + t * (b[1] - a[1]); + dst[2] = a[2] + t * (b[2] - a[2]); + return dst; +} +/** + * Performs linear interpolation on two vectors. + * Given vectors a and b and interpolation coefficient vector t, returns + * a + t * (b - a). + * @param a - Operand vector. + * @param b - Operand vector. + * @param t - Interpolation coefficients vector. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns the linear interpolated result. + */ +function lerpV$1(a, b, t, dst) { + dst = dst || new VecType$1(3); + dst[0] = a[0] + t[0] * (b[0] - a[0]); + dst[1] = a[1] + t[1] * (b[1] - a[1]); + dst[2] = a[2] + t[2] * (b[2] - a[2]); + return dst; +} +/** + * Return max values of two vectors. + * Given vectors a and b returns + * [max(a[0], b[0]), max(a[1], b[1]), max(a[2], b[2])]. + * @param a - Operand vector. + * @param b - Operand vector. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns The max components vector. + */ +function max$1(a, b, dst) { + dst = dst || new VecType$1(3); + dst[0] = Math.max(a[0], b[0]); + dst[1] = Math.max(a[1], b[1]); + dst[2] = Math.max(a[2], b[2]); + return dst; +} +/** + * Return min values of two vectors. + * Given vectors a and b returns + * [min(a[0], b[0]), min(a[1], b[1]), min(a[2], b[2])]. + * @param a - Operand vector. + * @param b - Operand vector. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns The min components vector. + */ +function min$1(a, b, dst) { + dst = dst || new VecType$1(3); + dst[0] = Math.min(a[0], b[0]); + dst[1] = Math.min(a[1], b[1]); + dst[2] = Math.min(a[2], b[2]); + return dst; +} +/** + * Multiplies a vector by a scalar. + * @param v - The vector. + * @param k - The scalar. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns The scaled vector. + */ +function mulScalar$2(v, k, dst) { + dst = dst || new VecType$1(3); + dst[0] = v[0] * k; + dst[1] = v[1] * k; + dst[2] = v[2] * k; + return dst; +} +/** + * Multiplies a vector by a scalar. (same as mulScalar) + * @param v - The vector. + * @param k - The scalar. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns The scaled vector. + */ +const scale$3 = mulScalar$2; +/** + * Divides a vector by a scalar. + * @param v - The vector. + * @param k - The scalar. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns The scaled vector. + */ +function divScalar$2(v, k, dst) { + dst = dst || new VecType$1(3); + dst[0] = v[0] / k; + dst[1] = v[1] / k; + dst[2] = v[2] / k; + return dst; +} +/** + * Inverse a vector. + * @param v - The vector. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns The inverted vector. + */ +function inverse$3(v, dst) { + dst = dst || new VecType$1(3); + dst[0] = 1 / v[0]; + dst[1] = 1 / v[1]; + dst[2] = 1 / v[2]; + return dst; +} +/** + * Invert a vector. (same as inverse) + * @param v - The vector. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns The inverted vector. + */ +const invert$2 = inverse$3; +/** + * Computes the cross product of two vectors; assumes both vectors have + * three entries. + * @param a - Operand vector. + * @param b - Operand vector. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns The vector of a cross b. + */ +function cross(a, b, dst) { + dst = dst || new VecType$1(3); + const t1 = a[2] * b[0] - a[0] * b[2]; + const t2 = a[0] * b[1] - a[1] * b[0]; + dst[0] = a[1] * b[2] - a[2] * b[1]; + dst[1] = t1; + dst[2] = t2; + return dst; +} +/** + * Computes the dot product of two vectors; assumes both vectors have + * three entries. + * @param a - Operand vector. + * @param b - Operand vector. + * @returns dot product + */ +function dot$2(a, b) { + return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]); +} +/** + * Computes the length of vector + * @param v - vector. + * @returns length of vector. + */ +function length$2(v) { + const v0 = v[0]; + const v1 = v[1]; + const v2 = v[2]; + return Math.sqrt(v0 * v0 + v1 * v1 + v2 * v2); +} +/** + * Computes the length of vector (same as length) + * @param v - vector. + * @returns length of vector. + */ +const len$2 = length$2; +/** + * Computes the square of the length of vector + * @param v - vector. + * @returns square of the length of vector. + */ +function lengthSq$2(v) { + const v0 = v[0]; + const v1 = v[1]; + const v2 = v[2]; + return v0 * v0 + v1 * v1 + v2 * v2; +} +/** + * Computes the square of the length of vector (same as lengthSq) + * @param v - vector. + * @returns square of the length of vector. + */ +const lenSq$2 = lengthSq$2; +/** + * Computes the distance between 2 points + * @param a - vector. + * @param b - vector. + * @returns distance between a and b + */ +function distance$1(a, b) { + const dx = a[0] - b[0]; + const dy = a[1] - b[1]; + const dz = a[2] - b[2]; + return Math.sqrt(dx * dx + dy * dy + dz * dz); +} +/** + * Computes the distance between 2 points (same as distance) + * @param a - vector. + * @param b - vector. + * @returns distance between a and b + */ +const dist$1 = distance$1; +/** + * Computes the square of the distance between 2 points + * @param a - vector. + * @param b - vector. + * @returns square of the distance between a and b + */ +function distanceSq$1(a, b) { + const dx = a[0] - b[0]; + const dy = a[1] - b[1]; + const dz = a[2] - b[2]; + return dx * dx + dy * dy + dz * dz; +} +/** + * Computes the square of the distance between 2 points (same as distanceSq) + * @param a - vector. + * @param b - vector. + * @returns square of the distance between a and b + */ +const distSq$1 = distanceSq$1; +/** + * Divides a vector by its Euclidean length and returns the quotient. + * @param v - The vector. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns The normalized vector. + */ +function normalize$2(v, dst) { + dst = dst || new VecType$1(3); + const v0 = v[0]; + const v1 = v[1]; + const v2 = v[2]; + const len = Math.sqrt(v0 * v0 + v1 * v1 + v2 * v2); + if (len > 0.00001) { + dst[0] = v0 / len; + dst[1] = v1 / len; + dst[2] = v2 / len; + } + else { + dst[0] = 0; + dst[1] = 0; + dst[2] = 0; + } + return dst; +} +/** + * Negates a vector. + * @param v - The vector. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns -v. + */ +function negate$2(v, dst) { + dst = dst || new VecType$1(3); + dst[0] = -v[0]; + dst[1] = -v[1]; + dst[2] = -v[2]; + return dst; +} +/** + * Copies a vector. (same as {@link vec3.clone}) + * Also see {@link vec3.create} and {@link vec3.set} + * @param v - The vector. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns A copy of v. + */ +function copy$3(v, dst) { + dst = dst || new VecType$1(3); + dst[0] = v[0]; + dst[1] = v[1]; + dst[2] = v[2]; + return dst; +} +/** + * Clones a vector. (same as {@link vec3.copy}) + * Also see {@link vec3.create} and {@link vec3.set} + * @param v - The vector. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns A copy of v. + */ +const clone$3 = copy$3; +/** + * Multiplies a vector by another vector (component-wise); assumes a and + * b have the same length. + * @param a - Operand vector. + * @param b - Operand vector. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns The vector of products of entries of a and b. + */ +function multiply$3(a, b, dst) { + dst = dst || new VecType$1(3); + dst[0] = a[0] * b[0]; + dst[1] = a[1] * b[1]; + dst[2] = a[2] * b[2]; + return dst; +} +/** + * Multiplies a vector by another vector (component-wise); assumes a and + * b have the same length. (same as mul) + * @param a - Operand vector. + * @param b - Operand vector. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns The vector of products of entries of a and b. + */ +const mul$3 = multiply$3; +/** + * Divides a vector by another vector (component-wise); assumes a and + * b have the same length. + * @param a - Operand vector. + * @param b - Operand vector. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns The vector of quotients of entries of a and b. + */ +function divide$1(a, b, dst) { + dst = dst || new VecType$1(3); + dst[0] = a[0] / b[0]; + dst[1] = a[1] / b[1]; + dst[2] = a[2] / b[2]; + return dst; +} +/** + * Divides a vector by another vector (component-wise); assumes a and + * b have the same length. (same as divide) + * @param a - Operand vector. + * @param b - Operand vector. + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns The vector of quotients of entries of a and b. + */ +const div$1 = divide$1; +/** + * Creates a random vector + * @param scale - Default 1 + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns The random vector. + */ +function random(scale = 1, dst) { + dst = dst || new VecType$1(3); + const angle = Math.random() * 2 * Math.PI; + const z = Math.random() * 2 - 1; + const zScale = Math.sqrt(1 - z * z) * scale; + dst[0] = Math.cos(angle) * zScale; + dst[1] = Math.sin(angle) * zScale; + dst[2] = z * scale; + return dst; +} +/** + * Zero's a vector + * @param dst - vector to hold result. If not passed in a new one is created. + * @returns The zeroed vector. + */ +function zero$1(dst) { + dst = dst || new VecType$1(3); + dst[0] = 0; + dst[1] = 0; + dst[2] = 0; + return dst; +} +/** + * transform vec3 by 4x4 matrix + * @param v - the vector + * @param m - The matrix. + * @param dst - optional vec3 to store result. If not passed a new one is created. + * @returns the transformed vector + */ +function transformMat4$1(v, m, dst) { + dst = dst || new VecType$1(3); + const x = v[0]; + const y = v[1]; + const z = v[2]; + const w = (m[3] * x + m[7] * y + m[11] * z + m[15]) || 1; + dst[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w; + dst[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w; + dst[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w; + return dst; +} +/** + * Transform vec4 by upper 3x3 matrix inside 4x4 matrix. + * @param v - The direction. + * @param m - The matrix. + * @param dst - optional Vec3 to store result. If not passed a new one is created. + * @returns The transformed vector. + */ +function transformMat4Upper3x3(v, m, dst) { + dst = dst || new VecType$1(3); + const v0 = v[0]; + const v1 = v[1]; + const v2 = v[2]; + dst[0] = v0 * m[0 * 4 + 0] + v1 * m[1 * 4 + 0] + v2 * m[2 * 4 + 0]; + dst[1] = v0 * m[0 * 4 + 1] + v1 * m[1 * 4 + 1] + v2 * m[2 * 4 + 1]; + dst[2] = v0 * m[0 * 4 + 2] + v1 * m[1 * 4 + 2] + v2 * m[2 * 4 + 2]; + return dst; +} +/** + * Transforms vec3 by 3x3 matrix + * + * @param v - the vector + * @param m - The matrix. + * @param dst - optional vec3 to store result. If not passed a new one is created. + * @returns the transformed vector + */ +function transformMat3(v, m, dst) { + dst = dst || new VecType$1(3); + const x = v[0]; + const y = v[1]; + const z = v[2]; + dst[0] = x * m[0] + y * m[4] + z * m[8]; + dst[1] = x * m[1] + y * m[5] + z * m[9]; + dst[2] = x * m[2] + y * m[6] + z * m[10]; + return dst; +} +/** + * Transforms vec3 by Quaternion + * @param v - the vector to transform + * @param q - the quaternion to transform by + * @param dst - optional vec3 to store result. If not passed a new one is created. + * @returns the transformed + */ +function transformQuat(v, q, dst) { + dst = dst || new VecType$1(3); + const qx = q[0]; + const qy = q[1]; + const qz = q[2]; + const w2 = q[3] * 2; + const x = v[0]; + const y = v[1]; + const z = v[2]; + const uvX = qy * z - qz * y; + const uvY = qz * x - qx * z; + const uvZ = qx * y - qy * x; + dst[0] = x + uvX * w2 + (qy * uvZ - qz * uvY) * 2; + dst[1] = y + uvY * w2 + (qz * uvX - qx * uvZ) * 2; + dst[2] = z + uvZ * w2 + (qx * uvY - qy * uvX) * 2; + return dst; +} +/** + * Returns the translation component of a 4-by-4 matrix as a vector with 3 + * entries. + * @param m - The matrix. + * @param dst - vector to hold result. If not passed a new one is created. + * @returns The translation component of m. + */ +function getTranslation$1(m, dst) { + dst = dst || new VecType$1(3); + dst[0] = m[12]; + dst[1] = m[13]; + dst[2] = m[14]; + return dst; +} +/** + * Returns an axis of a 4x4 matrix as a vector with 3 entries + * @param m - The matrix. + * @param axis - The axis 0 = x, 1 = y, 2 = z; + * @returns The axis component of m. + */ +function getAxis$1(m, axis, dst) { + dst = dst || new VecType$1(3); + const off = axis * 4; + dst[0] = m[off + 0]; + dst[1] = m[off + 1]; + dst[2] = m[off + 2]; + return dst; +} +/** + * Returns the scaling component of the matrix + * @param m - The Matrix + * @param dst - The vector to set. If not passed a new one is created. + */ +function getScaling$1(m, dst) { + dst = dst || new VecType$1(3); + const xx = m[0]; + const xy = m[1]; + const xz = m[2]; + const yx = m[4]; + const yy = m[5]; + const yz = m[6]; + const zx = m[8]; + const zy = m[9]; + const zz = m[10]; + dst[0] = Math.sqrt(xx * xx + xy * xy + xz * xz); + dst[1] = Math.sqrt(yx * yx + yy * yy + yz * yz); + dst[2] = Math.sqrt(zx * zx + zy * zy + zz * zz); + return dst; +} + +var vec3Impl = /*#__PURE__*/Object.freeze({ + __proto__: null, + create: create$4, + setDefaultType: setDefaultType$5, + fromValues: fromValues$2, + set: set$3, + ceil: ceil$1, + floor: floor$1, + round: round$1, + clamp: clamp$1, + add: add$2, + addScaled: addScaled$1, + angle: angle$1, + subtract: subtract$2, + sub: sub$2, + equalsApproximately: equalsApproximately$3, + equals: equals$3, + lerp: lerp$2, + lerpV: lerpV$1, + max: max$1, + min: min$1, + mulScalar: mulScalar$2, + scale: scale$3, + divScalar: divScalar$2, + inverse: inverse$3, + invert: invert$2, + cross: cross, + dot: dot$2, + length: length$2, + len: len$2, + lengthSq: lengthSq$2, + lenSq: lenSq$2, + distance: distance$1, + dist: dist$1, + distanceSq: distanceSq$1, + distSq: distSq$1, + normalize: normalize$2, + negate: negate$2, + copy: copy$3, + clone: clone$3, + multiply: multiply$3, + mul: mul$3, + divide: divide$1, + div: div$1, + random: random, + zero: zero$1, + transformMat4: transformMat4$1, + transformMat4Upper3x3: transformMat4Upper3x3, + transformMat3: transformMat3, + transformQuat: transformQuat, + getTranslation: getTranslation$1, + getAxis: getAxis$1, + getScaling: getScaling$1 +}); + +/** + * 4x4 Matrix math math functions. + * + * Almost all functions take an optional `dst` argument. If it is not passed in the + * functions will create a new matrix. In other words you can do this + * + * const mat = mat4.translation([1, 2, 3]); // Creates a new translation matrix + * + * or + * + * const mat = mat4.create(); + * mat4.translation([1, 2, 3], mat); // Puts translation matrix in mat. + * + * The first style is often easier but depending on where it's used it generates garbage where + * as there is almost never allocation with the second style. + * + * It is always save to pass any matrix as the destination. So for example + * + * const mat = mat4.identity(); + * const trans = mat4.translation([1, 2, 3]); + * mat4.multiply(mat, trans, mat); // Multiplies mat * trans and puts result in mat. + * + */ +let MatType = Float32Array; +/** + * Sets the type this library creates for a Mat4 + * @param ctor - the constructor for the type. Either `Float32Array`, `Float64Array`, or `Array` + * @returns previous constructor for Mat4 + */ +function setDefaultType$3(ctor) { + const oldType = MatType; + MatType = ctor; + return oldType; +} +/** + * Create a Mat4 from values + * + * Note: Since passing in a raw JavaScript array + * is valid in all circumstances, if you want to + * force a JavaScript array into a Mat4's specified type + * it would be faster to use + * + * ``` + * const m = mat4.clone(someJSArray); + * ``` + * + * Note: a consequence of the implementation is if your Mat4Type = `Array` + * instead of `Float32Array` or `Float64Array` then any values you + * don't pass in will be undefined. Usually this is not an issue since + * (a) using `Array` is rare and (b) using `mat4.create` is usually used + * to create a Mat4 to be filled out as in + * + * ``` + * const m = mat4.create(); + * mat4.perspective(fov, aspect, near, far, m); + * ``` + * + * @param v0 - value for element 0 + * @param v1 - value for element 1 + * @param v2 - value for element 2 + * @param v3 - value for element 3 + * @param v4 - value for element 4 + * @param v5 - value for element 5 + * @param v6 - value for element 6 + * @param v7 - value for element 7 + * @param v8 - value for element 8 + * @param v9 - value for element 9 + * @param v10 - value for element 10 + * @param v11 - value for element 11 + * @param v12 - value for element 12 + * @param v13 - value for element 13 + * @param v14 - value for element 14 + * @param v15 - value for element 15 + * @returns created from values. + */ +function create$2(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) { + const dst = new MatType(16); + if (v0 !== undefined) { + dst[0] = v0; + if (v1 !== undefined) { + dst[1] = v1; + if (v2 !== undefined) { + dst[2] = v2; + if (v3 !== undefined) { + dst[3] = v3; + if (v4 !== undefined) { + dst[4] = v4; + if (v5 !== undefined) { + dst[5] = v5; + if (v6 !== undefined) { + dst[6] = v6; + if (v7 !== undefined) { + dst[7] = v7; + if (v8 !== undefined) { + dst[8] = v8; + if (v9 !== undefined) { + dst[9] = v9; + if (v10 !== undefined) { + dst[10] = v10; + if (v11 !== undefined) { + dst[11] = v11; + if (v12 !== undefined) { + dst[12] = v12; + if (v13 !== undefined) { + dst[13] = v13; + if (v14 !== undefined) { + dst[14] = v14; + if (v15 !== undefined) { + dst[15] = v15; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + return dst; +} +/** + * Sets the values of a Mat4 + * Also see {@link mat4.create} and {@link mat4.copy} + * + * @param v0 - value for element 0 + * @param v1 - value for element 1 + * @param v2 - value for element 2 + * @param v3 - value for element 3 + * @param v4 - value for element 4 + * @param v5 - value for element 5 + * @param v6 - value for element 6 + * @param v7 - value for element 7 + * @param v8 - value for element 8 + * @param v9 - value for element 9 + * @param v10 - value for element 10 + * @param v11 - value for element 11 + * @param v12 - value for element 12 + * @param v13 - value for element 13 + * @param v14 - value for element 14 + * @param v15 - value for element 15 + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns Mat4 created from values. + */ +function set$2(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, dst) { + dst = dst || new MatType(16); + dst[0] = v0; + dst[1] = v1; + dst[2] = v2; + dst[3] = v3; + dst[4] = v4; + dst[5] = v5; + dst[6] = v6; + dst[7] = v7; + dst[8] = v8; + dst[9] = v9; + dst[10] = v10; + dst[11] = v11; + dst[12] = v12; + dst[13] = v13; + dst[14] = v14; + dst[15] = v15; + return dst; +} +/** + * Creates a Mat4 from a Mat3 + * @param m3 - source matrix + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns Mat4 made from m3 + */ +function fromMat3(m3, dst) { + dst = dst || new MatType(16); + dst[0] = m3[0]; + dst[1] = m3[1]; + dst[2] = m3[2]; + dst[3] = 0; + dst[4] = m3[4]; + dst[5] = m3[5]; + dst[6] = m3[6]; + dst[7] = 0; + dst[8] = m3[8]; + dst[9] = m3[9]; + dst[10] = m3[10]; + dst[11] = 0; + dst[12] = 0; + dst[13] = 0; + dst[14] = 0; + dst[15] = 1; + return dst; +} +/** + * Creates a Mat4 rotation matrix from a quaternion + * @param q - quaternion to create matrix from + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns Mat4 made from q + */ +function fromQuat(q, dst) { + dst = dst || new MatType(16); + const x = q[0]; + const y = q[1]; + const z = q[2]; + const w = q[3]; + const x2 = x + x; + const y2 = y + y; + const z2 = z + z; + const xx = x * x2; + const yx = y * x2; + const yy = y * y2; + const zx = z * x2; + const zy = z * y2; + const zz = z * z2; + const wx = w * x2; + const wy = w * y2; + const wz = w * z2; + dst[0] = 1 - yy - zz; + dst[1] = yx + wz; + dst[2] = zx - wy; + dst[3] = 0; + dst[4] = yx - wz; + dst[5] = 1 - xx - zz; + dst[6] = zy + wx; + dst[7] = 0; + dst[8] = zx + wy; + dst[9] = zy - wx; + dst[10] = 1 - xx - yy; + dst[11] = 0; + dst[12] = 0; + dst[13] = 0; + dst[14] = 0; + dst[15] = 1; + return dst; +} +/** + * Negates a matrix. + * @param m - The matrix. + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns -m. + */ +function negate$1(m, dst) { + dst = dst || new MatType(16); + dst[0] = -m[0]; + dst[1] = -m[1]; + dst[2] = -m[2]; + dst[3] = -m[3]; + dst[4] = -m[4]; + dst[5] = -m[5]; + dst[6] = -m[6]; + dst[7] = -m[7]; + dst[8] = -m[8]; + dst[9] = -m[9]; + dst[10] = -m[10]; + dst[11] = -m[11]; + dst[12] = -m[12]; + dst[13] = -m[13]; + dst[14] = -m[14]; + dst[15] = -m[15]; + return dst; +} +/** + * Copies a matrix. (same as {@link mat4.clone}) + * Also see {@link mat4.create} and {@link mat4.set} + * @param m - The matrix. + * @param dst - The matrix. If not passed a new one is created. + * @returns A copy of m. + */ +function copy$2(m, dst) { + dst = dst || new MatType(16); + dst[0] = m[0]; + dst[1] = m[1]; + dst[2] = m[2]; + dst[3] = m[3]; + dst[4] = m[4]; + dst[5] = m[5]; + dst[6] = m[6]; + dst[7] = m[7]; + dst[8] = m[8]; + dst[9] = m[9]; + dst[10] = m[10]; + dst[11] = m[11]; + dst[12] = m[12]; + dst[13] = m[13]; + dst[14] = m[14]; + dst[15] = m[15]; + return dst; +} +/** + * Copies a matrix (same as {@link mat4.copy}) + * Also see {@link mat4.create} and {@link mat4.set} + * @param m - The matrix. + * @param dst - The matrix. If not passed a new one is created. + * @returns A copy of m. + */ +const clone$2 = copy$2; +/** + * Check if 2 matrices are approximately equal + * @param a - Operand matrix. + * @param b - Operand matrix. + * @returns true if matrices are approximately equal + */ +function equalsApproximately$2(a, b) { + return Math.abs(a[0] - b[0]) < EPSILON && + Math.abs(a[1] - b[1]) < EPSILON && + Math.abs(a[2] - b[2]) < EPSILON && + Math.abs(a[3] - b[3]) < EPSILON && + Math.abs(a[4] - b[4]) < EPSILON && + Math.abs(a[5] - b[5]) < EPSILON && + Math.abs(a[6] - b[6]) < EPSILON && + Math.abs(a[7] - b[7]) < EPSILON && + Math.abs(a[8] - b[8]) < EPSILON && + Math.abs(a[9] - b[9]) < EPSILON && + Math.abs(a[10] - b[10]) < EPSILON && + Math.abs(a[11] - b[11]) < EPSILON && + Math.abs(a[12] - b[12]) < EPSILON && + Math.abs(a[13] - b[13]) < EPSILON && + Math.abs(a[14] - b[14]) < EPSILON && + Math.abs(a[15] - b[15]) < EPSILON; +} +/** + * Check if 2 matrices are exactly equal + * @param a - Operand matrix. + * @param b - Operand matrix. + * @returns true if matrices are exactly equal + */ +function equals$2(a, b) { + return a[0] === b[0] && + a[1] === b[1] && + a[2] === b[2] && + a[3] === b[3] && + a[4] === b[4] && + a[5] === b[5] && + a[6] === b[6] && + a[7] === b[7] && + a[8] === b[8] && + a[9] === b[9] && + a[10] === b[10] && + a[11] === b[11] && + a[12] === b[12] && + a[13] === b[13] && + a[14] === b[14] && + a[15] === b[15]; +} +/** + * Creates a 4-by-4 identity matrix. + * + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns A 4-by-4 identity matrix. + */ +function identity$1(dst) { + dst = dst || new MatType(16); + dst[0] = 1; + dst[1] = 0; + dst[2] = 0; + dst[3] = 0; + dst[4] = 0; + dst[5] = 1; + dst[6] = 0; + dst[7] = 0; + dst[8] = 0; + dst[9] = 0; + dst[10] = 1; + dst[11] = 0; + dst[12] = 0; + dst[13] = 0; + dst[14] = 0; + dst[15] = 1; + return dst; +} +/** + * Takes the transpose of a matrix. + * @param m - The matrix. + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The transpose of m. + */ +function transpose(m, dst) { + dst = dst || new MatType(16); + if (dst === m) { + let t; + t = m[1]; + m[1] = m[4]; + m[4] = t; + t = m[2]; + m[2] = m[8]; + m[8] = t; + t = m[3]; + m[3] = m[12]; + m[12] = t; + t = m[6]; + m[6] = m[9]; + m[9] = t; + t = m[7]; + m[7] = m[13]; + m[13] = t; + t = m[11]; + m[11] = m[14]; + m[14] = t; + return dst; + } + const m00 = m[0 * 4 + 0]; + const m01 = m[0 * 4 + 1]; + const m02 = m[0 * 4 + 2]; + const m03 = m[0 * 4 + 3]; + const m10 = m[1 * 4 + 0]; + const m11 = m[1 * 4 + 1]; + const m12 = m[1 * 4 + 2]; + const m13 = m[1 * 4 + 3]; + const m20 = m[2 * 4 + 0]; + const m21 = m[2 * 4 + 1]; + const m22 = m[2 * 4 + 2]; + const m23 = m[2 * 4 + 3]; + const m30 = m[3 * 4 + 0]; + const m31 = m[3 * 4 + 1]; + const m32 = m[3 * 4 + 2]; + const m33 = m[3 * 4 + 3]; + dst[0] = m00; + dst[1] = m10; + dst[2] = m20; + dst[3] = m30; + dst[4] = m01; + dst[5] = m11; + dst[6] = m21; + dst[7] = m31; + dst[8] = m02; + dst[9] = m12; + dst[10] = m22; + dst[11] = m32; + dst[12] = m03; + dst[13] = m13; + dst[14] = m23; + dst[15] = m33; + return dst; +} +/** + * Computes the inverse of a 4-by-4 matrix. + * @param m - The matrix. + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The inverse of m. + */ +function inverse$2(m, dst) { + dst = dst || new MatType(16); + const m00 = m[0 * 4 + 0]; + const m01 = m[0 * 4 + 1]; + const m02 = m[0 * 4 + 2]; + const m03 = m[0 * 4 + 3]; + const m10 = m[1 * 4 + 0]; + const m11 = m[1 * 4 + 1]; + const m12 = m[1 * 4 + 2]; + const m13 = m[1 * 4 + 3]; + const m20 = m[2 * 4 + 0]; + const m21 = m[2 * 4 + 1]; + const m22 = m[2 * 4 + 2]; + const m23 = m[2 * 4 + 3]; + const m30 = m[3 * 4 + 0]; + const m31 = m[3 * 4 + 1]; + const m32 = m[3 * 4 + 2]; + const m33 = m[3 * 4 + 3]; + const tmp0 = m22 * m33; + const tmp1 = m32 * m23; + const tmp2 = m12 * m33; + const tmp3 = m32 * m13; + const tmp4 = m12 * m23; + const tmp5 = m22 * m13; + const tmp6 = m02 * m33; + const tmp7 = m32 * m03; + const tmp8 = m02 * m23; + const tmp9 = m22 * m03; + const tmp10 = m02 * m13; + const tmp11 = m12 * m03; + const tmp12 = m20 * m31; + const tmp13 = m30 * m21; + const tmp14 = m10 * m31; + const tmp15 = m30 * m11; + const tmp16 = m10 * m21; + const tmp17 = m20 * m11; + const tmp18 = m00 * m31; + const tmp19 = m30 * m01; + const tmp20 = m00 * m21; + const tmp21 = m20 * m01; + const tmp22 = m00 * m11; + const tmp23 = m10 * m01; + const t0 = (tmp0 * m11 + tmp3 * m21 + tmp4 * m31) - + (tmp1 * m11 + tmp2 * m21 + tmp5 * m31); + const t1 = (tmp1 * m01 + tmp6 * m21 + tmp9 * m31) - + (tmp0 * m01 + tmp7 * m21 + tmp8 * m31); + const t2 = (tmp2 * m01 + tmp7 * m11 + tmp10 * m31) - + (tmp3 * m01 + tmp6 * m11 + tmp11 * m31); + const t3 = (tmp5 * m01 + tmp8 * m11 + tmp11 * m21) - + (tmp4 * m01 + tmp9 * m11 + tmp10 * m21); + const d = 1 / (m00 * t0 + m10 * t1 + m20 * t2 + m30 * t3); + dst[0] = d * t0; + dst[1] = d * t1; + dst[2] = d * t2; + dst[3] = d * t3; + dst[4] = d * ((tmp1 * m10 + tmp2 * m20 + tmp5 * m30) - + (tmp0 * m10 + tmp3 * m20 + tmp4 * m30)); + dst[5] = d * ((tmp0 * m00 + tmp7 * m20 + tmp8 * m30) - + (tmp1 * m00 + tmp6 * m20 + tmp9 * m30)); + dst[6] = d * ((tmp3 * m00 + tmp6 * m10 + tmp11 * m30) - + (tmp2 * m00 + tmp7 * m10 + tmp10 * m30)); + dst[7] = d * ((tmp4 * m00 + tmp9 * m10 + tmp10 * m20) - + (tmp5 * m00 + tmp8 * m10 + tmp11 * m20)); + dst[8] = d * ((tmp12 * m13 + tmp15 * m23 + tmp16 * m33) - + (tmp13 * m13 + tmp14 * m23 + tmp17 * m33)); + dst[9] = d * ((tmp13 * m03 + tmp18 * m23 + tmp21 * m33) - + (tmp12 * m03 + tmp19 * m23 + tmp20 * m33)); + dst[10] = d * ((tmp14 * m03 + tmp19 * m13 + tmp22 * m33) - + (tmp15 * m03 + tmp18 * m13 + tmp23 * m33)); + dst[11] = d * ((tmp17 * m03 + tmp20 * m13 + tmp23 * m23) - + (tmp16 * m03 + tmp21 * m13 + tmp22 * m23)); + dst[12] = d * ((tmp14 * m22 + tmp17 * m32 + tmp13 * m12) - + (tmp16 * m32 + tmp12 * m12 + tmp15 * m22)); + dst[13] = d * ((tmp20 * m32 + tmp12 * m02 + tmp19 * m22) - + (tmp18 * m22 + tmp21 * m32 + tmp13 * m02)); + dst[14] = d * ((tmp18 * m12 + tmp23 * m32 + tmp15 * m02) - + (tmp22 * m32 + tmp14 * m02 + tmp19 * m12)); + dst[15] = d * ((tmp22 * m22 + tmp16 * m02 + tmp21 * m12) - + (tmp20 * m12 + tmp23 * m22 + tmp17 * m02)); + return dst; +} +/** + * Compute the determinant of a matrix + * @param m - the matrix + * @returns the determinant + */ +function determinant(m) { + const m00 = m[0 * 4 + 0]; + const m01 = m[0 * 4 + 1]; + const m02 = m[0 * 4 + 2]; + const m03 = m[0 * 4 + 3]; + const m10 = m[1 * 4 + 0]; + const m11 = m[1 * 4 + 1]; + const m12 = m[1 * 4 + 2]; + const m13 = m[1 * 4 + 3]; + const m20 = m[2 * 4 + 0]; + const m21 = m[2 * 4 + 1]; + const m22 = m[2 * 4 + 2]; + const m23 = m[2 * 4 + 3]; + const m30 = m[3 * 4 + 0]; + const m31 = m[3 * 4 + 1]; + const m32 = m[3 * 4 + 2]; + const m33 = m[3 * 4 + 3]; + const tmp0 = m22 * m33; + const tmp1 = m32 * m23; + const tmp2 = m12 * m33; + const tmp3 = m32 * m13; + const tmp4 = m12 * m23; + const tmp5 = m22 * m13; + const tmp6 = m02 * m33; + const tmp7 = m32 * m03; + const tmp8 = m02 * m23; + const tmp9 = m22 * m03; + const tmp10 = m02 * m13; + const tmp11 = m12 * m03; + const t0 = (tmp0 * m11 + tmp3 * m21 + tmp4 * m31) - + (tmp1 * m11 + tmp2 * m21 + tmp5 * m31); + const t1 = (tmp1 * m01 + tmp6 * m21 + tmp9 * m31) - + (tmp0 * m01 + tmp7 * m21 + tmp8 * m31); + const t2 = (tmp2 * m01 + tmp7 * m11 + tmp10 * m31) - + (tmp3 * m01 + tmp6 * m11 + tmp11 * m31); + const t3 = (tmp5 * m01 + tmp8 * m11 + tmp11 * m21) - + (tmp4 * m01 + tmp9 * m11 + tmp10 * m21); + return m00 * t0 + m10 * t1 + m20 * t2 + m30 * t3; +} +/** + * Computes the inverse of a 4-by-4 matrix. (same as inverse) + * @param m - The matrix. + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The inverse of m. + */ +const invert$1 = inverse$2; +/** + * Multiplies two 4-by-4 matrices with a on the left and b on the right + * @param a - The matrix on the left. + * @param b - The matrix on the right. + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The matrix product of a and b. + */ +function multiply$2(a, b, dst) { + dst = dst || new MatType(16); + const a00 = a[0]; + const a01 = a[1]; + const a02 = a[2]; + const a03 = a[3]; + const a10 = a[4 + 0]; + const a11 = a[4 + 1]; + const a12 = a[4 + 2]; + const a13 = a[4 + 3]; + const a20 = a[8 + 0]; + const a21 = a[8 + 1]; + const a22 = a[8 + 2]; + const a23 = a[8 + 3]; + const a30 = a[12 + 0]; + const a31 = a[12 + 1]; + const a32 = a[12 + 2]; + const a33 = a[12 + 3]; + const b00 = b[0]; + const b01 = b[1]; + const b02 = b[2]; + const b03 = b[3]; + const b10 = b[4 + 0]; + const b11 = b[4 + 1]; + const b12 = b[4 + 2]; + const b13 = b[4 + 3]; + const b20 = b[8 + 0]; + const b21 = b[8 + 1]; + const b22 = b[8 + 2]; + const b23 = b[8 + 3]; + const b30 = b[12 + 0]; + const b31 = b[12 + 1]; + const b32 = b[12 + 2]; + const b33 = b[12 + 3]; + dst[0] = a00 * b00 + a10 * b01 + a20 * b02 + a30 * b03; + dst[1] = a01 * b00 + a11 * b01 + a21 * b02 + a31 * b03; + dst[2] = a02 * b00 + a12 * b01 + a22 * b02 + a32 * b03; + dst[3] = a03 * b00 + a13 * b01 + a23 * b02 + a33 * b03; + dst[4] = a00 * b10 + a10 * b11 + a20 * b12 + a30 * b13; + dst[5] = a01 * b10 + a11 * b11 + a21 * b12 + a31 * b13; + dst[6] = a02 * b10 + a12 * b11 + a22 * b12 + a32 * b13; + dst[7] = a03 * b10 + a13 * b11 + a23 * b12 + a33 * b13; + dst[8] = a00 * b20 + a10 * b21 + a20 * b22 + a30 * b23; + dst[9] = a01 * b20 + a11 * b21 + a21 * b22 + a31 * b23; + dst[10] = a02 * b20 + a12 * b21 + a22 * b22 + a32 * b23; + dst[11] = a03 * b20 + a13 * b21 + a23 * b22 + a33 * b23; + dst[12] = a00 * b30 + a10 * b31 + a20 * b32 + a30 * b33; + dst[13] = a01 * b30 + a11 * b31 + a21 * b32 + a31 * b33; + dst[14] = a02 * b30 + a12 * b31 + a22 * b32 + a32 * b33; + dst[15] = a03 * b30 + a13 * b31 + a23 * b32 + a33 * b33; + return dst; +} +/** + * Multiplies two 4-by-4 matrices with a on the left and b on the right (same as multiply) + * @param a - The matrix on the left. + * @param b - The matrix on the right. + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The matrix product of a and b. + */ +const mul$2 = multiply$2; +/** + * Sets the translation component of a 4-by-4 matrix to the given + * vector. + * @param a - The matrix. + * @param v - The vector. + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The matrix with translation set. + */ +function setTranslation(a, v, dst) { + dst = dst || identity$1(); + if (a !== dst) { + dst[0] = a[0]; + dst[1] = a[1]; + dst[2] = a[2]; + dst[3] = a[3]; + dst[4] = a[4]; + dst[5] = a[5]; + dst[6] = a[6]; + dst[7] = a[7]; + dst[8] = a[8]; + dst[9] = a[9]; + dst[10] = a[10]; + dst[11] = a[11]; + } + dst[12] = v[0]; + dst[13] = v[1]; + dst[14] = v[2]; + dst[15] = 1; + return dst; +} +/** + * Returns the translation component of a 4-by-4 matrix as a vector with 3 + * entries. + * @param m - The matrix. + * @param dst - vector to hold result. If not passed a new one is created. + * @returns The translation component of m. + */ +function getTranslation(m, dst) { + dst = dst || create$4(); + dst[0] = m[12]; + dst[1] = m[13]; + dst[2] = m[14]; + return dst; +} +/** + * Returns an axis of a 4x4 matrix as a vector with 3 entries + * @param m - The matrix. + * @param axis - The axis 0 = x, 1 = y, 2 = z; + * @returns The axis component of m. + */ +function getAxis(m, axis, dst) { + dst = dst || create$4(); + const off = axis * 4; + dst[0] = m[off + 0]; + dst[1] = m[off + 1]; + dst[2] = m[off + 2]; + return dst; +} +/** + * Sets an axis of a 4x4 matrix as a vector with 3 entries + * @param m - The matrix. + * @param v - the axis vector + * @param axis - The axis 0 = x, 1 = y, 2 = z; + * @param dst - The matrix to set. If not passed a new one is created. + * @returns The matrix with axis set. + */ +function setAxis(a, v, axis, dst) { + if (dst !== a) { + dst = copy$2(a, dst); + } + const off = axis * 4; + dst[off + 0] = v[0]; + dst[off + 1] = v[1]; + dst[off + 2] = v[2]; + return dst; +} +/** + * Returns the scaling component of the matrix + * @param m - The Matrix + * @param dst - The vector to set. If not passed a new one is created. + */ +function getScaling(m, dst) { + dst = dst || create$4(); + const xx = m[0]; + const xy = m[1]; + const xz = m[2]; + const yx = m[4]; + const yy = m[5]; + const yz = m[6]; + const zx = m[8]; + const zy = m[9]; + const zz = m[10]; + dst[0] = Math.sqrt(xx * xx + xy * xy + xz * xz); + dst[1] = Math.sqrt(yx * yx + yy * yy + yz * yz); + dst[2] = Math.sqrt(zx * zx + zy * zy + zz * zz); + return dst; +} +/** + * Computes a 4-by-4 perspective transformation matrix given the angular height + * of the frustum, the aspect ratio, and the near and far clipping planes. The + * arguments define a frustum extending in the negative z direction. The given + * angle is the vertical angle of the frustum, and the horizontal angle is + * determined to produce the given aspect ratio. The arguments near and far are + * the distances to the near and far clipping planes. Note that near and far + * are not z coordinates, but rather they are distances along the negative + * z-axis. The matrix generated sends the viewing frustum to the unit box. + * We assume a unit box extending from -1 to 1 in the x and y dimensions and + * from 0 to 1 in the z dimension. + * + * Note: If you pass `Infinity` for zFar then it will produce a projection matrix + * returns -Infinity for Z when transforming coordinates with Z <= 0 and +Infinity for Z + * otherwise. + * + * @param fieldOfViewYInRadians - The camera angle from top to bottom (in radians). + * @param aspect - The aspect ratio width / height. + * @param zNear - The depth (negative z coordinate) + * of the near clipping plane. + * @param zFar - The depth (negative z coordinate) + * of the far clipping plane. + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The perspective matrix. + */ +function perspective(fieldOfViewYInRadians, aspect, zNear, zFar, dst) { + dst = dst || new MatType(16); + const f = Math.tan(Math.PI * 0.5 - 0.5 * fieldOfViewYInRadians); + dst[0] = f / aspect; + dst[1] = 0; + dst[2] = 0; + dst[3] = 0; + dst[4] = 0; + dst[5] = f; + dst[6] = 0; + dst[7] = 0; + dst[8] = 0; + dst[9] = 0; + dst[11] = -1; + dst[12] = 0; + dst[13] = 0; + dst[15] = 0; + if (zFar === Infinity) { + dst[10] = -1; + dst[14] = -zNear; + } + else { + const rangeInv = 1 / (zNear - zFar); + dst[10] = zFar * rangeInv; + dst[14] = zFar * zNear * rangeInv; + } + return dst; +} +/** + * Computes a 4-by-4 orthogonal transformation matrix that transforms from + * the given the left, right, bottom, and top dimensions to -1 +1 in x, and y + * and 0 to +1 in z. + * @param left - Left side of the near clipping plane viewport. + * @param right - Right side of the near clipping plane viewport. + * @param bottom - Bottom of the near clipping plane viewport. + * @param top - Top of the near clipping plane viewport. + * @param near - The depth (negative z coordinate) + * of the near clipping plane. + * @param far - The depth (negative z coordinate) + * of the far clipping plane. + * @param dst - Output matrix. If not passed a new one is created. + * @returns The orthographic projection matrix. + */ +function ortho(left, right, bottom, top, near, far, dst) { + dst = dst || new MatType(16); + dst[0] = 2 / (right - left); + dst[1] = 0; + dst[2] = 0; + dst[3] = 0; + dst[4] = 0; + dst[5] = 2 / (top - bottom); + dst[6] = 0; + dst[7] = 0; + dst[8] = 0; + dst[9] = 0; + dst[10] = 1 / (near - far); + dst[11] = 0; + dst[12] = (right + left) / (left - right); + dst[13] = (top + bottom) / (bottom - top); + dst[14] = near / (near - far); + dst[15] = 1; + return dst; +} +/** + * Computes a 4-by-4 perspective transformation matrix given the left, right, + * top, bottom, near and far clipping planes. The arguments define a frustum + * extending in the negative z direction. The arguments near and far are the + * distances to the near and far clipping planes. Note that near and far are not + * z coordinates, but rather they are distances along the negative z-axis. The + * matrix generated sends the viewing frustum to the unit box. We assume a unit + * box extending from -1 to 1 in the x and y dimensions and from 0 to 1 in the z + * dimension. + * @param left - The x coordinate of the left plane of the box. + * @param right - The x coordinate of the right plane of the box. + * @param bottom - The y coordinate of the bottom plane of the box. + * @param top - The y coordinate of the right plane of the box. + * @param near - The negative z coordinate of the near plane of the box. + * @param far - The negative z coordinate of the far plane of the box. + * @param dst - Output matrix. If not passed a new one is created. + * @returns The perspective projection matrix. + */ +function frustum(left, right, bottom, top, near, far, dst) { + dst = dst || new MatType(16); + const dx = (right - left); + const dy = (top - bottom); + const dz = (near - far); + dst[0] = 2 * near / dx; + dst[1] = 0; + dst[2] = 0; + dst[3] = 0; + dst[4] = 0; + dst[5] = 2 * near / dy; + dst[6] = 0; + dst[7] = 0; + dst[8] = (left + right) / dx; + dst[9] = (top + bottom) / dy; + dst[10] = far / dz; + dst[11] = -1; + dst[12] = 0; + dst[13] = 0; + dst[14] = near * far / dz; + dst[15] = 0; + return dst; +} +let xAxis; +let yAxis; +let zAxis; +/** + * Computes a 4-by-4 aim transformation. + * + * This is a matrix which positions an object aiming down positive Z. + * toward the target. + * + * Note: this is **NOT** the inverse of lookAt as lookAt looks at negative Z. + * + * @param position - The position of the object. + * @param target - The position meant to be aimed at. + * @param up - A vector pointing up. + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The aim matrix. + */ +function aim(position, target, up, dst) { + dst = dst || new MatType(16); + xAxis = xAxis || create$4(); + yAxis = yAxis || create$4(); + zAxis = zAxis || create$4(); + normalize$2(subtract$2(target, position, zAxis), zAxis); + normalize$2(cross(up, zAxis, xAxis), xAxis); + normalize$2(cross(zAxis, xAxis, yAxis), yAxis); + dst[0] = xAxis[0]; + dst[1] = xAxis[1]; + dst[2] = xAxis[2]; + dst[3] = 0; + dst[4] = yAxis[0]; + dst[5] = yAxis[1]; + dst[6] = yAxis[2]; + dst[7] = 0; + dst[8] = zAxis[0]; + dst[9] = zAxis[1]; + dst[10] = zAxis[2]; + dst[11] = 0; + dst[12] = position[0]; + dst[13] = position[1]; + dst[14] = position[2]; + dst[15] = 1; + return dst; +} +/** + * Computes a 4-by-4 camera aim transformation. + * + * This is a matrix which positions an object aiming down negative Z. + * toward the target. + * + * Note: this is the inverse of `lookAt` + * + * @param eye - The position of the object. + * @param target - The position meant to be aimed at. + * @param up - A vector pointing up. + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The aim matrix. + */ +function cameraAim(eye, target, up, dst) { + dst = dst || new MatType(16); + xAxis = xAxis || create$4(); + yAxis = yAxis || create$4(); + zAxis = zAxis || create$4(); + normalize$2(subtract$2(eye, target, zAxis), zAxis); + normalize$2(cross(up, zAxis, xAxis), xAxis); + normalize$2(cross(zAxis, xAxis, yAxis), yAxis); + dst[0] = xAxis[0]; + dst[1] = xAxis[1]; + dst[2] = xAxis[2]; + dst[3] = 0; + dst[4] = yAxis[0]; + dst[5] = yAxis[1]; + dst[6] = yAxis[2]; + dst[7] = 0; + dst[8] = zAxis[0]; + dst[9] = zAxis[1]; + dst[10] = zAxis[2]; + dst[11] = 0; + dst[12] = eye[0]; + dst[13] = eye[1]; + dst[14] = eye[2]; + dst[15] = 1; + return dst; +} +/** + * Computes a 4-by-4 view transformation. + * + * This is a view matrix which transforms all other objects + * to be in the space of the view defined by the parameters. + * + * @param eye - The position of the object. + * @param target - The position meant to be aimed at. + * @param up - A vector pointing up. + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The look-at matrix. + */ +function lookAt(eye, target, up, dst) { + dst = dst || new MatType(16); + xAxis = xAxis || create$4(); + yAxis = yAxis || create$4(); + zAxis = zAxis || create$4(); + normalize$2(subtract$2(eye, target, zAxis), zAxis); + normalize$2(cross(up, zAxis, xAxis), xAxis); + normalize$2(cross(zAxis, xAxis, yAxis), yAxis); + dst[0] = xAxis[0]; + dst[1] = yAxis[0]; + dst[2] = zAxis[0]; + dst[3] = 0; + dst[4] = xAxis[1]; + dst[5] = yAxis[1]; + dst[6] = zAxis[1]; + dst[7] = 0; + dst[8] = xAxis[2]; + dst[9] = yAxis[2]; + dst[10] = zAxis[2]; + dst[11] = 0; + dst[12] = -(xAxis[0] * eye[0] + xAxis[1] * eye[1] + xAxis[2] * eye[2]); + dst[13] = -(yAxis[0] * eye[0] + yAxis[1] * eye[1] + yAxis[2] * eye[2]); + dst[14] = -(zAxis[0] * eye[0] + zAxis[1] * eye[1] + zAxis[2] * eye[2]); + dst[15] = 1; + return dst; +} +/** + * Creates a 4-by-4 matrix which translates by the given vector v. + * @param v - The vector by + * which to translate. + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The translation matrix. + */ +function translation(v, dst) { + dst = dst || new MatType(16); + dst[0] = 1; + dst[1] = 0; + dst[2] = 0; + dst[3] = 0; + dst[4] = 0; + dst[5] = 1; + dst[6] = 0; + dst[7] = 0; + dst[8] = 0; + dst[9] = 0; + dst[10] = 1; + dst[11] = 0; + dst[12] = v[0]; + dst[13] = v[1]; + dst[14] = v[2]; + dst[15] = 1; + return dst; +} +/** + * Translates the given 4-by-4 matrix by the given vector v. + * @param m - The matrix. + * @param v - The vector by + * which to translate. + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The translated matrix. + */ +function translate(m, v, dst) { + dst = dst || new MatType(16); + const v0 = v[0]; + const v1 = v[1]; + const v2 = v[2]; + const m00 = m[0]; + const m01 = m[1]; + const m02 = m[2]; + const m03 = m[3]; + const m10 = m[1 * 4 + 0]; + const m11 = m[1 * 4 + 1]; + const m12 = m[1 * 4 + 2]; + const m13 = m[1 * 4 + 3]; + const m20 = m[2 * 4 + 0]; + const m21 = m[2 * 4 + 1]; + const m22 = m[2 * 4 + 2]; + const m23 = m[2 * 4 + 3]; + const m30 = m[3 * 4 + 0]; + const m31 = m[3 * 4 + 1]; + const m32 = m[3 * 4 + 2]; + const m33 = m[3 * 4 + 3]; + if (m !== dst) { + dst[0] = m00; + dst[1] = m01; + dst[2] = m02; + dst[3] = m03; + dst[4] = m10; + dst[5] = m11; + dst[6] = m12; + dst[7] = m13; + dst[8] = m20; + dst[9] = m21; + dst[10] = m22; + dst[11] = m23; + } + dst[12] = m00 * v0 + m10 * v1 + m20 * v2 + m30; + dst[13] = m01 * v0 + m11 * v1 + m21 * v2 + m31; + dst[14] = m02 * v0 + m12 * v1 + m22 * v2 + m32; + dst[15] = m03 * v0 + m13 * v1 + m23 * v2 + m33; + return dst; +} +/** + * Creates a 4-by-4 matrix which rotates around the x-axis by the given angle. + * @param angleInRadians - The angle by which to rotate (in radians). + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The rotation matrix. + */ +function rotationX(angleInRadians, dst) { + dst = dst || new MatType(16); + const c = Math.cos(angleInRadians); + const s = Math.sin(angleInRadians); + dst[0] = 1; + dst[1] = 0; + dst[2] = 0; + dst[3] = 0; + dst[4] = 0; + dst[5] = c; + dst[6] = s; + dst[7] = 0; + dst[8] = 0; + dst[9] = -s; + dst[10] = c; + dst[11] = 0; + dst[12] = 0; + dst[13] = 0; + dst[14] = 0; + dst[15] = 1; + return dst; +} +/** + * Rotates the given 4-by-4 matrix around the x-axis by the given + * angle. + * @param m - The matrix. + * @param angleInRadians - The angle by which to rotate (in radians). + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The rotated matrix. + */ +function rotateX$1(m, angleInRadians, dst) { + dst = dst || new MatType(16); + const m10 = m[4]; + const m11 = m[5]; + const m12 = m[6]; + const m13 = m[7]; + const m20 = m[8]; + const m21 = m[9]; + const m22 = m[10]; + const m23 = m[11]; + const c = Math.cos(angleInRadians); + const s = Math.sin(angleInRadians); + dst[4] = c * m10 + s * m20; + dst[5] = c * m11 + s * m21; + dst[6] = c * m12 + s * m22; + dst[7] = c * m13 + s * m23; + dst[8] = c * m20 - s * m10; + dst[9] = c * m21 - s * m11; + dst[10] = c * m22 - s * m12; + dst[11] = c * m23 - s * m13; + if (m !== dst) { + dst[0] = m[0]; + dst[1] = m[1]; + dst[2] = m[2]; + dst[3] = m[3]; + dst[12] = m[12]; + dst[13] = m[13]; + dst[14] = m[14]; + dst[15] = m[15]; + } + return dst; +} +/** + * Creates a 4-by-4 matrix which rotates around the y-axis by the given angle. + * @param angleInRadians - The angle by which to rotate (in radians). + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The rotation matrix. + */ +function rotationY(angleInRadians, dst) { + dst = dst || new MatType(16); + const c = Math.cos(angleInRadians); + const s = Math.sin(angleInRadians); + dst[0] = c; + dst[1] = 0; + dst[2] = -s; + dst[3] = 0; + dst[4] = 0; + dst[5] = 1; + dst[6] = 0; + dst[7] = 0; + dst[8] = s; + dst[9] = 0; + dst[10] = c; + dst[11] = 0; + dst[12] = 0; + dst[13] = 0; + dst[14] = 0; + dst[15] = 1; + return dst; +} +/** + * Rotates the given 4-by-4 matrix around the y-axis by the given + * angle. + * @param m - The matrix. + * @param angleInRadians - The angle by which to rotate (in radians). + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The rotated matrix. + */ +function rotateY$1(m, angleInRadians, dst) { + dst = dst || new MatType(16); + const m00 = m[0 * 4 + 0]; + const m01 = m[0 * 4 + 1]; + const m02 = m[0 * 4 + 2]; + const m03 = m[0 * 4 + 3]; + const m20 = m[2 * 4 + 0]; + const m21 = m[2 * 4 + 1]; + const m22 = m[2 * 4 + 2]; + const m23 = m[2 * 4 + 3]; + const c = Math.cos(angleInRadians); + const s = Math.sin(angleInRadians); + dst[0] = c * m00 - s * m20; + dst[1] = c * m01 - s * m21; + dst[2] = c * m02 - s * m22; + dst[3] = c * m03 - s * m23; + dst[8] = c * m20 + s * m00; + dst[9] = c * m21 + s * m01; + dst[10] = c * m22 + s * m02; + dst[11] = c * m23 + s * m03; + if (m !== dst) { + dst[4] = m[4]; + dst[5] = m[5]; + dst[6] = m[6]; + dst[7] = m[7]; + dst[12] = m[12]; + dst[13] = m[13]; + dst[14] = m[14]; + dst[15] = m[15]; + } + return dst; +} +/** + * Creates a 4-by-4 matrix which rotates around the z-axis by the given angle. + * @param angleInRadians - The angle by which to rotate (in radians). + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The rotation matrix. + */ +function rotationZ(angleInRadians, dst) { + dst = dst || new MatType(16); + const c = Math.cos(angleInRadians); + const s = Math.sin(angleInRadians); + dst[0] = c; + dst[1] = s; + dst[2] = 0; + dst[3] = 0; + dst[4] = -s; + dst[5] = c; + dst[6] = 0; + dst[7] = 0; + dst[8] = 0; + dst[9] = 0; + dst[10] = 1; + dst[11] = 0; + dst[12] = 0; + dst[13] = 0; + dst[14] = 0; + dst[15] = 1; + return dst; +} +/** + * Rotates the given 4-by-4 matrix around the z-axis by the given + * angle. + * @param m - The matrix. + * @param angleInRadians - The angle by which to rotate (in radians). + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The rotated matrix. + */ +function rotateZ$1(m, angleInRadians, dst) { + dst = dst || new MatType(16); + const m00 = m[0 * 4 + 0]; + const m01 = m[0 * 4 + 1]; + const m02 = m[0 * 4 + 2]; + const m03 = m[0 * 4 + 3]; + const m10 = m[1 * 4 + 0]; + const m11 = m[1 * 4 + 1]; + const m12 = m[1 * 4 + 2]; + const m13 = m[1 * 4 + 3]; + const c = Math.cos(angleInRadians); + const s = Math.sin(angleInRadians); + dst[0] = c * m00 + s * m10; + dst[1] = c * m01 + s * m11; + dst[2] = c * m02 + s * m12; + dst[3] = c * m03 + s * m13; + dst[4] = c * m10 - s * m00; + dst[5] = c * m11 - s * m01; + dst[6] = c * m12 - s * m02; + dst[7] = c * m13 - s * m03; + if (m !== dst) { + dst[8] = m[8]; + dst[9] = m[9]; + dst[10] = m[10]; + dst[11] = m[11]; + dst[12] = m[12]; + dst[13] = m[13]; + dst[14] = m[14]; + dst[15] = m[15]; + } + return dst; +} +/** + * Creates a 4-by-4 matrix which rotates around the given axis by the given + * angle. + * @param axis - The axis + * about which to rotate. + * @param angleInRadians - The angle by which to rotate (in radians). + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns A matrix which rotates angle radians + * around the axis. + */ +function axisRotation(axis, angleInRadians, dst) { + dst = dst || new MatType(16); + let x = axis[0]; + let y = axis[1]; + let z = axis[2]; + const n = Math.sqrt(x * x + y * y + z * z); + x /= n; + y /= n; + z /= n; + const xx = x * x; + const yy = y * y; + const zz = z * z; + const c = Math.cos(angleInRadians); + const s = Math.sin(angleInRadians); + const oneMinusCosine = 1 - c; + dst[0] = xx + (1 - xx) * c; + dst[1] = x * y * oneMinusCosine + z * s; + dst[2] = x * z * oneMinusCosine - y * s; + dst[3] = 0; + dst[4] = x * y * oneMinusCosine - z * s; + dst[5] = yy + (1 - yy) * c; + dst[6] = y * z * oneMinusCosine + x * s; + dst[7] = 0; + dst[8] = x * z * oneMinusCosine + y * s; + dst[9] = y * z * oneMinusCosine - x * s; + dst[10] = zz + (1 - zz) * c; + dst[11] = 0; + dst[12] = 0; + dst[13] = 0; + dst[14] = 0; + dst[15] = 1; + return dst; +} +/** + * Creates a 4-by-4 matrix which rotates around the given axis by the given + * angle. (same as axisRotation) + * @param axis - The axis + * about which to rotate. + * @param angleInRadians - The angle by which to rotate (in radians). + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns A matrix which rotates angle radians + * around the axis. + */ +const rotation = axisRotation; +/** + * Rotates the given 4-by-4 matrix around the given axis by the + * given angle. + * @param m - The matrix. + * @param axis - The axis + * about which to rotate. + * @param angleInRadians - The angle by which to rotate (in radians). + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The rotated matrix. + */ +function axisRotate(m, axis, angleInRadians, dst) { + dst = dst || new MatType(16); + let x = axis[0]; + let y = axis[1]; + let z = axis[2]; + const n = Math.sqrt(x * x + y * y + z * z); + x /= n; + y /= n; + z /= n; + const xx = x * x; + const yy = y * y; + const zz = z * z; + const c = Math.cos(angleInRadians); + const s = Math.sin(angleInRadians); + const oneMinusCosine = 1 - c; + const r00 = xx + (1 - xx) * c; + const r01 = x * y * oneMinusCosine + z * s; + const r02 = x * z * oneMinusCosine - y * s; + const r10 = x * y * oneMinusCosine - z * s; + const r11 = yy + (1 - yy) * c; + const r12 = y * z * oneMinusCosine + x * s; + const r20 = x * z * oneMinusCosine + y * s; + const r21 = y * z * oneMinusCosine - x * s; + const r22 = zz + (1 - zz) * c; + const m00 = m[0]; + const m01 = m[1]; + const m02 = m[2]; + const m03 = m[3]; + const m10 = m[4]; + const m11 = m[5]; + const m12 = m[6]; + const m13 = m[7]; + const m20 = m[8]; + const m21 = m[9]; + const m22 = m[10]; + const m23 = m[11]; + dst[0] = r00 * m00 + r01 * m10 + r02 * m20; + dst[1] = r00 * m01 + r01 * m11 + r02 * m21; + dst[2] = r00 * m02 + r01 * m12 + r02 * m22; + dst[3] = r00 * m03 + r01 * m13 + r02 * m23; + dst[4] = r10 * m00 + r11 * m10 + r12 * m20; + dst[5] = r10 * m01 + r11 * m11 + r12 * m21; + dst[6] = r10 * m02 + r11 * m12 + r12 * m22; + dst[7] = r10 * m03 + r11 * m13 + r12 * m23; + dst[8] = r20 * m00 + r21 * m10 + r22 * m20; + dst[9] = r20 * m01 + r21 * m11 + r22 * m21; + dst[10] = r20 * m02 + r21 * m12 + r22 * m22; + dst[11] = r20 * m03 + r21 * m13 + r22 * m23; + if (m !== dst) { + dst[12] = m[12]; + dst[13] = m[13]; + dst[14] = m[14]; + dst[15] = m[15]; + } + return dst; +} +/** + * Rotates the given 4-by-4 matrix around the given axis by the + * given angle. (same as rotate) + * @param m - The matrix. + * @param axis - The axis + * about which to rotate. + * @param angleInRadians - The angle by which to rotate (in radians). + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The rotated matrix. + */ +const rotate = axisRotate; +/** + * Creates a 4-by-4 matrix which scales in each dimension by an amount given by + * the corresponding entry in the given vector; assumes the vector has three + * entries. + * @param v - A vector of + * three entries specifying the factor by which to scale in each dimension. + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The scaling matrix. + */ +function scaling(v, dst) { + dst = dst || new MatType(16); + dst[0] = v[0]; + dst[1] = 0; + dst[2] = 0; + dst[3] = 0; + dst[4] = 0; + dst[5] = v[1]; + dst[6] = 0; + dst[7] = 0; + dst[8] = 0; + dst[9] = 0; + dst[10] = v[2]; + dst[11] = 0; + dst[12] = 0; + dst[13] = 0; + dst[14] = 0; + dst[15] = 1; + return dst; +} +/** + * Scales the given 4-by-4 matrix in each dimension by an amount + * given by the corresponding entry in the given vector; assumes the vector has + * three entries. + * @param m - The matrix to be modified. + * @param v - A vector of three entries specifying the + * factor by which to scale in each dimension. + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The scaled matrix. + */ +function scale$2(m, v, dst) { + dst = dst || new MatType(16); + const v0 = v[0]; + const v1 = v[1]; + const v2 = v[2]; + dst[0] = v0 * m[0 * 4 + 0]; + dst[1] = v0 * m[0 * 4 + 1]; + dst[2] = v0 * m[0 * 4 + 2]; + dst[3] = v0 * m[0 * 4 + 3]; + dst[4] = v1 * m[1 * 4 + 0]; + dst[5] = v1 * m[1 * 4 + 1]; + dst[6] = v1 * m[1 * 4 + 2]; + dst[7] = v1 * m[1 * 4 + 3]; + dst[8] = v2 * m[2 * 4 + 0]; + dst[9] = v2 * m[2 * 4 + 1]; + dst[10] = v2 * m[2 * 4 + 2]; + dst[11] = v2 * m[2 * 4 + 3]; + if (m !== dst) { + dst[12] = m[12]; + dst[13] = m[13]; + dst[14] = m[14]; + dst[15] = m[15]; + } + return dst; +} +/** + * Creates a 4-by-4 matrix which scales a uniform amount in each dimension. + * @param s - the amount to scale + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The scaling matrix. + */ +function uniformScaling(s, dst) { + dst = dst || new MatType(16); + dst[0] = s; + dst[1] = 0; + dst[2] = 0; + dst[3] = 0; + dst[4] = 0; + dst[5] = s; + dst[6] = 0; + dst[7] = 0; + dst[8] = 0; + dst[9] = 0; + dst[10] = s; + dst[11] = 0; + dst[12] = 0; + dst[13] = 0; + dst[14] = 0; + dst[15] = 1; + return dst; +} +/** + * Scales the given 4-by-4 matrix in each dimension by a uniform scale. + * @param m - The matrix to be modified. + * @param s - The amount to scale. + * @param dst - matrix to hold result. If not passed a new one is created. + * @returns The scaled matrix. + */ +function uniformScale(m, s, dst) { + dst = dst || new MatType(16); + dst[0] = s * m[0 * 4 + 0]; + dst[1] = s * m[0 * 4 + 1]; + dst[2] = s * m[0 * 4 + 2]; + dst[3] = s * m[0 * 4 + 3]; + dst[4] = s * m[1 * 4 + 0]; + dst[5] = s * m[1 * 4 + 1]; + dst[6] = s * m[1 * 4 + 2]; + dst[7] = s * m[1 * 4 + 3]; + dst[8] = s * m[2 * 4 + 0]; + dst[9] = s * m[2 * 4 + 1]; + dst[10] = s * m[2 * 4 + 2]; + dst[11] = s * m[2 * 4 + 3]; + if (m !== dst) { + dst[12] = m[12]; + dst[13] = m[13]; + dst[14] = m[14]; + dst[15] = m[15]; + } + return dst; +} + +var mat4Impl = /*#__PURE__*/Object.freeze({ + __proto__: null, + setDefaultType: setDefaultType$3, + create: create$2, + set: set$2, + fromMat3: fromMat3, + fromQuat: fromQuat, + negate: negate$1, + copy: copy$2, + clone: clone$2, + equalsApproximately: equalsApproximately$2, + equals: equals$2, + identity: identity$1, + transpose: transpose, + inverse: inverse$2, + determinant: determinant, + invert: invert$1, + multiply: multiply$2, + mul: mul$2, + setTranslation: setTranslation, + getTranslation: getTranslation, + getAxis: getAxis, + setAxis: setAxis, + getScaling: getScaling, + perspective: perspective, + ortho: ortho, + frustum: frustum, + aim: aim, + cameraAim: cameraAim, + lookAt: lookAt, + translation: translation, + translate: translate, + rotationX: rotationX, + rotateX: rotateX$1, + rotationY: rotationY, + rotateY: rotateY$1, + rotationZ: rotationZ, + rotateZ: rotateZ$1, + axisRotation: axisRotation, + rotation: rotation, + axisRotate: axisRotate, + rotate: rotate, + scaling: scaling, + scale: scale$2, + uniformScaling: uniformScaling, + uniformScale: uniformScale +}); + +const cubeVertexSize = 4 * 10; // Byte size of one cube vertex. +const cubePositionOffset = 0; +const cubeUVOffset = 4 * 8; +const cubeVertexCount = 36; +// prettier-ignore +const cubeVertexArray = new Float32Array([ + // float4 position, float4 color, float2 uv, + 1, -1, 1, 1, 1, 0, 1, 1, 0, 1, + -1, -1, 1, 1, 0, 0, 1, 1, 1, 1, + -1, -1, -1, 1, 0, 0, 0, 1, 1, 0, + 1, -1, -1, 1, 1, 0, 0, 1, 0, 0, + 1, -1, 1, 1, 1, 0, 1, 1, 0, 1, + -1, -1, -1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, + 1, -1, 1, 1, 1, 0, 1, 1, 1, 1, + 1, -1, -1, 1, 1, 0, 0, 1, 1, 0, + 1, 1, -1, 1, 1, 1, 0, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, + 1, -1, -1, 1, 1, 0, 0, 1, 1, 0, + -1, 1, 1, 1, 0, 1, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, -1, 1, 1, 1, 0, 1, 1, 0, + -1, 1, -1, 1, 0, 1, 0, 1, 0, 0, + -1, 1, 1, 1, 0, 1, 1, 1, 0, 1, + 1, 1, -1, 1, 1, 1, 0, 1, 1, 0, + -1, -1, 1, 1, 0, 0, 1, 1, 0, 1, + -1, 1, 1, 1, 0, 1, 1, 1, 1, 1, + -1, 1, -1, 1, 0, 1, 0, 1, 1, 0, + -1, -1, -1, 1, 0, 0, 0, 1, 0, 0, + -1, -1, 1, 1, 0, 0, 1, 1, 0, 1, + -1, 1, -1, 1, 0, 1, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, + -1, 1, 1, 1, 0, 1, 1, 1, 1, 1, + -1, -1, 1, 1, 0, 0, 1, 1, 1, 0, + -1, -1, 1, 1, 0, 0, 1, 1, 1, 0, + 1, -1, 1, 1, 1, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, + 1, -1, -1, 1, 1, 0, 0, 1, 0, 1, + -1, -1, -1, 1, 0, 0, 0, 1, 1, 1, + -1, 1, -1, 1, 0, 1, 0, 1, 1, 0, + 1, 1, -1, 1, 1, 1, 0, 1, 0, 0, + 1, -1, -1, 1, 1, 0, 0, 1, 0, 1, + -1, 1, -1, 1, 0, 1, 0, 1, 1, 0, +]); + +var msdfTextWGSL = `// Positions for simple quad geometry +const pos = array(vec2f(0, -1), vec2f(1, -1), vec2f(0, 0), vec2f(1, 0)); + +struct VertexInput { + @builtin(vertex_index) vertex : u32, + @builtin(instance_index) instance : u32, +}; + +struct VertexOutput { + @builtin(position) position : vec4f, + @location(0) texcoord : vec2f, +}; + +struct Char { + texOffset: vec2f, + texExtent: vec2f, + size: vec2f, + offset: vec2f, +}; + +struct FormattedText { + transform: mat4x4f, + color: vec4f, + scale: f32, + chars: array, +}; + +struct Camera { + projection: mat4x4f, + view: mat4x4f, +}; + +// Font bindings +@group(0) @binding(0) var fontTexture: texture_2d; +@group(0) @binding(1) var fontSampler: sampler; +@group(0) @binding(2) var chars: array; + +// Text bindings +@group(1) @binding(0) var camera: Camera; +@group(1) @binding(1) var text: FormattedText; + +@vertex +fn vertexMain(input : VertexInput) -> VertexOutput { + let textElement = text.chars[input.instance]; + let char = chars[u32(textElement.z)]; + let charPos = (pos[input.vertex] * char.size + textElement.xy + char.offset) * text.scale; + + var output : VertexOutput; + output.position = camera.projection * camera.view * text.transform * vec4f(charPos, 0, 1); + + output.texcoord = pos[input.vertex] * vec2f(1, -1); + output.texcoord *= char.texExtent; + output.texcoord += char.texOffset; + return output; +} + +fn sampleMsdf(texcoord: vec2f) -> f32 { + let c = textureSample(fontTexture, fontSampler, texcoord); + return max(min(c.r, c.g), min(max(c.r, c.g), c.b)); +} + +// Antialiasing technique from https://drewcassidy.me/2020/06/26/sdf-antialiasing/ +@fragment +fn fragmentMain(input : VertexOutput) -> @location(0) vec4f { + let dist = 0.5 - sampleMsdf(input.texcoord); + + // sdf distance per pixel (gradient vector) + let ddist = vec2f(dpdx(dist), dpdy(dist)); + + // distance to edge in pixels (scalar) + let pixelDist = dist / length(ddist); + + let alpha = saturate(0.5 - pixelDist); + if (alpha < 0.001) { + discard; + } + + return vec4f(text.color.rgb, text.color.a * alpha); +}`; + +class MsdfFont { + pipeline; + bindGroup; + lineHeight; + chars; + kernings; + charCount; + defaultChar; + constructor(pipeline, bindGroup, lineHeight, chars, kernings) { + this.pipeline = pipeline; + this.bindGroup = bindGroup; + this.lineHeight = lineHeight; + this.chars = chars; + this.kernings = kernings; + const charArray = Object.values(chars); + this.charCount = charArray.length; + this.defaultChar = charArray[0]; + } + getChar(charCode) { + let char = this.chars[charCode]; + if (!char) { + char = this.defaultChar; + } + return char; + } + // Gets the distance in pixels a line should advance for a given character code. If the upcoming + // character code is given any kerning between the two characters will be taken into account. + getXAdvance(charCode, nextCharCode = -1) { + const char = this.getChar(charCode); + if (nextCharCode >= 0) { + const kerning = this.kernings.get(charCode); + if (kerning) { + return char.xadvance + (kerning.get(nextCharCode) ?? 0); + } + } + return char.xadvance; + } +} +class MsdfText { + device; + renderBundle; + measurements; + font; + textBuffer; + bufferArray = new Float32Array(24); + bufferArrayDirty = true; + constructor(device, renderBundle, measurements, font, textBuffer) { + this.device = device; + this.renderBundle = renderBundle; + this.measurements = measurements; + this.font = font; + this.textBuffer = textBuffer; + mat4Impl.identity(this.bufferArray); + this.setColor(1, 1, 1, 1); + this.setPixelScale(1 / 512); + this.bufferArrayDirty = true; + } + getRenderBundle() { + if (this.bufferArrayDirty) { + this.bufferArrayDirty = false; + this.device.queue.writeBuffer(this.textBuffer, 0, this.bufferArray, 0, this.bufferArray.length); + } + return this.renderBundle; + } + setTransform(matrix) { + mat4Impl.copy(matrix, this.bufferArray); + this.bufferArrayDirty = true; + } + setColor(r, g, b, a = 1.0) { + this.bufferArray[16] = r; + this.bufferArray[17] = g; + this.bufferArray[18] = b; + this.bufferArray[19] = a; + this.bufferArrayDirty = true; + } + setPixelScale(pixelScale) { + this.bufferArray[20] = pixelScale; + this.bufferArrayDirty = true; + } +} +class MsdfTextRenderer { + device; + fontBindGroupLayout; + textBindGroupLayout; + pipelinePromise; + sampler; + cameraUniformBuffer; + renderBundleDescriptor; + cameraArray = new Float32Array(16 * 2); + constructor(device, colorFormat, depthFormat) { + this.device = device; + this.renderBundleDescriptor = { + colorFormats: [colorFormat], + depthStencilFormat: depthFormat, + }; + this.sampler = device.createSampler({ + label: 'MSDF text sampler', + minFilter: 'linear', + magFilter: 'linear', + mipmapFilter: 'linear', + maxAnisotropy: 16, + }); + this.cameraUniformBuffer = device.createBuffer({ + label: 'MSDF camera uniform buffer', + size: this.cameraArray.byteLength, + usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.UNIFORM, + }); + this.fontBindGroupLayout = device.createBindGroupLayout({ + label: 'MSDF font group layout', + entries: [ + { + binding: 0, + visibility: GPUShaderStage.FRAGMENT, + texture: {}, + }, + { + binding: 1, + visibility: GPUShaderStage.FRAGMENT, + sampler: {}, + }, + { + binding: 2, + visibility: GPUShaderStage.VERTEX, + buffer: { type: 'read-only-storage' }, + }, + ], + }); + this.textBindGroupLayout = device.createBindGroupLayout({ + label: 'MSDF text group layout', + entries: [ + { + binding: 0, + visibility: GPUShaderStage.VERTEX, + buffer: {}, + }, + { + binding: 1, + visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, + buffer: { type: 'read-only-storage' }, + }, + ], + }); + const shaderModule = device.createShaderModule({ + label: 'MSDF text shader', + code: msdfTextWGSL, + }); + this.pipelinePromise = device.createRenderPipelineAsync({ + label: `msdf text pipeline`, + layout: device.createPipelineLayout({ + bindGroupLayouts: [this.fontBindGroupLayout, this.textBindGroupLayout], + }), + vertex: { + module: shaderModule, + entryPoint: 'vertexMain', + }, + fragment: { + module: shaderModule, + entryPoint: 'fragmentMain', + targets: [ + { + format: colorFormat, + blend: { + color: { + srcFactor: 'src-alpha', + dstFactor: 'one-minus-src-alpha', + }, + alpha: { + srcFactor: 'one', + dstFactor: 'one', + }, + }, + }, + ], + }, + primitive: { + topology: 'triangle-strip', + stripIndexFormat: 'uint32', + }, + depthStencil: { + depthWriteEnabled: false, + depthCompare: 'less', + format: depthFormat, + }, + }); + } + async loadTexture(url) { + const response = await fetch(url); + const imageBitmap = await createImageBitmap(await response.blob()); + const texture = this.device.createTexture({ + label: `MSDF font texture ${url}`, + size: [imageBitmap.width, imageBitmap.height, 1], + format: 'rgba8unorm', + usage: GPUTextureUsage.TEXTURE_BINDING | + GPUTextureUsage.COPY_DST | + GPUTextureUsage.RENDER_ATTACHMENT, + }); + this.device.queue.copyExternalImageToTexture({ source: imageBitmap }, { texture }, [imageBitmap.width, imageBitmap.height]); + return texture; + } + async createFont(fontJsonUrl) { + const response = await fetch(fontJsonUrl); + const json = await response.json(); + const i = fontJsonUrl.lastIndexOf('/'); + const baseUrl = i !== -1 ? fontJsonUrl.substring(0, i + 1) : undefined; + const pagePromises = []; + for (const pageUrl of json.pages) { + pagePromises.push(this.loadTexture(baseUrl + pageUrl)); + } + const charCount = json.chars.length; + const charsBuffer = this.device.createBuffer({ + label: 'MSDF character layout buffer', + size: charCount * Float32Array.BYTES_PER_ELEMENT * 8, + usage: GPUBufferUsage.STORAGE, + mappedAtCreation: true, + }); + const charsArray = new Float32Array(charsBuffer.getMappedRange()); + const u = 1 / json.common.scaleW; + const v = 1 / json.common.scaleH; + const chars = {}; + let offset = 0; + for (const [i, char] of json.chars.entries()) { + chars[char.id] = char; + chars[char.id].charIndex = i; + charsArray[offset] = char.x * u; // texOffset.x + charsArray[offset + 1] = char.y * v; // texOffset.y + charsArray[offset + 2] = char.width * u; // texExtent.x + charsArray[offset + 3] = char.height * v; // texExtent.y + charsArray[offset + 4] = char.width; // size.x + charsArray[offset + 5] = char.height; // size.y + charsArray[offset + 6] = char.xoffset; // offset.x + charsArray[offset + 7] = -char.yoffset; // offset.y + offset += 8; + } + charsBuffer.unmap(); + const pageTextures = await Promise.all(pagePromises); + const bindGroup = this.device.createBindGroup({ + label: 'msdf font bind group', + layout: this.fontBindGroupLayout, + entries: [ + { + binding: 0, + // TODO: Allow multi-page fonts + resource: pageTextures[0].createView(), + }, + { + binding: 1, + resource: this.sampler, + }, + { + binding: 2, + resource: { buffer: charsBuffer }, + }, + ], + }); + const kernings = new Map(); + if (json.kernings) { + for (const kearning of json.kernings) { + let charKerning = kernings.get(kearning.first); + if (!charKerning) { + charKerning = new Map(); + kernings.set(kearning.first, charKerning); + } + charKerning.set(kearning.second, kearning.amount); + } + } + return new MsdfFont(await this.pipelinePromise, bindGroup, json.common.lineHeight, chars, kernings); + } + formatText(font, text, options = {}) { + const textBuffer = this.device.createBuffer({ + label: 'msdf text buffer', + size: (text.length + 6) * Float32Array.BYTES_PER_ELEMENT * 4, + usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST, + mappedAtCreation: true, + }); + const textArray = new Float32Array(textBuffer.getMappedRange()); + let offset = 24; // Accounts for the values managed by MsdfText internally. + let measurements; + if (options.centered) { + measurements = this.measureText(font, text); + this.measureText(font, text, (textX, textY, line, char) => { + const lineOffset = measurements.width * -0.5 - + (measurements.width - measurements.lineWidths[line]) * -0.5; + textArray[offset] = textX + lineOffset; + textArray[offset + 1] = textY + measurements.height * 0.5; + textArray[offset + 2] = char.charIndex; + offset += 4; + }); + } + else { + measurements = this.measureText(font, text, (textX, textY, line, char) => { + textArray[offset] = textX; + textArray[offset + 1] = textY; + textArray[offset + 2] = char.charIndex; + offset += 4; + }); + } + textBuffer.unmap(); + const bindGroup = this.device.createBindGroup({ + label: 'msdf text bind group', + layout: this.textBindGroupLayout, + entries: [ + { + binding: 0, + resource: { buffer: this.cameraUniformBuffer }, + }, + { + binding: 1, + resource: { buffer: textBuffer }, + }, + ], + }); + const encoder = this.device.createRenderBundleEncoder(this.renderBundleDescriptor); + encoder.setPipeline(font.pipeline); + encoder.setBindGroup(0, font.bindGroup); + encoder.setBindGroup(1, bindGroup); + encoder.draw(4, measurements.printedCharCount); + const renderBundle = encoder.finish(); + const msdfText = new MsdfText(this.device, renderBundle, measurements, font, textBuffer); + if (options.pixelScale !== undefined) { + msdfText.setPixelScale(options.pixelScale); + } + if (options.color !== undefined) { + msdfText.setColor(...options.color); + } + return msdfText; + } + measureText(font, text, charCallback) { + let maxWidth = 0; + const lineWidths = []; + let textOffsetX = 0; + let textOffsetY = 0; + let line = 0; + let printedCharCount = 0; + let nextCharCode = text.charCodeAt(0); + for (let i = 0; i < text.length; ++i) { + const charCode = nextCharCode; + nextCharCode = i < text.length - 1 ? text.charCodeAt(i + 1) : -1; + switch (charCode) { + case 10: // Newline + lineWidths.push(textOffsetX); + line++; + maxWidth = Math.max(maxWidth, textOffsetX); + textOffsetX = 0; + textOffsetY -= font.lineHeight; + case 13: // CR + break; + case 32: // Space + // For spaces, advance the offset without actually adding a character. + textOffsetX += font.getXAdvance(charCode); + break; + default: { + if (charCallback) { + charCallback(textOffsetX, textOffsetY, line, font.getChar(charCode)); + } + textOffsetX += font.getXAdvance(charCode, nextCharCode); + printedCharCount++; + } + } + } + lineWidths.push(textOffsetX); + maxWidth = Math.max(maxWidth, textOffsetX); + return { + width: maxWidth, + height: lineWidths.length * font.lineHeight, + lineWidths, + printedCharCount, + }; + } + updateCamera(projection, view) { + this.cameraArray.set(projection, 0); + this.cameraArray.set(view, 16); + this.device.queue.writeBuffer(this.cameraUniformBuffer, 0, this.cameraArray); + } + render(renderPass, ...text) { + const renderBundles = text.map((t) => t.getRenderBundle()); + renderPass.executeBundles(renderBundles); + } +} + +var basicVertWGSL = `struct Uniforms { + modelViewProjectionMatrix : mat4x4f, +} +@binding(0) @group(0) var uniforms : Uniforms; + +struct VertexOutput { + @builtin(position) Position : vec4f, + @location(0) fragUV : vec2f, + @location(1) fragPosition: vec4f, +} + +@vertex +fn main( + @location(0) position : vec4f, + @location(1) uv : vec2f +) -> VertexOutput { + var output : VertexOutput; + output.Position = uniforms.modelViewProjectionMatrix * position; + output.fragUV = uv; + output.fragPosition = 0.5 * (position + vec4(1.0, 1.0, 1.0, 1.0)); + return output; +} +`; + +var vertexPositionColorWGSL = `@fragment +fn main( + @location(0) fragUV: vec2f, + @location(1) fragPosition: vec4f +) -> @location(0) vec4f { + return fragPosition; +} +`; + +const canvas = document.querySelector('canvas'); +const adapter = await navigator.gpu.requestAdapter(); +const device = await adapter.requestDevice(); +const context = canvas.getContext('webgpu'); +const devicePixelRatio = window.devicePixelRatio || 1; +canvas.width = canvas.clientWidth * devicePixelRatio; +canvas.height = canvas.clientHeight * devicePixelRatio; +const presentationFormat = navigator.gpu.getPreferredCanvasFormat(); +const depthFormat = 'depth24plus'; +context.configure({ + device, + format: presentationFormat, + alphaMode: 'premultiplied', +}); +const textRenderer = new MsdfTextRenderer(device, presentationFormat, depthFormat); +const font = await textRenderer.createFont(new URL('../../assets/font/ya-hei-ascii-msdf.json', import.meta.url).toString()); +function getTextTransform(position, rotation) { + const textTransform = mat4Impl.create(); + mat4Impl.identity(textTransform); + mat4Impl.translate(textTransform, position, textTransform); + if (rotation && rotation[0] != 0) { + mat4Impl.rotateX(textTransform, rotation[0], textTransform); + } + if (rotation && rotation[1] != 0) { + mat4Impl.rotateY(textTransform, rotation[1], textTransform); + } + if (rotation && rotation[2] != 0) { + mat4Impl.rotateZ(textTransform, rotation[2], textTransform); + } + return textTransform; +} +const textTransforms = [ + getTextTransform([0, 0, 1.1]), + getTextTransform([0, 0, -1.1], [0, Math.PI, 0]), + getTextTransform([1.1, 0, 0], [0, Math.PI / 2, 0]), + getTextTransform([-1.1, 0, 0], [0, -Math.PI / 2, 0]), + getTextTransform([0, 1.1, 0], [-Math.PI / 2, 0, 0]), + getTextTransform([0, -1.1, 0], [Math.PI / 2, 0, 0]), +]; +const titleText = textRenderer.formatText(font, `WebGPU`, { + centered: true, + pixelScale: 1 / 128, +}); +const largeText = textRenderer.formatText(font, ` +WebGPU exposes an API for performing operations, such as rendering +and computation, on a Graphics Processing Unit. + +Graphics Processing Units, or GPUs for short, have been essential +in enabling rich rendering and computational applications in personal +computing. WebGPU is an API that exposes the capabilities of GPU +hardware for the Web. The API is designed from the ground up to +efficiently map to (post-2014) native GPU APIs. WebGPU is not related +to WebGL and does not explicitly target OpenGL ES. + +WebGPU sees physical GPU hardware as GPUAdapters. It provides a +connection to an adapter via GPUDevice, which manages resources, and +the device’s GPUQueues, which execute commands. GPUDevice may have +its own memory with high-speed access to the processing units. +GPUBuffer and GPUTexture are the physical resources backed by GPU +memory. GPUCommandBuffer and GPURenderBundle are containers for +user-recorded commands. GPUShaderModule contains shader code. The +other resources, such as GPUSampler or GPUBindGroup, configure the +way physical resources are used by the GPU. + +GPUs execute commands encoded in GPUCommandBuffers by feeding data +through a pipeline, which is a mix of fixed-function and programmable +stages. Programmable stages execute shaders, which are special +programs designed to run on GPU hardware. Most of the state of a +pipeline is defined by a GPURenderPipeline or a GPUComputePipeline +object. The state not included in these pipeline objects is set +during encoding with commands, such as beginRenderPass() or +setBlendConstant().`, { pixelScale: 1 / 256 }); +const text = [ + textRenderer.formatText(font, 'Front', { + centered: true, + pixelScale: 1 / 128, + color: [1, 0, 0, 1], + }), + textRenderer.formatText(font, 'Back', { + centered: true, + pixelScale: 1 / 128, + color: [0, 1, 1, 1], + }), + textRenderer.formatText(font, 'Right', { + centered: true, + pixelScale: 1 / 128, + color: [0, 1, 0, 1], + }), + textRenderer.formatText(font, 'Left', { + centered: true, + pixelScale: 1 / 128, + color: [1, 0, 1, 1], + }), + textRenderer.formatText(font, 'Top', { + centered: true, + pixelScale: 1 / 128, + color: [0, 0, 1, 1], + }), + textRenderer.formatText(font, 'Bottom', { + centered: true, + pixelScale: 1 / 128, + color: [1, 1, 0, 1], + }), + titleText, + largeText, +]; +// Create a vertex buffer from the cube data. +const verticesBuffer = device.createBuffer({ + size: cubeVertexArray.byteLength, + usage: GPUBufferUsage.VERTEX, + mappedAtCreation: true, +}); +new Float32Array(verticesBuffer.getMappedRange()).set(cubeVertexArray); +verticesBuffer.unmap(); +const pipeline = device.createRenderPipeline({ + layout: 'auto', + vertex: { + module: device.createShaderModule({ + code: basicVertWGSL, + }), + buffers: [ + { + arrayStride: cubeVertexSize, + attributes: [ + { + // position + shaderLocation: 0, + offset: cubePositionOffset, + format: 'float32x4', + }, + { + // uv + shaderLocation: 1, + offset: cubeUVOffset, + format: 'float32x2', + }, + ], + }, + ], + }, + fragment: { + module: device.createShaderModule({ + code: vertexPositionColorWGSL, + }), + targets: [ + { + format: presentationFormat, + }, + ], + }, + primitive: { + // Backface culling since the cube is solid piece of geometry. + // Faces pointing away from the camera will be occluded by faces + // pointing toward the camera. + cullMode: 'back', + }, + // Enable depth testing so that the fragment closest to the camera + // is rendered in front. + depthStencil: { + depthWriteEnabled: true, + depthCompare: 'less', + format: depthFormat, + }, +}); +const depthTexture = device.createTexture({ + size: [canvas.width, canvas.height], + format: depthFormat, + usage: GPUTextureUsage.RENDER_ATTACHMENT, +}); +const uniformBufferSize = 4 * 16; // 4x4 matrix +const uniformBuffer = device.createBuffer({ + size: uniformBufferSize, + usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, +}); +const uniformBindGroup = device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [ + { + binding: 0, + resource: { + buffer: uniformBuffer, + }, + }, + ], +}); +const renderPassDescriptor = { + colorAttachments: [ + { + view: undefined, // Assigned later + clearValue: [0, 0, 0, 1], + loadOp: 'clear', + storeOp: 'store', + }, + ], + depthStencilAttachment: { + view: depthTexture.createView(), + depthClearValue: 1.0, + depthLoadOp: 'clear', + depthStoreOp: 'store', + }, +}; +const aspect = canvas.width / canvas.height; +const projectionMatrix = mat4Impl.perspective((2 * Math.PI) / 5, aspect, 1, 100.0); +const modelViewProjectionMatrix = mat4Impl.create(); +const start = Date.now(); +function getTransformationMatrix() { + const now = Date.now() / 5000; + const viewMatrix = mat4Impl.identity(); + mat4Impl.translate(viewMatrix, vec3Impl.fromValues(0, 0, -5), viewMatrix); + const modelMatrix = mat4Impl.identity(); + mat4Impl.translate(modelMatrix, vec3Impl.fromValues(0, 2, -3), modelMatrix); + mat4Impl.rotate(modelMatrix, vec3Impl.fromValues(Math.sin(now), Math.cos(now), 0), 1, modelMatrix); + // Update the matrix for the cube + mat4Impl.multiply(projectionMatrix, viewMatrix, modelViewProjectionMatrix); + mat4Impl.multiply(modelViewProjectionMatrix, modelMatrix, modelViewProjectionMatrix); + // Update the projection and view matrices for the text + textRenderer.updateCamera(projectionMatrix, viewMatrix); + // Update the transform of all the text surrounding the cube + const textMatrix = mat4Impl.create(); + for (const [index, transform] of textTransforms.entries()) { + mat4Impl.multiply(modelMatrix, transform, textMatrix); + text[index].setTransform(textMatrix); + } + // Update the transform of the larger block of text + const crawl = ((Date.now() - start) / 2500) % 14; + mat4Impl.identity(textMatrix); + mat4Impl.rotateX(textMatrix, -Math.PI / 8, textMatrix); + mat4Impl.translate(textMatrix, [0, crawl - 3, 0], textMatrix); + titleText.setTransform(textMatrix); + mat4Impl.translate(textMatrix, [-3, -0.1, 0], textMatrix); + largeText.setTransform(textMatrix); + return modelViewProjectionMatrix; +} +function frame() { + const transformationMatrix = getTransformationMatrix(); + device.queue.writeBuffer(uniformBuffer, 0, transformationMatrix.buffer, transformationMatrix.byteOffset, transformationMatrix.byteLength); + renderPassDescriptor.colorAttachments[0].view = context + .getCurrentTexture() + .createView(); + const commandEncoder = device.createCommandEncoder(); + const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); + passEncoder.setPipeline(pipeline); + passEncoder.setBindGroup(0, uniformBindGroup); + passEncoder.setVertexBuffer(0, verticesBuffer); + passEncoder.draw(cubeVertexCount, 1, 0, 0); + textRenderer.render(passEncoder, ...text); + passEncoder.end(); + device.queue.submit([commandEncoder.finish()]); + requestAnimationFrame(frame); +} +requestAnimationFrame(frame); +//# sourceMappingURL=main.js.map diff --git a/sample/textRenderingMsdf/main.js.map b/sample/textRenderingMsdf/main.js.map new file mode 100644 index 00000000..1c006731 --- /dev/null +++ b/sample/textRenderingMsdf/main.js.map @@ -0,0 +1 @@ +{"version":3,"file":"main.js","sources":["../../../node_modules/wgpu-matrix/dist/2.x/wgpu-matrix.module.js","../../../../../meshes/cube.ts","../../../../../sample/textRenderingMsdf/msdfText.ts","../../../../../sample/textRenderingMsdf/main.ts"],"sourcesContent":["/* wgpu-matrix@2.5.1, license MIT */\n/*\n * Copyright 2022 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\nlet EPSILON = 0.000001;\n/**\n * Set the value for EPSILON for various checks\n * @param v - Value to use for EPSILON.\n * @returns previous value of EPSILON;\n */\nfunction setEpsilon(v) {\n const old = EPSILON;\n EPSILON = v;\n return old;\n}\n/**\n * Convert degrees to radians\n * @param degrees - Angle in degrees\n * @returns angle converted to radians\n */\nfunction degToRad(degrees) {\n return degrees * Math.PI / 180;\n}\n/**\n * Convert radians to degrees\n * @param radians - Angle in radians\n * @returns angle converted to degrees\n */\nfunction radToDeg(radians) {\n return radians * 180 / Math.PI;\n}\n/**\n * Lerps between a and b via t\n * @param a - starting value\n * @param b - ending value\n * @param t - value where 0 = a and 1 = b\n * @returns a + (b - a) * t\n */\nfunction lerp$4(a, b, t) {\n return a + (b - a) * t;\n}\n/**\n * Compute the opposite of lerp. Given a and b and a value between\n * a and b returns a value between 0 and 1. 0 if a, 1 if b.\n * Note: no clamping is done.\n * @param a - start value\n * @param b - end value\n * @param v - value between a and b\n * @returns (v - a) / (b - a)\n */\nfunction inverseLerp(a, b, v) {\n const d = b - a;\n return (Math.abs(b - a) < EPSILON)\n ? a\n : (v - a) / d;\n}\n/**\n * Compute the euclidean modulo\n *\n * ```\n * // table for n / 3\n * -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5 <- n\n * ------------------------------------\n * -2 -1 -0 -2 -1 0, 1, 2, 0, 1, 2 <- n % 3\n * 1 2 0 1 2 0, 1, 2, 0, 1, 2 <- euclideanModule(n, 3)\n * ```\n *\n * @param n - dividend\n * @param m - divisor\n * @returns the euclidean modulo of n / m\n */\nfunction euclideanModulo(n, m) {\n return ((n % m) + m) % m;\n}\n\nvar utils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n get EPSILON () { return EPSILON; },\n setEpsilon: setEpsilon,\n degToRad: degToRad,\n radToDeg: radToDeg,\n lerp: lerp$4,\n inverseLerp: inverseLerp,\n euclideanModulo: euclideanModulo\n});\n\n/*\n * Copyright 2022 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n/**\n *\n * Vec2 math functions.\n *\n * Almost all functions take an optional `dst` argument. If it is not passed in the\n * functions will create a new Vec2. In other words you can do this\n *\n * const v = vec2.cross(v1, v2); // Creates a new Vec2 with the cross product of v1 x v2.\n *\n * or\n *\n * const v = vec2.create();\n * vec2.cross(v1, v2, v); // Puts the cross product of v1 x v2 in v\n *\n * The first style is often easier but depending on where it's used it generates garbage where\n * as there is almost never allocation with the second style.\n *\n * It is always safe to pass any vector as the destination. So for example\n *\n * vec2.cross(v1, v2, v1); // Puts the cross product of v1 x v2 in v1\n *\n */\nlet VecType$2 = Float32Array;\n/**\n * Sets the type this library creates for a Vec2\n * @param ctor - the constructor for the type. Either `Float32Array`, `Float64Array`, or `Array`\n * @returns previous constructor for Vec2\n */\nfunction setDefaultType$6(ctor) {\n const oldType = VecType$2;\n VecType$2 = ctor;\n return oldType;\n}\n/**\n * Creates a Vec2; may be called with x, y, z to set initial values.\n *\n * Note: Since passing in a raw JavaScript array\n * is valid in all circumstances, if you want to\n * force a JavaScript array into a Vec2's specified type\n * it would be faster to use\n *\n * ```\n * const v = vec2.clone(someJSArray);\n * ```\n *\n * Note: a consequence of the implementation is if your Vec2Type = `Array`\n * instead of `Float32Array` or `Float64Array` then any values you\n * don't pass in will be undefined. Usually this is not an issue since\n * (a) using `Array` is rare and (b) using `vec2.create` is usually used\n * to create a Vec2 to be filled out as in\n *\n * ```\n * const sum = vec2.create();\n * vec2.add(v1, v2, sum);\n * ```\n *\n * @param x - Initial x value.\n * @param y - Initial y value.\n * @returns the created vector\n */\nfunction create$5(x = 0, y = 0) {\n const dst = new VecType$2(2);\n if (x !== undefined) {\n dst[0] = x;\n if (y !== undefined) {\n dst[1] = y;\n }\n }\n return dst;\n}\n\n/*\n * Copyright 2022 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n/**\n *\n * Vec3 math functions.\n *\n * Almost all functions take an optional `dst` argument. If it is not passed in the\n * functions will create a new `Vec3`. In other words you can do this\n *\n * const v = vec3.cross(v1, v2); // Creates a new Vec3 with the cross product of v1 x v2.\n *\n * or\n *\n * const v = vec3.create();\n * vec3.cross(v1, v2, v); // Puts the cross product of v1 x v2 in v\n *\n * The first style is often easier but depending on where it's used it generates garbage where\n * as there is almost never allocation with the second style.\n *\n * It is always safe to pass any vector as the destination. So for example\n *\n * vec3.cross(v1, v2, v1); // Puts the cross product of v1 x v2 in v1\n *\n */\nlet VecType$1 = Float32Array;\n/**\n * Sets the type this library creates for a Vec3\n * @param ctor - the constructor for the type. Either `Float32Array`, `Float64Array`, or `Array`\n * @returns previous constructor for Vec3\n */\nfunction setDefaultType$5(ctor) {\n const oldType = VecType$1;\n VecType$1 = ctor;\n return oldType;\n}\n/**\n * Creates a vec3; may be called with x, y, z to set initial values.\n * @param x - Initial x value.\n * @param y - Initial y value.\n * @param z - Initial z value.\n * @returns the created vector\n */\nfunction create$4(x, y, z) {\n const dst = new VecType$1(3);\n if (x !== undefined) {\n dst[0] = x;\n if (y !== undefined) {\n dst[1] = y;\n if (z !== undefined) {\n dst[2] = z;\n }\n }\n }\n return dst;\n}\n\n/*\n * Copyright 2022 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n/**\n * Creates a Vec2; may be called with x, y, z to set initial values. (same as create)\n * @param x - Initial x value.\n * @param y - Initial y value.\n * @returns the created vector\n */\nconst fromValues$3 = create$5;\n/**\n * Sets the values of a Vec2\n * Also see {@link vec2.create} and {@link vec2.copy}\n *\n * @param x first value\n * @param y second value\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector with its elements set.\n */\nfunction set$5(x, y, dst) {\n dst = dst || new VecType$2(2);\n dst[0] = x;\n dst[1] = y;\n return dst;\n}\n/**\n * Applies Math.ceil to each element of vector\n * @param v - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the ceil of each element of v.\n */\nfunction ceil$2(v, dst) {\n dst = dst || new VecType$2(2);\n dst[0] = Math.ceil(v[0]);\n dst[1] = Math.ceil(v[1]);\n return dst;\n}\n/**\n * Applies Math.floor to each element of vector\n * @param v - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the floor of each element of v.\n */\nfunction floor$2(v, dst) {\n dst = dst || new VecType$2(2);\n dst[0] = Math.floor(v[0]);\n dst[1] = Math.floor(v[1]);\n return dst;\n}\n/**\n * Applies Math.round to each element of vector\n * @param v - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the round of each element of v.\n */\nfunction round$2(v, dst) {\n dst = dst || new VecType$2(2);\n dst[0] = Math.round(v[0]);\n dst[1] = Math.round(v[1]);\n return dst;\n}\n/**\n * Clamp each element of vector between min and max\n * @param v - Operand vector.\n * @param max - Min value, default 0\n * @param min - Max value, default 1\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that the clamped value of each element of v.\n */\nfunction clamp$2(v, min = 0, max = 1, dst) {\n dst = dst || new VecType$2(2);\n dst[0] = Math.min(max, Math.max(min, v[0]));\n dst[1] = Math.min(max, Math.max(min, v[1]));\n return dst;\n}\n/**\n * Adds two vectors; assumes a and b have the same dimension.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the sum of a and b.\n */\nfunction add$3(a, b, dst) {\n dst = dst || new VecType$2(2);\n dst[0] = a[0] + b[0];\n dst[1] = a[1] + b[1];\n return dst;\n}\n/**\n * Adds two vectors, scaling the 2nd; assumes a and b have the same dimension.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param scale - Amount to scale b\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the sum of a + b * scale.\n */\nfunction addScaled$2(a, b, scale, dst) {\n dst = dst || new VecType$2(2);\n dst[0] = a[0] + b[0] * scale;\n dst[1] = a[1] + b[1] * scale;\n return dst;\n}\n/**\n * Returns the angle in radians between two vectors.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @returns The angle in radians between the 2 vectors.\n */\nfunction angle$2(a, b) {\n const ax = a[0];\n const ay = a[1];\n const bx = a[0];\n const by = a[1];\n const mag1 = Math.sqrt(ax * ax + ay * ay);\n const mag2 = Math.sqrt(bx * bx + by * by);\n const mag = mag1 * mag2;\n const cosine = mag && dot$3(a, b) / mag;\n return Math.acos(cosine);\n}\n/**\n * Subtracts two vectors.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the difference of a and b.\n */\nfunction subtract$3(a, b, dst) {\n dst = dst || new VecType$2(2);\n dst[0] = a[0] - b[0];\n dst[1] = a[1] - b[1];\n return dst;\n}\n/**\n * Subtracts two vectors.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the difference of a and b.\n */\nconst sub$3 = subtract$3;\n/**\n * Check if 2 vectors are approximately equal\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @returns true if vectors are approximately equal\n */\nfunction equalsApproximately$5(a, b) {\n return Math.abs(a[0] - b[0]) < EPSILON &&\n Math.abs(a[1] - b[1]) < EPSILON;\n}\n/**\n * Check if 2 vectors are exactly equal\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @returns true if vectors are exactly equal\n */\nfunction equals$5(a, b) {\n return a[0] === b[0] && a[1] === b[1];\n}\n/**\n * Performs linear interpolation on two vectors.\n * Given vectors a and b and interpolation coefficient t, returns\n * a + t * (b - a).\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param t - Interpolation coefficient.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The linear interpolated result.\n */\nfunction lerp$3(a, b, t, dst) {\n dst = dst || new VecType$2(2);\n dst[0] = a[0] + t * (b[0] - a[0]);\n dst[1] = a[1] + t * (b[1] - a[1]);\n return dst;\n}\n/**\n * Performs linear interpolation on two vectors.\n * Given vectors a and b and interpolation coefficient vector t, returns\n * a + t * (b - a).\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param t - Interpolation coefficients vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns the linear interpolated result.\n */\nfunction lerpV$2(a, b, t, dst) {\n dst = dst || new VecType$2(2);\n dst[0] = a[0] + t[0] * (b[0] - a[0]);\n dst[1] = a[1] + t[1] * (b[1] - a[1]);\n return dst;\n}\n/**\n * Return max values of two vectors.\n * Given vectors a and b returns\n * [max(a[0], b[0]), max(a[1], b[1]), max(a[2], b[2])].\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The max components vector.\n */\nfunction max$2(a, b, dst) {\n dst = dst || new VecType$2(2);\n dst[0] = Math.max(a[0], b[0]);\n dst[1] = Math.max(a[1], b[1]);\n return dst;\n}\n/**\n * Return min values of two vectors.\n * Given vectors a and b returns\n * [min(a[0], b[0]), min(a[1], b[1]), min(a[2], b[2])].\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The min components vector.\n */\nfunction min$2(a, b, dst) {\n dst = dst || new VecType$2(2);\n dst[0] = Math.min(a[0], b[0]);\n dst[1] = Math.min(a[1], b[1]);\n return dst;\n}\n/**\n * Multiplies a vector by a scalar.\n * @param v - The vector.\n * @param k - The scalar.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The scaled vector.\n */\nfunction mulScalar$3(v, k, dst) {\n dst = dst || new VecType$2(2);\n dst[0] = v[0] * k;\n dst[1] = v[1] * k;\n return dst;\n}\n/**\n * Multiplies a vector by a scalar. (same as mulScalar)\n * @param v - The vector.\n * @param k - The scalar.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The scaled vector.\n */\nconst scale$5 = mulScalar$3;\n/**\n * Divides a vector by a scalar.\n * @param v - The vector.\n * @param k - The scalar.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The scaled vector.\n */\nfunction divScalar$3(v, k, dst) {\n dst = dst || new VecType$2(2);\n dst[0] = v[0] / k;\n dst[1] = v[1] / k;\n return dst;\n}\n/**\n * Inverse a vector.\n * @param v - The vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The inverted vector.\n */\nfunction inverse$5(v, dst) {\n dst = dst || new VecType$2(2);\n dst[0] = 1 / v[0];\n dst[1] = 1 / v[1];\n return dst;\n}\n/**\n * Invert a vector. (same as inverse)\n * @param v - The vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The inverted vector.\n */\nconst invert$4 = inverse$5;\n/**\n * Computes the cross product of two vectors; assumes both vectors have\n * three entries.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The vector of a cross b.\n */\nfunction cross$1(a, b, dst) {\n dst = dst || new VecType$1(3);\n const z = a[0] * b[1] - a[1] * b[0];\n dst[0] = 0;\n dst[1] = 0;\n dst[2] = z;\n return dst;\n}\n/**\n * Computes the dot product of two vectors; assumes both vectors have\n * three entries.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @returns dot product\n */\nfunction dot$3(a, b) {\n return a[0] * b[0] + a[1] * b[1];\n}\n/**\n * Computes the length of vector\n * @param v - vector.\n * @returns length of vector.\n */\nfunction length$3(v) {\n const v0 = v[0];\n const v1 = v[1];\n return Math.sqrt(v0 * v0 + v1 * v1);\n}\n/**\n * Computes the length of vector (same as length)\n * @param v - vector.\n * @returns length of vector.\n */\nconst len$3 = length$3;\n/**\n * Computes the square of the length of vector\n * @param v - vector.\n * @returns square of the length of vector.\n */\nfunction lengthSq$3(v) {\n const v0 = v[0];\n const v1 = v[1];\n return v0 * v0 + v1 * v1;\n}\n/**\n * Computes the square of the length of vector (same as lengthSq)\n * @param v - vector.\n * @returns square of the length of vector.\n */\nconst lenSq$3 = lengthSq$3;\n/**\n * Computes the distance between 2 points\n * @param a - vector.\n * @param b - vector.\n * @returns distance between a and b\n */\nfunction distance$2(a, b) {\n const dx = a[0] - b[0];\n const dy = a[1] - b[1];\n return Math.sqrt(dx * dx + dy * dy);\n}\n/**\n * Computes the distance between 2 points (same as distance)\n * @param a - vector.\n * @param b - vector.\n * @returns distance between a and b\n */\nconst dist$2 = distance$2;\n/**\n * Computes the square of the distance between 2 points\n * @param a - vector.\n * @param b - vector.\n * @returns square of the distance between a and b\n */\nfunction distanceSq$2(a, b) {\n const dx = a[0] - b[0];\n const dy = a[1] - b[1];\n return dx * dx + dy * dy;\n}\n/**\n * Computes the square of the distance between 2 points (same as distanceSq)\n * @param a - vector.\n * @param b - vector.\n * @returns square of the distance between a and b\n */\nconst distSq$2 = distanceSq$2;\n/**\n * Divides a vector by its Euclidean length and returns the quotient.\n * @param v - The vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The normalized vector.\n */\nfunction normalize$3(v, dst) {\n dst = dst || new VecType$2(2);\n const v0 = v[0];\n const v1 = v[1];\n const len = Math.sqrt(v0 * v0 + v1 * v1);\n if (len > 0.00001) {\n dst[0] = v0 / len;\n dst[1] = v1 / len;\n }\n else {\n dst[0] = 0;\n dst[1] = 0;\n }\n return dst;\n}\n/**\n * Negates a vector.\n * @param v - The vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns -v.\n */\nfunction negate$4(v, dst) {\n dst = dst || new VecType$2(2);\n dst[0] = -v[0];\n dst[1] = -v[1];\n return dst;\n}\n/**\n * Copies a vector. (same as {@link vec2.clone})\n * Also see {@link vec2.create} and {@link vec2.set}\n * @param v - The vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A copy of v.\n */\nfunction copy$5(v, dst) {\n dst = dst || new VecType$2(2);\n dst[0] = v[0];\n dst[1] = v[1];\n return dst;\n}\n/**\n * Clones a vector. (same as {@link vec2.copy})\n * Also see {@link vec2.create} and {@link vec2.set}\n * @param v - The vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A copy of v.\n */\nconst clone$5 = copy$5;\n/**\n * Multiplies a vector by another vector (component-wise); assumes a and\n * b have the same length.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The vector of products of entries of a and b.\n */\nfunction multiply$5(a, b, dst) {\n dst = dst || new VecType$2(2);\n dst[0] = a[0] * b[0];\n dst[1] = a[1] * b[1];\n return dst;\n}\n/**\n * Multiplies a vector by another vector (component-wise); assumes a and\n * b have the same length. (same as mul)\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The vector of products of entries of a and b.\n */\nconst mul$5 = multiply$5;\n/**\n * Divides a vector by another vector (component-wise); assumes a and\n * b have the same length.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The vector of quotients of entries of a and b.\n */\nfunction divide$2(a, b, dst) {\n dst = dst || new VecType$2(2);\n dst[0] = a[0] / b[0];\n dst[1] = a[1] / b[1];\n return dst;\n}\n/**\n * Divides a vector by another vector (component-wise); assumes a and\n * b have the same length. (same as divide)\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The vector of quotients of entries of a and b.\n */\nconst div$2 = divide$2;\n/**\n * Creates a random unit vector * scale\n * @param scale - Default 1\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The random vector.\n */\nfunction random$1(scale = 1, dst) {\n dst = dst || new VecType$2(2);\n const angle = Math.random() * 2 * Math.PI;\n dst[0] = Math.cos(angle) * scale;\n dst[1] = Math.sin(angle) * scale;\n return dst;\n}\n/**\n * Zero's a vector\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The zeroed vector.\n */\nfunction zero$2(dst) {\n dst = dst || new VecType$2(2);\n dst[0] = 0;\n dst[1] = 0;\n return dst;\n}\n/**\n * transform Vec2 by 4x4 matrix\n * @param v - the vector\n * @param m - The matrix.\n * @param dst - optional Vec2 to store result. If not passed a new one is created.\n * @returns the transformed vector\n */\nfunction transformMat4$2(v, m, dst) {\n dst = dst || new VecType$2(2);\n const x = v[0];\n const y = v[1];\n dst[0] = x * m[0] + y * m[4] + m[12];\n dst[1] = x * m[1] + y * m[5] + m[13];\n return dst;\n}\n/**\n * Transforms vec4 by 3x3 matrix\n *\n * @param v - the vector\n * @param m - The matrix.\n * @param dst - optional Vec2 to store result. If not passed a new one is created.\n * @returns the transformed vector\n */\nfunction transformMat3$1(v, m, dst) {\n dst = dst || new VecType$2(2);\n const x = v[0];\n const y = v[1];\n dst[0] = m[0] * x + m[4] * y + m[8];\n dst[1] = m[1] * x + m[5] * y + m[9];\n return dst;\n}\n\nvar vec2Impl = /*#__PURE__*/Object.freeze({\n __proto__: null,\n create: create$5,\n setDefaultType: setDefaultType$6,\n fromValues: fromValues$3,\n set: set$5,\n ceil: ceil$2,\n floor: floor$2,\n round: round$2,\n clamp: clamp$2,\n add: add$3,\n addScaled: addScaled$2,\n angle: angle$2,\n subtract: subtract$3,\n sub: sub$3,\n equalsApproximately: equalsApproximately$5,\n equals: equals$5,\n lerp: lerp$3,\n lerpV: lerpV$2,\n max: max$2,\n min: min$2,\n mulScalar: mulScalar$3,\n scale: scale$5,\n divScalar: divScalar$3,\n inverse: inverse$5,\n invert: invert$4,\n cross: cross$1,\n dot: dot$3,\n length: length$3,\n len: len$3,\n lengthSq: lengthSq$3,\n lenSq: lenSq$3,\n distance: distance$2,\n dist: dist$2,\n distanceSq: distanceSq$2,\n distSq: distSq$2,\n normalize: normalize$3,\n negate: negate$4,\n copy: copy$5,\n clone: clone$5,\n multiply: multiply$5,\n mul: mul$5,\n divide: divide$2,\n div: div$2,\n random: random$1,\n zero: zero$2,\n transformMat4: transformMat4$2,\n transformMat3: transformMat3$1\n});\n\n/*\n * Copyright 2022 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n/**\n * 3x3 Matrix math math functions.\n *\n * Almost all functions take an optional `dst` argument. If it is not passed in the\n * functions will create a new matrix. In other words you can do this\n *\n * const mat = mat3.translation([1, 2, 3]); // Creates a new translation matrix\n *\n * or\n *\n * const mat = mat3.create();\n * mat3.translation([1, 2, 3], mat); // Puts translation matrix in mat.\n *\n * The first style is often easier but depending on where it's used it generates garbage where\n * as there is almost never allocation with the second style.\n *\n * It is always save to pass any matrix as the destination. So for example\n *\n * const mat = mat3.identity();\n * const trans = mat3.translation([1, 2, 3]);\n * mat3.multiply(mat, trans, mat); // Multiplies mat * trans and puts result in mat.\n *\n */\nlet MatType$1 = Float32Array;\n// This mess is because with Mat3 we have 3 unused elements.\n// For Float32Array and Float64Array that's not an issue\n// but for Array it's troublesome\nconst ctorMap = new Map([\n [Float32Array, () => new Float32Array(12)],\n [Float64Array, () => new Float64Array(12)],\n [Array, () => new Array(12).fill(0)],\n]);\nlet newMat3 = ctorMap.get(Float32Array);\n/**\n * Sets the type this library creates for a Mat3\n * @param ctor - the constructor for the type. Either `Float32Array`, `Float64Array`, or `Array`\n * @returns previous constructor for Mat3\n */\nfunction setDefaultType$4(ctor) {\n const oldType = MatType$1;\n MatType$1 = ctor;\n newMat3 = ctorMap.get(ctor);\n return oldType;\n}\n/**\n * Create a Mat3 from values\n *\n * Note: Since passing in a raw JavaScript array\n * is valid in all circumstances, if you want to\n * force a JavaScript array into a Mat3's specified type\n * it would be faster to use\n *\n * ```\n * const m = mat3.clone(someJSArray);\n * ```\n *\n * Note: a consequence of the implementation is if your Mat3Type = `Array`\n * instead of `Float32Array` or `Float64Array` then any values you\n * don't pass in will be undefined. Usually this is not an issue since\n * (a) using `Array` is rare and (b) using `mat3.create` is usually used\n * to create a Mat3 to be filled out as in\n *\n * ```\n * const m = mat3.create();\n * mat3.perspective(fov, aspect, near, far, m);\n * ```\n *\n * @param v0 - value for element 0\n * @param v1 - value for element 1\n * @param v2 - value for element 2\n * @param v3 - value for element 3\n * @param v4 - value for element 4\n * @param v5 - value for element 5\n * @param v6 - value for element 6\n * @param v7 - value for element 7\n * @param v8 - value for element 8\n * @returns matrix created from values.\n */\nfunction create$3(v0, v1, v2, v3, v4, v5, v6, v7, v8) {\n const dst = newMat3();\n // to make the array homogenous\n dst[3] = 0;\n dst[7] = 0;\n dst[11] = 0;\n if (v0 !== undefined) {\n dst[0] = v0;\n if (v1 !== undefined) {\n dst[1] = v1;\n if (v2 !== undefined) {\n dst[2] = v2;\n if (v3 !== undefined) {\n dst[4] = v3;\n if (v4 !== undefined) {\n dst[5] = v4;\n if (v5 !== undefined) {\n dst[6] = v5;\n if (v6 !== undefined) {\n dst[8] = v6;\n if (v7 !== undefined) {\n dst[9] = v7;\n if (v8 !== undefined) {\n dst[10] = v8;\n }\n }\n }\n }\n }\n }\n }\n }\n }\n return dst;\n}\n/**\n * Sets the values of a Mat3\n * Also see {@link mat3.create} and {@link mat3.copy}\n *\n * @param v0 - value for element 0\n * @param v1 - value for element 1\n * @param v2 - value for element 2\n * @param v3 - value for element 3\n * @param v4 - value for element 4\n * @param v5 - value for element 5\n * @param v6 - value for element 6\n * @param v7 - value for element 7\n * @param v8 - value for element 8\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns Mat3 set from values.\n */\nfunction set$4(v0, v1, v2, v3, v4, v5, v6, v7, v8, dst) {\n dst = dst || newMat3();\n dst[0] = v0;\n dst[1] = v1;\n dst[2] = v2;\n dst[3] = 0;\n dst[4] = v3;\n dst[5] = v4;\n dst[6] = v5;\n dst[7] = 0;\n dst[8] = v6;\n dst[9] = v7;\n dst[10] = v8;\n dst[11] = 0;\n return dst;\n}\n/**\n * Creates a Mat3 from the upper left 3x3 part of a Mat4\n * @param m4 - source matrix\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns Mat3 made from m4\n */\nfunction fromMat4(m4, dst) {\n dst = dst || newMat3();\n dst[0] = m4[0];\n dst[1] = m4[1];\n dst[2] = m4[2];\n dst[3] = 0;\n dst[4] = m4[4];\n dst[5] = m4[5];\n dst[6] = m4[6];\n dst[7] = 0;\n dst[8] = m4[8];\n dst[9] = m4[9];\n dst[10] = m4[10];\n dst[11] = 0;\n return dst;\n}\n/**\n * Creates a Mat3 rotation matrix from a quaternion\n * @param q - quaternion to create matrix from\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns Mat3 made from q\n */\nfunction fromQuat$1(q, dst) {\n dst = dst || newMat3();\n const x = q[0];\n const y = q[1];\n const z = q[2];\n const w = q[3];\n const x2 = x + x;\n const y2 = y + y;\n const z2 = z + z;\n const xx = x * x2;\n const yx = y * x2;\n const yy = y * y2;\n const zx = z * x2;\n const zy = z * y2;\n const zz = z * z2;\n const wx = w * x2;\n const wy = w * y2;\n const wz = w * z2;\n dst[0] = 1 - yy - zz;\n dst[1] = yx + wz;\n dst[2] = zx - wy;\n dst[3] = 0;\n dst[4] = yx - wz;\n dst[5] = 1 - xx - zz;\n dst[6] = zy + wx;\n dst[7] = 0;\n dst[8] = zx + wy;\n dst[9] = zy - wx;\n dst[10] = 1 - xx - yy;\n dst[11] = 0;\n return dst;\n}\n/**\n * Negates a matrix.\n * @param m - The matrix.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns -m.\n */\nfunction negate$3(m, dst) {\n dst = dst || newMat3();\n dst[0] = -m[0];\n dst[1] = -m[1];\n dst[2] = -m[2];\n dst[4] = -m[4];\n dst[5] = -m[5];\n dst[6] = -m[6];\n dst[8] = -m[8];\n dst[9] = -m[9];\n dst[10] = -m[10];\n return dst;\n}\n/**\n * Copies a matrix. (same as {@link mat3.clone})\n * Also see {@link mat3.create} and {@link mat3.set}\n * @param m - The matrix.\n * @param dst - The matrix. If not passed a new one is created.\n * @returns A copy of m.\n */\nfunction copy$4(m, dst) {\n dst = dst || newMat3();\n dst[0] = m[0];\n dst[1] = m[1];\n dst[2] = m[2];\n dst[4] = m[4];\n dst[5] = m[5];\n dst[6] = m[6];\n dst[8] = m[8];\n dst[9] = m[9];\n dst[10] = m[10];\n return dst;\n}\n/**\n * Copies a matrix (same as {@link mat3.copy})\n * Also see {@link mat3.create} and {@link mat3.set}\n * @param m - The matrix.\n * @param dst - The matrix. If not passed a new one is created.\n * @returns A copy of m.\n */\nconst clone$4 = copy$4;\n/**\n * Check if 2 matrices are approximately equal\n * @param a Operand matrix.\n * @param b Operand matrix.\n * @returns true if matrices are approximately equal\n */\nfunction equalsApproximately$4(a, b) {\n return Math.abs(a[0] - b[0]) < EPSILON &&\n Math.abs(a[1] - b[1]) < EPSILON &&\n Math.abs(a[2] - b[2]) < EPSILON &&\n Math.abs(a[4] - b[4]) < EPSILON &&\n Math.abs(a[5] - b[5]) < EPSILON &&\n Math.abs(a[6] - b[6]) < EPSILON &&\n Math.abs(a[8] - b[8]) < EPSILON &&\n Math.abs(a[9] - b[9]) < EPSILON &&\n Math.abs(a[10] - b[10]) < EPSILON;\n}\n/**\n * Check if 2 matrices are exactly equal\n * @param a Operand matrix.\n * @param b Operand matrix.\n * @returns true if matrices are exactly equal\n */\nfunction equals$4(a, b) {\n return a[0] === b[0] &&\n a[1] === b[1] &&\n a[2] === b[2] &&\n a[4] === b[4] &&\n a[5] === b[5] &&\n a[6] === b[6] &&\n a[8] === b[8] &&\n a[9] === b[9] &&\n a[10] === b[10];\n}\n/**\n * Creates a 3-by-3 identity matrix.\n *\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns A 3-by-3 identity matrix.\n */\nfunction identity$2(dst) {\n dst = dst || newMat3();\n dst[0] = 1;\n dst[1] = 0;\n dst[2] = 0;\n dst[4] = 0;\n dst[5] = 1;\n dst[6] = 0;\n dst[8] = 0;\n dst[9] = 0;\n dst[10] = 1;\n return dst;\n}\n/**\n * Takes the transpose of a matrix.\n * @param m - The matrix.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The transpose of m.\n */\nfunction transpose$1(m, dst) {\n dst = dst || newMat3();\n if (dst === m) {\n let t;\n // 0 1 2\n // 4 5 6\n // 8 9 10\n t = m[1];\n m[1] = m[4];\n m[4] = t;\n t = m[2];\n m[2] = m[8];\n m[8] = t;\n t = m[6];\n m[6] = m[9];\n m[9] = t;\n return dst;\n }\n const m00 = m[0 * 4 + 0];\n const m01 = m[0 * 4 + 1];\n const m02 = m[0 * 4 + 2];\n const m10 = m[1 * 4 + 0];\n const m11 = m[1 * 4 + 1];\n const m12 = m[1 * 4 + 2];\n const m20 = m[2 * 4 + 0];\n const m21 = m[2 * 4 + 1];\n const m22 = m[2 * 4 + 2];\n dst[0] = m00;\n dst[1] = m10;\n dst[2] = m20;\n dst[4] = m01;\n dst[5] = m11;\n dst[6] = m21;\n dst[8] = m02;\n dst[9] = m12;\n dst[10] = m22;\n return dst;\n}\n/**\n * Computes the inverse of a 3-by-3 matrix.\n * @param m - The matrix.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The inverse of m.\n */\nfunction inverse$4(m, dst) {\n dst = dst || newMat3();\n const m00 = m[0 * 4 + 0];\n const m01 = m[0 * 4 + 1];\n const m02 = m[0 * 4 + 2];\n const m10 = m[1 * 4 + 0];\n const m11 = m[1 * 4 + 1];\n const m12 = m[1 * 4 + 2];\n const m20 = m[2 * 4 + 0];\n const m21 = m[2 * 4 + 1];\n const m22 = m[2 * 4 + 2];\n const b01 = m22 * m11 - m12 * m21;\n const b11 = -m22 * m10 + m12 * m20;\n const b21 = m21 * m10 - m11 * m20;\n const invDet = 1 / (m00 * b01 + m01 * b11 + m02 * b21);\n dst[0] = b01 * invDet;\n dst[1] = (-m22 * m01 + m02 * m21) * invDet;\n dst[2] = (m12 * m01 - m02 * m11) * invDet;\n dst[4] = b11 * invDet;\n dst[5] = (m22 * m00 - m02 * m20) * invDet;\n dst[6] = (-m12 * m00 + m02 * m10) * invDet;\n dst[8] = b21 * invDet;\n dst[9] = (-m21 * m00 + m01 * m20) * invDet;\n dst[10] = (m11 * m00 - m01 * m10) * invDet;\n return dst;\n}\n/**\n * Compute the determinant of a matrix\n * @param m - the matrix\n * @returns the determinant\n */\nfunction determinant$1(m) {\n const m00 = m[0 * 4 + 0];\n const m01 = m[0 * 4 + 1];\n const m02 = m[0 * 4 + 2];\n const m10 = m[1 * 4 + 0];\n const m11 = m[1 * 4 + 1];\n const m12 = m[1 * 4 + 2];\n const m20 = m[2 * 4 + 0];\n const m21 = m[2 * 4 + 1];\n const m22 = m[2 * 4 + 2];\n return m00 * (m11 * m22 - m21 * m12) -\n m10 * (m01 * m22 - m21 * m02) +\n m20 * (m01 * m12 - m11 * m02);\n}\n/**\n * Computes the inverse of a 3-by-3 matrix. (same as inverse)\n * @param m - The matrix.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The inverse of m.\n */\nconst invert$3 = inverse$4;\n/**\n * Multiplies two 3-by-3 matrices with a on the left and b on the right\n * @param a - The matrix on the left.\n * @param b - The matrix on the right.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The matrix product of a and b.\n */\nfunction multiply$4(a, b, dst) {\n dst = dst || newMat3();\n const a00 = a[0];\n const a01 = a[1];\n const a02 = a[2];\n const a10 = a[4 + 0];\n const a11 = a[4 + 1];\n const a12 = a[4 + 2];\n const a20 = a[8 + 0];\n const a21 = a[8 + 1];\n const a22 = a[8 + 2];\n const b00 = b[0];\n const b01 = b[1];\n const b02 = b[2];\n const b10 = b[4 + 0];\n const b11 = b[4 + 1];\n const b12 = b[4 + 2];\n const b20 = b[8 + 0];\n const b21 = b[8 + 1];\n const b22 = b[8 + 2];\n dst[0] = a00 * b00 + a10 * b01 + a20 * b02;\n dst[1] = a01 * b00 + a11 * b01 + a21 * b02;\n dst[2] = a02 * b00 + a12 * b01 + a22 * b02;\n dst[4] = a00 * b10 + a10 * b11 + a20 * b12;\n dst[5] = a01 * b10 + a11 * b11 + a21 * b12;\n dst[6] = a02 * b10 + a12 * b11 + a22 * b12;\n dst[8] = a00 * b20 + a10 * b21 + a20 * b22;\n dst[9] = a01 * b20 + a11 * b21 + a21 * b22;\n dst[10] = a02 * b20 + a12 * b21 + a22 * b22;\n return dst;\n}\n/**\n * Multiplies two 3-by-3 matrices with a on the left and b on the right (same as multiply)\n * @param a - The matrix on the left.\n * @param b - The matrix on the right.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The matrix product of a and b.\n */\nconst mul$4 = multiply$4;\n/**\n * Sets the translation component of a 3-by-3 matrix to the given\n * vector.\n * @param a - The matrix.\n * @param v - The vector.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The matrix with translation set.\n */\nfunction setTranslation$1(a, v, dst) {\n dst = dst || identity$2();\n if (a !== dst) {\n dst[0] = a[0];\n dst[1] = a[1];\n dst[2] = a[2];\n dst[4] = a[4];\n dst[5] = a[5];\n dst[6] = a[6];\n }\n dst[8] = v[0];\n dst[9] = v[1];\n dst[10] = 1;\n return dst;\n}\n/**\n * Returns the translation component of a 3-by-3 matrix as a vector with 3\n * entries.\n * @param m - The matrix.\n * @param dst - vector to hold result. If not passed a new one is created.\n * @returns The translation component of m.\n */\nfunction getTranslation$2(m, dst) {\n dst = dst || create$5();\n dst[0] = m[8];\n dst[1] = m[9];\n return dst;\n}\n/**\n * Returns an axis of a 3x3 matrix as a vector with 2 entries\n * @param m - The matrix.\n * @param axis - The axis 0 = x, 1 = y,\n * @returns The axis component of m.\n */\nfunction getAxis$2(m, axis, dst) {\n dst = dst || create$5();\n const off = axis * 4;\n dst[0] = m[off + 0];\n dst[1] = m[off + 1];\n return dst;\n}\n/**\n * Sets an axis of a 3x3 matrix as a vector with 2 entries\n * @param m - The matrix.\n * @param v - the axis vector\n * @param axis - The axis 0 = x, 1 = y;\n * @param dst - The matrix to set. If not passed a new one is created.\n * @returns The matrix with axis set.\n */\nfunction setAxis$1(m, v, axis, dst) {\n if (dst !== m) {\n dst = copy$4(m, dst);\n }\n const off = axis * 4;\n dst[off + 0] = v[0];\n dst[off + 1] = v[1];\n return dst;\n}\n/**\n * Returns the scaling component of the matrix\n * @param m - The Matrix\n * @param dst - The vector to set. If not passed a new one is created.\n */\nfunction getScaling$2(m, dst) {\n dst = dst || create$5();\n const xx = m[0];\n const xy = m[1];\n const yx = m[4];\n const yy = m[5];\n dst[0] = Math.sqrt(xx * xx + xy * xy);\n dst[1] = Math.sqrt(yx * yx + yy * yy);\n return dst;\n}\n/**\n * Creates a 3-by-3 matrix which translates by the given vector v.\n * @param v - The vector by which to translate.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The translation matrix.\n */\nfunction translation$1(v, dst) {\n dst = dst || newMat3();\n dst[0] = 1;\n dst[1] = 0;\n dst[2] = 0;\n dst[4] = 0;\n dst[5] = 1;\n dst[6] = 0;\n dst[8] = v[0];\n dst[9] = v[1];\n dst[10] = 1;\n return dst;\n}\n/**\n * Translates the given 3-by-3 matrix by the given vector v.\n * @param m - The matrix.\n * @param v - The vector by which to translate.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The translated matrix.\n */\nfunction translate$1(m, v, dst) {\n dst = dst || newMat3();\n const v0 = v[0];\n const v1 = v[1];\n const m00 = m[0];\n const m01 = m[1];\n const m02 = m[2];\n const m10 = m[1 * 4 + 0];\n const m11 = m[1 * 4 + 1];\n const m12 = m[1 * 4 + 2];\n const m20 = m[2 * 4 + 0];\n const m21 = m[2 * 4 + 1];\n const m22 = m[2 * 4 + 2];\n if (m !== dst) {\n dst[0] = m00;\n dst[1] = m01;\n dst[2] = m02;\n dst[4] = m10;\n dst[5] = m11;\n dst[6] = m12;\n }\n dst[8] = m00 * v0 + m10 * v1 + m20;\n dst[9] = m01 * v0 + m11 * v1 + m21;\n dst[10] = m02 * v0 + m12 * v1 + m22;\n return dst;\n}\n/**\n * Creates a 3-by-3 matrix which rotates by the given angle.\n * @param angleInRadians - The angle by which to rotate (in radians).\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The rotation matrix.\n */\nfunction rotation$1(angleInRadians, dst) {\n dst = dst || newMat3();\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n dst[0] = c;\n dst[1] = s;\n dst[2] = 0;\n dst[4] = -s;\n dst[5] = c;\n dst[6] = 0;\n dst[8] = 0;\n dst[9] = 0;\n dst[10] = 1;\n return dst;\n}\n/**\n * Rotates the given 3-by-3 matrix by the given angle.\n * @param m - The matrix.\n * @param angleInRadians - The angle by which to rotate (in radians).\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The rotated matrix.\n */\nfunction rotate$1(m, angleInRadians, dst) {\n dst = dst || newMat3();\n const m00 = m[0 * 4 + 0];\n const m01 = m[0 * 4 + 1];\n const m02 = m[0 * 4 + 2];\n const m10 = m[1 * 4 + 0];\n const m11 = m[1 * 4 + 1];\n const m12 = m[1 * 4 + 2];\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n dst[0] = c * m00 + s * m10;\n dst[1] = c * m01 + s * m11;\n dst[2] = c * m02 + s * m12;\n dst[4] = c * m10 - s * m00;\n dst[5] = c * m11 - s * m01;\n dst[6] = c * m12 - s * m02;\n if (m !== dst) {\n dst[8] = m[8];\n dst[9] = m[9];\n dst[10] = m[10];\n }\n return dst;\n}\n/**\n * Creates a 3-by-3 matrix which scales in each dimension by an amount given by\n * the corresponding entry in the given vector; assumes the vector has three\n * entries.\n * @param v - A vector of\n * 2 entries specifying the factor by which to scale in each dimension.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The scaling matrix.\n */\nfunction scaling$1(v, dst) {\n dst = dst || newMat3();\n dst[0] = v[0];\n dst[1] = 0;\n dst[2] = 0;\n dst[4] = 0;\n dst[5] = v[1];\n dst[6] = 0;\n dst[8] = 0;\n dst[9] = 0;\n dst[10] = 1;\n return dst;\n}\n/**\n * Scales the given 3-by-3 matrix in each dimension by an amount\n * given by the corresponding entry in the given vector; assumes the vector has\n * three entries.\n * @param m - The matrix to be modified.\n * @param v - A vector of 2 entries specifying the\n * factor by which to scale in each dimension.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The scaled matrix.\n */\nfunction scale$4(m, v, dst) {\n dst = dst || newMat3();\n const v0 = v[0];\n const v1 = v[1];\n dst[0] = v0 * m[0 * 4 + 0];\n dst[1] = v0 * m[0 * 4 + 1];\n dst[2] = v0 * m[0 * 4 + 2];\n dst[4] = v1 * m[1 * 4 + 0];\n dst[5] = v1 * m[1 * 4 + 1];\n dst[6] = v1 * m[1 * 4 + 2];\n if (m !== dst) {\n dst[8] = m[8];\n dst[9] = m[9];\n dst[10] = m[10];\n }\n return dst;\n}\n/**\n * Creates a 3-by-3 matrix which scales uniformly in each dimension\n * @param s - Amount to scale\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The scaling matrix.\n */\nfunction uniformScaling$1(s, dst) {\n dst = dst || newMat3();\n dst[0] = s;\n dst[1] = 0;\n dst[2] = 0;\n dst[4] = 0;\n dst[5] = s;\n dst[6] = 0;\n dst[8] = 0;\n dst[9] = 0;\n dst[10] = 1;\n return dst;\n}\n/**\n * Scales the given 3-by-3 matrix in each dimension by an amount\n * given.\n * @param m - The matrix to be modified.\n * @param s - Amount to scale.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The scaled matrix.\n */\nfunction uniformScale$1(m, s, dst) {\n dst = dst || newMat3();\n dst[0] = s * m[0 * 4 + 0];\n dst[1] = s * m[0 * 4 + 1];\n dst[2] = s * m[0 * 4 + 2];\n dst[4] = s * m[1 * 4 + 0];\n dst[5] = s * m[1 * 4 + 1];\n dst[6] = s * m[1 * 4 + 2];\n if (m !== dst) {\n dst[8] = m[8];\n dst[9] = m[9];\n dst[10] = m[10];\n }\n return dst;\n}\n\nvar mat3Impl = /*#__PURE__*/Object.freeze({\n __proto__: null,\n setDefaultType: setDefaultType$4,\n create: create$3,\n set: set$4,\n fromMat4: fromMat4,\n fromQuat: fromQuat$1,\n negate: negate$3,\n copy: copy$4,\n clone: clone$4,\n equalsApproximately: equalsApproximately$4,\n equals: equals$4,\n identity: identity$2,\n transpose: transpose$1,\n inverse: inverse$4,\n determinant: determinant$1,\n invert: invert$3,\n multiply: multiply$4,\n mul: mul$4,\n setTranslation: setTranslation$1,\n getTranslation: getTranslation$2,\n getAxis: getAxis$2,\n setAxis: setAxis$1,\n getScaling: getScaling$2,\n translation: translation$1,\n translate: translate$1,\n rotation: rotation$1,\n rotate: rotate$1,\n scaling: scaling$1,\n scale: scale$4,\n uniformScaling: uniformScaling$1,\n uniformScale: uniformScale$1\n});\n\n/*\n * Copyright 2022 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n/**\n * Creates a vec3; may be called with x, y, z to set initial values. (same as create)\n * @param x - Initial x value.\n * @param y - Initial y value.\n * @param z - Initial z value.\n * @returns the created vector\n */\nconst fromValues$2 = create$4;\n/**\n * Sets the values of a Vec3\n * Also see {@link vec3.create} and {@link vec3.copy}\n *\n * @param x first value\n * @param y second value\n * @param z third value\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector with its elements set.\n */\nfunction set$3(x, y, z, dst) {\n dst = dst || new VecType$1(3);\n dst[0] = x;\n dst[1] = y;\n dst[2] = z;\n return dst;\n}\n/**\n * Applies Math.ceil to each element of vector\n * @param v - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the ceil of each element of v.\n */\nfunction ceil$1(v, dst) {\n dst = dst || new VecType$1(3);\n dst[0] = Math.ceil(v[0]);\n dst[1] = Math.ceil(v[1]);\n dst[2] = Math.ceil(v[2]);\n return dst;\n}\n/**\n * Applies Math.floor to each element of vector\n * @param v - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the floor of each element of v.\n */\nfunction floor$1(v, dst) {\n dst = dst || new VecType$1(3);\n dst[0] = Math.floor(v[0]);\n dst[1] = Math.floor(v[1]);\n dst[2] = Math.floor(v[2]);\n return dst;\n}\n/**\n * Applies Math.round to each element of vector\n * @param v - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the round of each element of v.\n */\nfunction round$1(v, dst) {\n dst = dst || new VecType$1(3);\n dst[0] = Math.round(v[0]);\n dst[1] = Math.round(v[1]);\n dst[2] = Math.round(v[2]);\n return dst;\n}\n/**\n * Clamp each element of vector between min and max\n * @param v - Operand vector.\n * @param max - Min value, default 0\n * @param min - Max value, default 1\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that the clamped value of each element of v.\n */\nfunction clamp$1(v, min = 0, max = 1, dst) {\n dst = dst || new VecType$1(3);\n dst[0] = Math.min(max, Math.max(min, v[0]));\n dst[1] = Math.min(max, Math.max(min, v[1]));\n dst[2] = Math.min(max, Math.max(min, v[2]));\n return dst;\n}\n/**\n * Adds two vectors; assumes a and b have the same dimension.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the sum of a and b.\n */\nfunction add$2(a, b, dst) {\n dst = dst || new VecType$1(3);\n dst[0] = a[0] + b[0];\n dst[1] = a[1] + b[1];\n dst[2] = a[2] + b[2];\n return dst;\n}\n/**\n * Adds two vectors, scaling the 2nd; assumes a and b have the same dimension.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param scale - Amount to scale b\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the sum of a + b * scale.\n */\nfunction addScaled$1(a, b, scale, dst) {\n dst = dst || new VecType$1(3);\n dst[0] = a[0] + b[0] * scale;\n dst[1] = a[1] + b[1] * scale;\n dst[2] = a[2] + b[2] * scale;\n return dst;\n}\n/**\n * Returns the angle in radians between two vectors.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @returns The angle in radians between the 2 vectors.\n */\nfunction angle$1(a, b) {\n const ax = a[0];\n const ay = a[1];\n const az = a[2];\n const bx = a[0];\n const by = a[1];\n const bz = a[2];\n const mag1 = Math.sqrt(ax * ax + ay * ay + az * az);\n const mag2 = Math.sqrt(bx * bx + by * by + bz * bz);\n const mag = mag1 * mag2;\n const cosine = mag && dot$2(a, b) / mag;\n return Math.acos(cosine);\n}\n/**\n * Subtracts two vectors.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the difference of a and b.\n */\nfunction subtract$2(a, b, dst) {\n dst = dst || new VecType$1(3);\n dst[0] = a[0] - b[0];\n dst[1] = a[1] - b[1];\n dst[2] = a[2] - b[2];\n return dst;\n}\n/**\n * Subtracts two vectors.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the difference of a and b.\n */\nconst sub$2 = subtract$2;\n/**\n * Check if 2 vectors are approximately equal\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @returns true if vectors are approximately equal\n */\nfunction equalsApproximately$3(a, b) {\n return Math.abs(a[0] - b[0]) < EPSILON &&\n Math.abs(a[1] - b[1]) < EPSILON &&\n Math.abs(a[2] - b[2]) < EPSILON;\n}\n/**\n * Check if 2 vectors are exactly equal\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @returns true if vectors are exactly equal\n */\nfunction equals$3(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];\n}\n/**\n * Performs linear interpolation on two vectors.\n * Given vectors a and b and interpolation coefficient t, returns\n * a + t * (b - a).\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param t - Interpolation coefficient.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The linear interpolated result.\n */\nfunction lerp$2(a, b, t, dst) {\n dst = dst || new VecType$1(3);\n dst[0] = a[0] + t * (b[0] - a[0]);\n dst[1] = a[1] + t * (b[1] - a[1]);\n dst[2] = a[2] + t * (b[2] - a[2]);\n return dst;\n}\n/**\n * Performs linear interpolation on two vectors.\n * Given vectors a and b and interpolation coefficient vector t, returns\n * a + t * (b - a).\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param t - Interpolation coefficients vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns the linear interpolated result.\n */\nfunction lerpV$1(a, b, t, dst) {\n dst = dst || new VecType$1(3);\n dst[0] = a[0] + t[0] * (b[0] - a[0]);\n dst[1] = a[1] + t[1] * (b[1] - a[1]);\n dst[2] = a[2] + t[2] * (b[2] - a[2]);\n return dst;\n}\n/**\n * Return max values of two vectors.\n * Given vectors a and b returns\n * [max(a[0], b[0]), max(a[1], b[1]), max(a[2], b[2])].\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The max components vector.\n */\nfunction max$1(a, b, dst) {\n dst = dst || new VecType$1(3);\n dst[0] = Math.max(a[0], b[0]);\n dst[1] = Math.max(a[1], b[1]);\n dst[2] = Math.max(a[2], b[2]);\n return dst;\n}\n/**\n * Return min values of two vectors.\n * Given vectors a and b returns\n * [min(a[0], b[0]), min(a[1], b[1]), min(a[2], b[2])].\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The min components vector.\n */\nfunction min$1(a, b, dst) {\n dst = dst || new VecType$1(3);\n dst[0] = Math.min(a[0], b[0]);\n dst[1] = Math.min(a[1], b[1]);\n dst[2] = Math.min(a[2], b[2]);\n return dst;\n}\n/**\n * Multiplies a vector by a scalar.\n * @param v - The vector.\n * @param k - The scalar.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The scaled vector.\n */\nfunction mulScalar$2(v, k, dst) {\n dst = dst || new VecType$1(3);\n dst[0] = v[0] * k;\n dst[1] = v[1] * k;\n dst[2] = v[2] * k;\n return dst;\n}\n/**\n * Multiplies a vector by a scalar. (same as mulScalar)\n * @param v - The vector.\n * @param k - The scalar.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The scaled vector.\n */\nconst scale$3 = mulScalar$2;\n/**\n * Divides a vector by a scalar.\n * @param v - The vector.\n * @param k - The scalar.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The scaled vector.\n */\nfunction divScalar$2(v, k, dst) {\n dst = dst || new VecType$1(3);\n dst[0] = v[0] / k;\n dst[1] = v[1] / k;\n dst[2] = v[2] / k;\n return dst;\n}\n/**\n * Inverse a vector.\n * @param v - The vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The inverted vector.\n */\nfunction inverse$3(v, dst) {\n dst = dst || new VecType$1(3);\n dst[0] = 1 / v[0];\n dst[1] = 1 / v[1];\n dst[2] = 1 / v[2];\n return dst;\n}\n/**\n * Invert a vector. (same as inverse)\n * @param v - The vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The inverted vector.\n */\nconst invert$2 = inverse$3;\n/**\n * Computes the cross product of two vectors; assumes both vectors have\n * three entries.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The vector of a cross b.\n */\nfunction cross(a, b, dst) {\n dst = dst || new VecType$1(3);\n const t1 = a[2] * b[0] - a[0] * b[2];\n const t2 = a[0] * b[1] - a[1] * b[0];\n dst[0] = a[1] * b[2] - a[2] * b[1];\n dst[1] = t1;\n dst[2] = t2;\n return dst;\n}\n/**\n * Computes the dot product of two vectors; assumes both vectors have\n * three entries.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @returns dot product\n */\nfunction dot$2(a, b) {\n return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]);\n}\n/**\n * Computes the length of vector\n * @param v - vector.\n * @returns length of vector.\n */\nfunction length$2(v) {\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n return Math.sqrt(v0 * v0 + v1 * v1 + v2 * v2);\n}\n/**\n * Computes the length of vector (same as length)\n * @param v - vector.\n * @returns length of vector.\n */\nconst len$2 = length$2;\n/**\n * Computes the square of the length of vector\n * @param v - vector.\n * @returns square of the length of vector.\n */\nfunction lengthSq$2(v) {\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n return v0 * v0 + v1 * v1 + v2 * v2;\n}\n/**\n * Computes the square of the length of vector (same as lengthSq)\n * @param v - vector.\n * @returns square of the length of vector.\n */\nconst lenSq$2 = lengthSq$2;\n/**\n * Computes the distance between 2 points\n * @param a - vector.\n * @param b - vector.\n * @returns distance between a and b\n */\nfunction distance$1(a, b) {\n const dx = a[0] - b[0];\n const dy = a[1] - b[1];\n const dz = a[2] - b[2];\n return Math.sqrt(dx * dx + dy * dy + dz * dz);\n}\n/**\n * Computes the distance between 2 points (same as distance)\n * @param a - vector.\n * @param b - vector.\n * @returns distance between a and b\n */\nconst dist$1 = distance$1;\n/**\n * Computes the square of the distance between 2 points\n * @param a - vector.\n * @param b - vector.\n * @returns square of the distance between a and b\n */\nfunction distanceSq$1(a, b) {\n const dx = a[0] - b[0];\n const dy = a[1] - b[1];\n const dz = a[2] - b[2];\n return dx * dx + dy * dy + dz * dz;\n}\n/**\n * Computes the square of the distance between 2 points (same as distanceSq)\n * @param a - vector.\n * @param b - vector.\n * @returns square of the distance between a and b\n */\nconst distSq$1 = distanceSq$1;\n/**\n * Divides a vector by its Euclidean length and returns the quotient.\n * @param v - The vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The normalized vector.\n */\nfunction normalize$2(v, dst) {\n dst = dst || new VecType$1(3);\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n const len = Math.sqrt(v0 * v0 + v1 * v1 + v2 * v2);\n if (len > 0.00001) {\n dst[0] = v0 / len;\n dst[1] = v1 / len;\n dst[2] = v2 / len;\n }\n else {\n dst[0] = 0;\n dst[1] = 0;\n dst[2] = 0;\n }\n return dst;\n}\n/**\n * Negates a vector.\n * @param v - The vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns -v.\n */\nfunction negate$2(v, dst) {\n dst = dst || new VecType$1(3);\n dst[0] = -v[0];\n dst[1] = -v[1];\n dst[2] = -v[2];\n return dst;\n}\n/**\n * Copies a vector. (same as {@link vec3.clone})\n * Also see {@link vec3.create} and {@link vec3.set}\n * @param v - The vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A copy of v.\n */\nfunction copy$3(v, dst) {\n dst = dst || new VecType$1(3);\n dst[0] = v[0];\n dst[1] = v[1];\n dst[2] = v[2];\n return dst;\n}\n/**\n * Clones a vector. (same as {@link vec3.copy})\n * Also see {@link vec3.create} and {@link vec3.set}\n * @param v - The vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A copy of v.\n */\nconst clone$3 = copy$3;\n/**\n * Multiplies a vector by another vector (component-wise); assumes a and\n * b have the same length.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The vector of products of entries of a and b.\n */\nfunction multiply$3(a, b, dst) {\n dst = dst || new VecType$1(3);\n dst[0] = a[0] * b[0];\n dst[1] = a[1] * b[1];\n dst[2] = a[2] * b[2];\n return dst;\n}\n/**\n * Multiplies a vector by another vector (component-wise); assumes a and\n * b have the same length. (same as mul)\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The vector of products of entries of a and b.\n */\nconst mul$3 = multiply$3;\n/**\n * Divides a vector by another vector (component-wise); assumes a and\n * b have the same length.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The vector of quotients of entries of a and b.\n */\nfunction divide$1(a, b, dst) {\n dst = dst || new VecType$1(3);\n dst[0] = a[0] / b[0];\n dst[1] = a[1] / b[1];\n dst[2] = a[2] / b[2];\n return dst;\n}\n/**\n * Divides a vector by another vector (component-wise); assumes a and\n * b have the same length. (same as divide)\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The vector of quotients of entries of a and b.\n */\nconst div$1 = divide$1;\n/**\n * Creates a random vector\n * @param scale - Default 1\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The random vector.\n */\nfunction random(scale = 1, dst) {\n dst = dst || new VecType$1(3);\n const angle = Math.random() * 2 * Math.PI;\n const z = Math.random() * 2 - 1;\n const zScale = Math.sqrt(1 - z * z) * scale;\n dst[0] = Math.cos(angle) * zScale;\n dst[1] = Math.sin(angle) * zScale;\n dst[2] = z * scale;\n return dst;\n}\n/**\n * Zero's a vector\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The zeroed vector.\n */\nfunction zero$1(dst) {\n dst = dst || new VecType$1(3);\n dst[0] = 0;\n dst[1] = 0;\n dst[2] = 0;\n return dst;\n}\n/**\n * transform vec3 by 4x4 matrix\n * @param v - the vector\n * @param m - The matrix.\n * @param dst - optional vec3 to store result. If not passed a new one is created.\n * @returns the transformed vector\n */\nfunction transformMat4$1(v, m, dst) {\n dst = dst || new VecType$1(3);\n const x = v[0];\n const y = v[1];\n const z = v[2];\n const w = (m[3] * x + m[7] * y + m[11] * z + m[15]) || 1;\n dst[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;\n dst[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;\n dst[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;\n return dst;\n}\n/**\n * Transform vec4 by upper 3x3 matrix inside 4x4 matrix.\n * @param v - The direction.\n * @param m - The matrix.\n * @param dst - optional Vec3 to store result. If not passed a new one is created.\n * @returns The transformed vector.\n */\nfunction transformMat4Upper3x3(v, m, dst) {\n dst = dst || new VecType$1(3);\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n dst[0] = v0 * m[0 * 4 + 0] + v1 * m[1 * 4 + 0] + v2 * m[2 * 4 + 0];\n dst[1] = v0 * m[0 * 4 + 1] + v1 * m[1 * 4 + 1] + v2 * m[2 * 4 + 1];\n dst[2] = v0 * m[0 * 4 + 2] + v1 * m[1 * 4 + 2] + v2 * m[2 * 4 + 2];\n return dst;\n}\n/**\n * Transforms vec3 by 3x3 matrix\n *\n * @param v - the vector\n * @param m - The matrix.\n * @param dst - optional vec3 to store result. If not passed a new one is created.\n * @returns the transformed vector\n */\nfunction transformMat3(v, m, dst) {\n dst = dst || new VecType$1(3);\n const x = v[0];\n const y = v[1];\n const z = v[2];\n dst[0] = x * m[0] + y * m[4] + z * m[8];\n dst[1] = x * m[1] + y * m[5] + z * m[9];\n dst[2] = x * m[2] + y * m[6] + z * m[10];\n return dst;\n}\n/**\n * Transforms vec3 by Quaternion\n * @param v - the vector to transform\n * @param q - the quaternion to transform by\n * @param dst - optional vec3 to store result. If not passed a new one is created.\n * @returns the transformed\n */\nfunction transformQuat(v, q, dst) {\n dst = dst || new VecType$1(3);\n const qx = q[0];\n const qy = q[1];\n const qz = q[2];\n const w2 = q[3] * 2;\n const x = v[0];\n const y = v[1];\n const z = v[2];\n const uvX = qy * z - qz * y;\n const uvY = qz * x - qx * z;\n const uvZ = qx * y - qy * x;\n dst[0] = x + uvX * w2 + (qy * uvZ - qz * uvY) * 2;\n dst[1] = y + uvY * w2 + (qz * uvX - qx * uvZ) * 2;\n dst[2] = z + uvZ * w2 + (qx * uvY - qy * uvX) * 2;\n return dst;\n}\n/**\n * Returns the translation component of a 4-by-4 matrix as a vector with 3\n * entries.\n * @param m - The matrix.\n * @param dst - vector to hold result. If not passed a new one is created.\n * @returns The translation component of m.\n */\nfunction getTranslation$1(m, dst) {\n dst = dst || new VecType$1(3);\n dst[0] = m[12];\n dst[1] = m[13];\n dst[2] = m[14];\n return dst;\n}\n/**\n * Returns an axis of a 4x4 matrix as a vector with 3 entries\n * @param m - The matrix.\n * @param axis - The axis 0 = x, 1 = y, 2 = z;\n * @returns The axis component of m.\n */\nfunction getAxis$1(m, axis, dst) {\n dst = dst || new VecType$1(3);\n const off = axis * 4;\n dst[0] = m[off + 0];\n dst[1] = m[off + 1];\n dst[2] = m[off + 2];\n return dst;\n}\n/**\n * Returns the scaling component of the matrix\n * @param m - The Matrix\n * @param dst - The vector to set. If not passed a new one is created.\n */\nfunction getScaling$1(m, dst) {\n dst = dst || new VecType$1(3);\n const xx = m[0];\n const xy = m[1];\n const xz = m[2];\n const yx = m[4];\n const yy = m[5];\n const yz = m[6];\n const zx = m[8];\n const zy = m[9];\n const zz = m[10];\n dst[0] = Math.sqrt(xx * xx + xy * xy + xz * xz);\n dst[1] = Math.sqrt(yx * yx + yy * yy + yz * yz);\n dst[2] = Math.sqrt(zx * zx + zy * zy + zz * zz);\n return dst;\n}\n\nvar vec3Impl = /*#__PURE__*/Object.freeze({\n __proto__: null,\n create: create$4,\n setDefaultType: setDefaultType$5,\n fromValues: fromValues$2,\n set: set$3,\n ceil: ceil$1,\n floor: floor$1,\n round: round$1,\n clamp: clamp$1,\n add: add$2,\n addScaled: addScaled$1,\n angle: angle$1,\n subtract: subtract$2,\n sub: sub$2,\n equalsApproximately: equalsApproximately$3,\n equals: equals$3,\n lerp: lerp$2,\n lerpV: lerpV$1,\n max: max$1,\n min: min$1,\n mulScalar: mulScalar$2,\n scale: scale$3,\n divScalar: divScalar$2,\n inverse: inverse$3,\n invert: invert$2,\n cross: cross,\n dot: dot$2,\n length: length$2,\n len: len$2,\n lengthSq: lengthSq$2,\n lenSq: lenSq$2,\n distance: distance$1,\n dist: dist$1,\n distanceSq: distanceSq$1,\n distSq: distSq$1,\n normalize: normalize$2,\n negate: negate$2,\n copy: copy$3,\n clone: clone$3,\n multiply: multiply$3,\n mul: mul$3,\n divide: divide$1,\n div: div$1,\n random: random,\n zero: zero$1,\n transformMat4: transformMat4$1,\n transformMat4Upper3x3: transformMat4Upper3x3,\n transformMat3: transformMat3,\n transformQuat: transformQuat,\n getTranslation: getTranslation$1,\n getAxis: getAxis$1,\n getScaling: getScaling$1\n});\n\n/**\n * 4x4 Matrix math math functions.\n *\n * Almost all functions take an optional `dst` argument. If it is not passed in the\n * functions will create a new matrix. In other words you can do this\n *\n * const mat = mat4.translation([1, 2, 3]); // Creates a new translation matrix\n *\n * or\n *\n * const mat = mat4.create();\n * mat4.translation([1, 2, 3], mat); // Puts translation matrix in mat.\n *\n * The first style is often easier but depending on where it's used it generates garbage where\n * as there is almost never allocation with the second style.\n *\n * It is always save to pass any matrix as the destination. So for example\n *\n * const mat = mat4.identity();\n * const trans = mat4.translation([1, 2, 3]);\n * mat4.multiply(mat, trans, mat); // Multiplies mat * trans and puts result in mat.\n *\n */\nlet MatType = Float32Array;\n/**\n * Sets the type this library creates for a Mat4\n * @param ctor - the constructor for the type. Either `Float32Array`, `Float64Array`, or `Array`\n * @returns previous constructor for Mat4\n */\nfunction setDefaultType$3(ctor) {\n const oldType = MatType;\n MatType = ctor;\n return oldType;\n}\n/**\n * Create a Mat4 from values\n *\n * Note: Since passing in a raw JavaScript array\n * is valid in all circumstances, if you want to\n * force a JavaScript array into a Mat4's specified type\n * it would be faster to use\n *\n * ```\n * const m = mat4.clone(someJSArray);\n * ```\n *\n * Note: a consequence of the implementation is if your Mat4Type = `Array`\n * instead of `Float32Array` or `Float64Array` then any values you\n * don't pass in will be undefined. Usually this is not an issue since\n * (a) using `Array` is rare and (b) using `mat4.create` is usually used\n * to create a Mat4 to be filled out as in\n *\n * ```\n * const m = mat4.create();\n * mat4.perspective(fov, aspect, near, far, m);\n * ```\n *\n * @param v0 - value for element 0\n * @param v1 - value for element 1\n * @param v2 - value for element 2\n * @param v3 - value for element 3\n * @param v4 - value for element 4\n * @param v5 - value for element 5\n * @param v6 - value for element 6\n * @param v7 - value for element 7\n * @param v8 - value for element 8\n * @param v9 - value for element 9\n * @param v10 - value for element 10\n * @param v11 - value for element 11\n * @param v12 - value for element 12\n * @param v13 - value for element 13\n * @param v14 - value for element 14\n * @param v15 - value for element 15\n * @returns created from values.\n */\nfunction create$2(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) {\n const dst = new MatType(16);\n if (v0 !== undefined) {\n dst[0] = v0;\n if (v1 !== undefined) {\n dst[1] = v1;\n if (v2 !== undefined) {\n dst[2] = v2;\n if (v3 !== undefined) {\n dst[3] = v3;\n if (v4 !== undefined) {\n dst[4] = v4;\n if (v5 !== undefined) {\n dst[5] = v5;\n if (v6 !== undefined) {\n dst[6] = v6;\n if (v7 !== undefined) {\n dst[7] = v7;\n if (v8 !== undefined) {\n dst[8] = v8;\n if (v9 !== undefined) {\n dst[9] = v9;\n if (v10 !== undefined) {\n dst[10] = v10;\n if (v11 !== undefined) {\n dst[11] = v11;\n if (v12 !== undefined) {\n dst[12] = v12;\n if (v13 !== undefined) {\n dst[13] = v13;\n if (v14 !== undefined) {\n dst[14] = v14;\n if (v15 !== undefined) {\n dst[15] = v15;\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n return dst;\n}\n/**\n * Sets the values of a Mat4\n * Also see {@link mat4.create} and {@link mat4.copy}\n *\n * @param v0 - value for element 0\n * @param v1 - value for element 1\n * @param v2 - value for element 2\n * @param v3 - value for element 3\n * @param v4 - value for element 4\n * @param v5 - value for element 5\n * @param v6 - value for element 6\n * @param v7 - value for element 7\n * @param v8 - value for element 8\n * @param v9 - value for element 9\n * @param v10 - value for element 10\n * @param v11 - value for element 11\n * @param v12 - value for element 12\n * @param v13 - value for element 13\n * @param v14 - value for element 14\n * @param v15 - value for element 15\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns Mat4 created from values.\n */\nfunction set$2(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, dst) {\n dst = dst || new MatType(16);\n dst[0] = v0;\n dst[1] = v1;\n dst[2] = v2;\n dst[3] = v3;\n dst[4] = v4;\n dst[5] = v5;\n dst[6] = v6;\n dst[7] = v7;\n dst[8] = v8;\n dst[9] = v9;\n dst[10] = v10;\n dst[11] = v11;\n dst[12] = v12;\n dst[13] = v13;\n dst[14] = v14;\n dst[15] = v15;\n return dst;\n}\n/**\n * Creates a Mat4 from a Mat3\n * @param m3 - source matrix\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns Mat4 made from m3\n */\nfunction fromMat3(m3, dst) {\n dst = dst || new MatType(16);\n dst[0] = m3[0];\n dst[1] = m3[1];\n dst[2] = m3[2];\n dst[3] = 0;\n dst[4] = m3[4];\n dst[5] = m3[5];\n dst[6] = m3[6];\n dst[7] = 0;\n dst[8] = m3[8];\n dst[9] = m3[9];\n dst[10] = m3[10];\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n return dst;\n}\n/**\n * Creates a Mat4 rotation matrix from a quaternion\n * @param q - quaternion to create matrix from\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns Mat4 made from q\n */\nfunction fromQuat(q, dst) {\n dst = dst || new MatType(16);\n const x = q[0];\n const y = q[1];\n const z = q[2];\n const w = q[3];\n const x2 = x + x;\n const y2 = y + y;\n const z2 = z + z;\n const xx = x * x2;\n const yx = y * x2;\n const yy = y * y2;\n const zx = z * x2;\n const zy = z * y2;\n const zz = z * z2;\n const wx = w * x2;\n const wy = w * y2;\n const wz = w * z2;\n dst[0] = 1 - yy - zz;\n dst[1] = yx + wz;\n dst[2] = zx - wy;\n dst[3] = 0;\n dst[4] = yx - wz;\n dst[5] = 1 - xx - zz;\n dst[6] = zy + wx;\n dst[7] = 0;\n dst[8] = zx + wy;\n dst[9] = zy - wx;\n dst[10] = 1 - xx - yy;\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n return dst;\n}\n/**\n * Negates a matrix.\n * @param m - The matrix.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns -m.\n */\nfunction negate$1(m, dst) {\n dst = dst || new MatType(16);\n dst[0] = -m[0];\n dst[1] = -m[1];\n dst[2] = -m[2];\n dst[3] = -m[3];\n dst[4] = -m[4];\n dst[5] = -m[5];\n dst[6] = -m[6];\n dst[7] = -m[7];\n dst[8] = -m[8];\n dst[9] = -m[9];\n dst[10] = -m[10];\n dst[11] = -m[11];\n dst[12] = -m[12];\n dst[13] = -m[13];\n dst[14] = -m[14];\n dst[15] = -m[15];\n return dst;\n}\n/**\n * Copies a matrix. (same as {@link mat4.clone})\n * Also see {@link mat4.create} and {@link mat4.set}\n * @param m - The matrix.\n * @param dst - The matrix. If not passed a new one is created.\n * @returns A copy of m.\n */\nfunction copy$2(m, dst) {\n dst = dst || new MatType(16);\n dst[0] = m[0];\n dst[1] = m[1];\n dst[2] = m[2];\n dst[3] = m[3];\n dst[4] = m[4];\n dst[5] = m[5];\n dst[6] = m[6];\n dst[7] = m[7];\n dst[8] = m[8];\n dst[9] = m[9];\n dst[10] = m[10];\n dst[11] = m[11];\n dst[12] = m[12];\n dst[13] = m[13];\n dst[14] = m[14];\n dst[15] = m[15];\n return dst;\n}\n/**\n * Copies a matrix (same as {@link mat4.copy})\n * Also see {@link mat4.create} and {@link mat4.set}\n * @param m - The matrix.\n * @param dst - The matrix. If not passed a new one is created.\n * @returns A copy of m.\n */\nconst clone$2 = copy$2;\n/**\n * Check if 2 matrices are approximately equal\n * @param a - Operand matrix.\n * @param b - Operand matrix.\n * @returns true if matrices are approximately equal\n */\nfunction equalsApproximately$2(a, b) {\n return Math.abs(a[0] - b[0]) < EPSILON &&\n Math.abs(a[1] - b[1]) < EPSILON &&\n Math.abs(a[2] - b[2]) < EPSILON &&\n Math.abs(a[3] - b[3]) < EPSILON &&\n Math.abs(a[4] - b[4]) < EPSILON &&\n Math.abs(a[5] - b[5]) < EPSILON &&\n Math.abs(a[6] - b[6]) < EPSILON &&\n Math.abs(a[7] - b[7]) < EPSILON &&\n Math.abs(a[8] - b[8]) < EPSILON &&\n Math.abs(a[9] - b[9]) < EPSILON &&\n Math.abs(a[10] - b[10]) < EPSILON &&\n Math.abs(a[11] - b[11]) < EPSILON &&\n Math.abs(a[12] - b[12]) < EPSILON &&\n Math.abs(a[13] - b[13]) < EPSILON &&\n Math.abs(a[14] - b[14]) < EPSILON &&\n Math.abs(a[15] - b[15]) < EPSILON;\n}\n/**\n * Check if 2 matrices are exactly equal\n * @param a - Operand matrix.\n * @param b - Operand matrix.\n * @returns true if matrices are exactly equal\n */\nfunction equals$2(a, b) {\n return a[0] === b[0] &&\n a[1] === b[1] &&\n a[2] === b[2] &&\n a[3] === b[3] &&\n a[4] === b[4] &&\n a[5] === b[5] &&\n a[6] === b[6] &&\n a[7] === b[7] &&\n a[8] === b[8] &&\n a[9] === b[9] &&\n a[10] === b[10] &&\n a[11] === b[11] &&\n a[12] === b[12] &&\n a[13] === b[13] &&\n a[14] === b[14] &&\n a[15] === b[15];\n}\n/**\n * Creates a 4-by-4 identity matrix.\n *\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns A 4-by-4 identity matrix.\n */\nfunction identity$1(dst) {\n dst = dst || new MatType(16);\n dst[0] = 1;\n dst[1] = 0;\n dst[2] = 0;\n dst[3] = 0;\n dst[4] = 0;\n dst[5] = 1;\n dst[6] = 0;\n dst[7] = 0;\n dst[8] = 0;\n dst[9] = 0;\n dst[10] = 1;\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n return dst;\n}\n/**\n * Takes the transpose of a matrix.\n * @param m - The matrix.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The transpose of m.\n */\nfunction transpose(m, dst) {\n dst = dst || new MatType(16);\n if (dst === m) {\n let t;\n t = m[1];\n m[1] = m[4];\n m[4] = t;\n t = m[2];\n m[2] = m[8];\n m[8] = t;\n t = m[3];\n m[3] = m[12];\n m[12] = t;\n t = m[6];\n m[6] = m[9];\n m[9] = t;\n t = m[7];\n m[7] = m[13];\n m[13] = t;\n t = m[11];\n m[11] = m[14];\n m[14] = t;\n return dst;\n }\n const m00 = m[0 * 4 + 0];\n const m01 = m[0 * 4 + 1];\n const m02 = m[0 * 4 + 2];\n const m03 = m[0 * 4 + 3];\n const m10 = m[1 * 4 + 0];\n const m11 = m[1 * 4 + 1];\n const m12 = m[1 * 4 + 2];\n const m13 = m[1 * 4 + 3];\n const m20 = m[2 * 4 + 0];\n const m21 = m[2 * 4 + 1];\n const m22 = m[2 * 4 + 2];\n const m23 = m[2 * 4 + 3];\n const m30 = m[3 * 4 + 0];\n const m31 = m[3 * 4 + 1];\n const m32 = m[3 * 4 + 2];\n const m33 = m[3 * 4 + 3];\n dst[0] = m00;\n dst[1] = m10;\n dst[2] = m20;\n dst[3] = m30;\n dst[4] = m01;\n dst[5] = m11;\n dst[6] = m21;\n dst[7] = m31;\n dst[8] = m02;\n dst[9] = m12;\n dst[10] = m22;\n dst[11] = m32;\n dst[12] = m03;\n dst[13] = m13;\n dst[14] = m23;\n dst[15] = m33;\n return dst;\n}\n/**\n * Computes the inverse of a 4-by-4 matrix.\n * @param m - The matrix.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The inverse of m.\n */\nfunction inverse$2(m, dst) {\n dst = dst || new MatType(16);\n const m00 = m[0 * 4 + 0];\n const m01 = m[0 * 4 + 1];\n const m02 = m[0 * 4 + 2];\n const m03 = m[0 * 4 + 3];\n const m10 = m[1 * 4 + 0];\n const m11 = m[1 * 4 + 1];\n const m12 = m[1 * 4 + 2];\n const m13 = m[1 * 4 + 3];\n const m20 = m[2 * 4 + 0];\n const m21 = m[2 * 4 + 1];\n const m22 = m[2 * 4 + 2];\n const m23 = m[2 * 4 + 3];\n const m30 = m[3 * 4 + 0];\n const m31 = m[3 * 4 + 1];\n const m32 = m[3 * 4 + 2];\n const m33 = m[3 * 4 + 3];\n const tmp0 = m22 * m33;\n const tmp1 = m32 * m23;\n const tmp2 = m12 * m33;\n const tmp3 = m32 * m13;\n const tmp4 = m12 * m23;\n const tmp5 = m22 * m13;\n const tmp6 = m02 * m33;\n const tmp7 = m32 * m03;\n const tmp8 = m02 * m23;\n const tmp9 = m22 * m03;\n const tmp10 = m02 * m13;\n const tmp11 = m12 * m03;\n const tmp12 = m20 * m31;\n const tmp13 = m30 * m21;\n const tmp14 = m10 * m31;\n const tmp15 = m30 * m11;\n const tmp16 = m10 * m21;\n const tmp17 = m20 * m11;\n const tmp18 = m00 * m31;\n const tmp19 = m30 * m01;\n const tmp20 = m00 * m21;\n const tmp21 = m20 * m01;\n const tmp22 = m00 * m11;\n const tmp23 = m10 * m01;\n const t0 = (tmp0 * m11 + tmp3 * m21 + tmp4 * m31) -\n (tmp1 * m11 + tmp2 * m21 + tmp5 * m31);\n const t1 = (tmp1 * m01 + tmp6 * m21 + tmp9 * m31) -\n (tmp0 * m01 + tmp7 * m21 + tmp8 * m31);\n const t2 = (tmp2 * m01 + tmp7 * m11 + tmp10 * m31) -\n (tmp3 * m01 + tmp6 * m11 + tmp11 * m31);\n const t3 = (tmp5 * m01 + tmp8 * m11 + tmp11 * m21) -\n (tmp4 * m01 + tmp9 * m11 + tmp10 * m21);\n const d = 1 / (m00 * t0 + m10 * t1 + m20 * t2 + m30 * t3);\n dst[0] = d * t0;\n dst[1] = d * t1;\n dst[2] = d * t2;\n dst[3] = d * t3;\n dst[4] = d * ((tmp1 * m10 + tmp2 * m20 + tmp5 * m30) -\n (tmp0 * m10 + tmp3 * m20 + tmp4 * m30));\n dst[5] = d * ((tmp0 * m00 + tmp7 * m20 + tmp8 * m30) -\n (tmp1 * m00 + tmp6 * m20 + tmp9 * m30));\n dst[6] = d * ((tmp3 * m00 + tmp6 * m10 + tmp11 * m30) -\n (tmp2 * m00 + tmp7 * m10 + tmp10 * m30));\n dst[7] = d * ((tmp4 * m00 + tmp9 * m10 + tmp10 * m20) -\n (tmp5 * m00 + tmp8 * m10 + tmp11 * m20));\n dst[8] = d * ((tmp12 * m13 + tmp15 * m23 + tmp16 * m33) -\n (tmp13 * m13 + tmp14 * m23 + tmp17 * m33));\n dst[9] = d * ((tmp13 * m03 + tmp18 * m23 + tmp21 * m33) -\n (tmp12 * m03 + tmp19 * m23 + tmp20 * m33));\n dst[10] = d * ((tmp14 * m03 + tmp19 * m13 + tmp22 * m33) -\n (tmp15 * m03 + tmp18 * m13 + tmp23 * m33));\n dst[11] = d * ((tmp17 * m03 + tmp20 * m13 + tmp23 * m23) -\n (tmp16 * m03 + tmp21 * m13 + tmp22 * m23));\n dst[12] = d * ((tmp14 * m22 + tmp17 * m32 + tmp13 * m12) -\n (tmp16 * m32 + tmp12 * m12 + tmp15 * m22));\n dst[13] = d * ((tmp20 * m32 + tmp12 * m02 + tmp19 * m22) -\n (tmp18 * m22 + tmp21 * m32 + tmp13 * m02));\n dst[14] = d * ((tmp18 * m12 + tmp23 * m32 + tmp15 * m02) -\n (tmp22 * m32 + tmp14 * m02 + tmp19 * m12));\n dst[15] = d * ((tmp22 * m22 + tmp16 * m02 + tmp21 * m12) -\n (tmp20 * m12 + tmp23 * m22 + tmp17 * m02));\n return dst;\n}\n/**\n * Compute the determinant of a matrix\n * @param m - the matrix\n * @returns the determinant\n */\nfunction determinant(m) {\n const m00 = m[0 * 4 + 0];\n const m01 = m[0 * 4 + 1];\n const m02 = m[0 * 4 + 2];\n const m03 = m[0 * 4 + 3];\n const m10 = m[1 * 4 + 0];\n const m11 = m[1 * 4 + 1];\n const m12 = m[1 * 4 + 2];\n const m13 = m[1 * 4 + 3];\n const m20 = m[2 * 4 + 0];\n const m21 = m[2 * 4 + 1];\n const m22 = m[2 * 4 + 2];\n const m23 = m[2 * 4 + 3];\n const m30 = m[3 * 4 + 0];\n const m31 = m[3 * 4 + 1];\n const m32 = m[3 * 4 + 2];\n const m33 = m[3 * 4 + 3];\n const tmp0 = m22 * m33;\n const tmp1 = m32 * m23;\n const tmp2 = m12 * m33;\n const tmp3 = m32 * m13;\n const tmp4 = m12 * m23;\n const tmp5 = m22 * m13;\n const tmp6 = m02 * m33;\n const tmp7 = m32 * m03;\n const tmp8 = m02 * m23;\n const tmp9 = m22 * m03;\n const tmp10 = m02 * m13;\n const tmp11 = m12 * m03;\n const t0 = (tmp0 * m11 + tmp3 * m21 + tmp4 * m31) -\n (tmp1 * m11 + tmp2 * m21 + tmp5 * m31);\n const t1 = (tmp1 * m01 + tmp6 * m21 + tmp9 * m31) -\n (tmp0 * m01 + tmp7 * m21 + tmp8 * m31);\n const t2 = (tmp2 * m01 + tmp7 * m11 + tmp10 * m31) -\n (tmp3 * m01 + tmp6 * m11 + tmp11 * m31);\n const t3 = (tmp5 * m01 + tmp8 * m11 + tmp11 * m21) -\n (tmp4 * m01 + tmp9 * m11 + tmp10 * m21);\n return m00 * t0 + m10 * t1 + m20 * t2 + m30 * t3;\n}\n/**\n * Computes the inverse of a 4-by-4 matrix. (same as inverse)\n * @param m - The matrix.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The inverse of m.\n */\nconst invert$1 = inverse$2;\n/**\n * Multiplies two 4-by-4 matrices with a on the left and b on the right\n * @param a - The matrix on the left.\n * @param b - The matrix on the right.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The matrix product of a and b.\n */\nfunction multiply$2(a, b, dst) {\n dst = dst || new MatType(16);\n const a00 = a[0];\n const a01 = a[1];\n const a02 = a[2];\n const a03 = a[3];\n const a10 = a[4 + 0];\n const a11 = a[4 + 1];\n const a12 = a[4 + 2];\n const a13 = a[4 + 3];\n const a20 = a[8 + 0];\n const a21 = a[8 + 1];\n const a22 = a[8 + 2];\n const a23 = a[8 + 3];\n const a30 = a[12 + 0];\n const a31 = a[12 + 1];\n const a32 = a[12 + 2];\n const a33 = a[12 + 3];\n const b00 = b[0];\n const b01 = b[1];\n const b02 = b[2];\n const b03 = b[3];\n const b10 = b[4 + 0];\n const b11 = b[4 + 1];\n const b12 = b[4 + 2];\n const b13 = b[4 + 3];\n const b20 = b[8 + 0];\n const b21 = b[8 + 1];\n const b22 = b[8 + 2];\n const b23 = b[8 + 3];\n const b30 = b[12 + 0];\n const b31 = b[12 + 1];\n const b32 = b[12 + 2];\n const b33 = b[12 + 3];\n dst[0] = a00 * b00 + a10 * b01 + a20 * b02 + a30 * b03;\n dst[1] = a01 * b00 + a11 * b01 + a21 * b02 + a31 * b03;\n dst[2] = a02 * b00 + a12 * b01 + a22 * b02 + a32 * b03;\n dst[3] = a03 * b00 + a13 * b01 + a23 * b02 + a33 * b03;\n dst[4] = a00 * b10 + a10 * b11 + a20 * b12 + a30 * b13;\n dst[5] = a01 * b10 + a11 * b11 + a21 * b12 + a31 * b13;\n dst[6] = a02 * b10 + a12 * b11 + a22 * b12 + a32 * b13;\n dst[7] = a03 * b10 + a13 * b11 + a23 * b12 + a33 * b13;\n dst[8] = a00 * b20 + a10 * b21 + a20 * b22 + a30 * b23;\n dst[9] = a01 * b20 + a11 * b21 + a21 * b22 + a31 * b23;\n dst[10] = a02 * b20 + a12 * b21 + a22 * b22 + a32 * b23;\n dst[11] = a03 * b20 + a13 * b21 + a23 * b22 + a33 * b23;\n dst[12] = a00 * b30 + a10 * b31 + a20 * b32 + a30 * b33;\n dst[13] = a01 * b30 + a11 * b31 + a21 * b32 + a31 * b33;\n dst[14] = a02 * b30 + a12 * b31 + a22 * b32 + a32 * b33;\n dst[15] = a03 * b30 + a13 * b31 + a23 * b32 + a33 * b33;\n return dst;\n}\n/**\n * Multiplies two 4-by-4 matrices with a on the left and b on the right (same as multiply)\n * @param a - The matrix on the left.\n * @param b - The matrix on the right.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The matrix product of a and b.\n */\nconst mul$2 = multiply$2;\n/**\n * Sets the translation component of a 4-by-4 matrix to the given\n * vector.\n * @param a - The matrix.\n * @param v - The vector.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The matrix with translation set.\n */\nfunction setTranslation(a, v, dst) {\n dst = dst || identity$1();\n if (a !== dst) {\n dst[0] = a[0];\n dst[1] = a[1];\n dst[2] = a[2];\n dst[3] = a[3];\n dst[4] = a[4];\n dst[5] = a[5];\n dst[6] = a[6];\n dst[7] = a[7];\n dst[8] = a[8];\n dst[9] = a[9];\n dst[10] = a[10];\n dst[11] = a[11];\n }\n dst[12] = v[0];\n dst[13] = v[1];\n dst[14] = v[2];\n dst[15] = 1;\n return dst;\n}\n/**\n * Returns the translation component of a 4-by-4 matrix as a vector with 3\n * entries.\n * @param m - The matrix.\n * @param dst - vector to hold result. If not passed a new one is created.\n * @returns The translation component of m.\n */\nfunction getTranslation(m, dst) {\n dst = dst || create$4();\n dst[0] = m[12];\n dst[1] = m[13];\n dst[2] = m[14];\n return dst;\n}\n/**\n * Returns an axis of a 4x4 matrix as a vector with 3 entries\n * @param m - The matrix.\n * @param axis - The axis 0 = x, 1 = y, 2 = z;\n * @returns The axis component of m.\n */\nfunction getAxis(m, axis, dst) {\n dst = dst || create$4();\n const off = axis * 4;\n dst[0] = m[off + 0];\n dst[1] = m[off + 1];\n dst[2] = m[off + 2];\n return dst;\n}\n/**\n * Sets an axis of a 4x4 matrix as a vector with 3 entries\n * @param m - The matrix.\n * @param v - the axis vector\n * @param axis - The axis 0 = x, 1 = y, 2 = z;\n * @param dst - The matrix to set. If not passed a new one is created.\n * @returns The matrix with axis set.\n */\nfunction setAxis(a, v, axis, dst) {\n if (dst !== a) {\n dst = copy$2(a, dst);\n }\n const off = axis * 4;\n dst[off + 0] = v[0];\n dst[off + 1] = v[1];\n dst[off + 2] = v[2];\n return dst;\n}\n/**\n * Returns the scaling component of the matrix\n * @param m - The Matrix\n * @param dst - The vector to set. If not passed a new one is created.\n */\nfunction getScaling(m, dst) {\n dst = dst || create$4();\n const xx = m[0];\n const xy = m[1];\n const xz = m[2];\n const yx = m[4];\n const yy = m[5];\n const yz = m[6];\n const zx = m[8];\n const zy = m[9];\n const zz = m[10];\n dst[0] = Math.sqrt(xx * xx + xy * xy + xz * xz);\n dst[1] = Math.sqrt(yx * yx + yy * yy + yz * yz);\n dst[2] = Math.sqrt(zx * zx + zy * zy + zz * zz);\n return dst;\n}\n/**\n * Computes a 4-by-4 perspective transformation matrix given the angular height\n * of the frustum, the aspect ratio, and the near and far clipping planes. The\n * arguments define a frustum extending in the negative z direction. The given\n * angle is the vertical angle of the frustum, and the horizontal angle is\n * determined to produce the given aspect ratio. The arguments near and far are\n * the distances to the near and far clipping planes. Note that near and far\n * are not z coordinates, but rather they are distances along the negative\n * z-axis. The matrix generated sends the viewing frustum to the unit box.\n * We assume a unit box extending from -1 to 1 in the x and y dimensions and\n * from 0 to 1 in the z dimension.\n *\n * Note: If you pass `Infinity` for zFar then it will produce a projection matrix\n * returns -Infinity for Z when transforming coordinates with Z <= 0 and +Infinity for Z\n * otherwise.\n *\n * @param fieldOfViewYInRadians - The camera angle from top to bottom (in radians).\n * @param aspect - The aspect ratio width / height.\n * @param zNear - The depth (negative z coordinate)\n * of the near clipping plane.\n * @param zFar - The depth (negative z coordinate)\n * of the far clipping plane.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The perspective matrix.\n */\nfunction perspective(fieldOfViewYInRadians, aspect, zNear, zFar, dst) {\n dst = dst || new MatType(16);\n const f = Math.tan(Math.PI * 0.5 - 0.5 * fieldOfViewYInRadians);\n dst[0] = f / aspect;\n dst[1] = 0;\n dst[2] = 0;\n dst[3] = 0;\n dst[4] = 0;\n dst[5] = f;\n dst[6] = 0;\n dst[7] = 0;\n dst[8] = 0;\n dst[9] = 0;\n dst[11] = -1;\n dst[12] = 0;\n dst[13] = 0;\n dst[15] = 0;\n if (zFar === Infinity) {\n dst[10] = -1;\n dst[14] = -zNear;\n }\n else {\n const rangeInv = 1 / (zNear - zFar);\n dst[10] = zFar * rangeInv;\n dst[14] = zFar * zNear * rangeInv;\n }\n return dst;\n}\n/**\n * Computes a 4-by-4 orthogonal transformation matrix that transforms from\n * the given the left, right, bottom, and top dimensions to -1 +1 in x, and y\n * and 0 to +1 in z.\n * @param left - Left side of the near clipping plane viewport.\n * @param right - Right side of the near clipping plane viewport.\n * @param bottom - Bottom of the near clipping plane viewport.\n * @param top - Top of the near clipping plane viewport.\n * @param near - The depth (negative z coordinate)\n * of the near clipping plane.\n * @param far - The depth (negative z coordinate)\n * of the far clipping plane.\n * @param dst - Output matrix. If not passed a new one is created.\n * @returns The orthographic projection matrix.\n */\nfunction ortho(left, right, bottom, top, near, far, dst) {\n dst = dst || new MatType(16);\n dst[0] = 2 / (right - left);\n dst[1] = 0;\n dst[2] = 0;\n dst[3] = 0;\n dst[4] = 0;\n dst[5] = 2 / (top - bottom);\n dst[6] = 0;\n dst[7] = 0;\n dst[8] = 0;\n dst[9] = 0;\n dst[10] = 1 / (near - far);\n dst[11] = 0;\n dst[12] = (right + left) / (left - right);\n dst[13] = (top + bottom) / (bottom - top);\n dst[14] = near / (near - far);\n dst[15] = 1;\n return dst;\n}\n/**\n * Computes a 4-by-4 perspective transformation matrix given the left, right,\n * top, bottom, near and far clipping planes. The arguments define a frustum\n * extending in the negative z direction. The arguments near and far are the\n * distances to the near and far clipping planes. Note that near and far are not\n * z coordinates, but rather they are distances along the negative z-axis. The\n * matrix generated sends the viewing frustum to the unit box. We assume a unit\n * box extending from -1 to 1 in the x and y dimensions and from 0 to 1 in the z\n * dimension.\n * @param left - The x coordinate of the left plane of the box.\n * @param right - The x coordinate of the right plane of the box.\n * @param bottom - The y coordinate of the bottom plane of the box.\n * @param top - The y coordinate of the right plane of the box.\n * @param near - The negative z coordinate of the near plane of the box.\n * @param far - The negative z coordinate of the far plane of the box.\n * @param dst - Output matrix. If not passed a new one is created.\n * @returns The perspective projection matrix.\n */\nfunction frustum(left, right, bottom, top, near, far, dst) {\n dst = dst || new MatType(16);\n const dx = (right - left);\n const dy = (top - bottom);\n const dz = (near - far);\n dst[0] = 2 * near / dx;\n dst[1] = 0;\n dst[2] = 0;\n dst[3] = 0;\n dst[4] = 0;\n dst[5] = 2 * near / dy;\n dst[6] = 0;\n dst[7] = 0;\n dst[8] = (left + right) / dx;\n dst[9] = (top + bottom) / dy;\n dst[10] = far / dz;\n dst[11] = -1;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = near * far / dz;\n dst[15] = 0;\n return dst;\n}\nlet xAxis;\nlet yAxis;\nlet zAxis;\n/**\n * Computes a 4-by-4 aim transformation.\n *\n * This is a matrix which positions an object aiming down positive Z.\n * toward the target.\n *\n * Note: this is **NOT** the inverse of lookAt as lookAt looks at negative Z.\n *\n * @param position - The position of the object.\n * @param target - The position meant to be aimed at.\n * @param up - A vector pointing up.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The aim matrix.\n */\nfunction aim(position, target, up, dst) {\n dst = dst || new MatType(16);\n xAxis = xAxis || create$4();\n yAxis = yAxis || create$4();\n zAxis = zAxis || create$4();\n normalize$2(subtract$2(target, position, zAxis), zAxis);\n normalize$2(cross(up, zAxis, xAxis), xAxis);\n normalize$2(cross(zAxis, xAxis, yAxis), yAxis);\n dst[0] = xAxis[0];\n dst[1] = xAxis[1];\n dst[2] = xAxis[2];\n dst[3] = 0;\n dst[4] = yAxis[0];\n dst[5] = yAxis[1];\n dst[6] = yAxis[2];\n dst[7] = 0;\n dst[8] = zAxis[0];\n dst[9] = zAxis[1];\n dst[10] = zAxis[2];\n dst[11] = 0;\n dst[12] = position[0];\n dst[13] = position[1];\n dst[14] = position[2];\n dst[15] = 1;\n return dst;\n}\n/**\n * Computes a 4-by-4 camera aim transformation.\n *\n * This is a matrix which positions an object aiming down negative Z.\n * toward the target.\n *\n * Note: this is the inverse of `lookAt`\n *\n * @param eye - The position of the object.\n * @param target - The position meant to be aimed at.\n * @param up - A vector pointing up.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The aim matrix.\n */\nfunction cameraAim(eye, target, up, dst) {\n dst = dst || new MatType(16);\n xAxis = xAxis || create$4();\n yAxis = yAxis || create$4();\n zAxis = zAxis || create$4();\n normalize$2(subtract$2(eye, target, zAxis), zAxis);\n normalize$2(cross(up, zAxis, xAxis), xAxis);\n normalize$2(cross(zAxis, xAxis, yAxis), yAxis);\n dst[0] = xAxis[0];\n dst[1] = xAxis[1];\n dst[2] = xAxis[2];\n dst[3] = 0;\n dst[4] = yAxis[0];\n dst[5] = yAxis[1];\n dst[6] = yAxis[2];\n dst[7] = 0;\n dst[8] = zAxis[0];\n dst[9] = zAxis[1];\n dst[10] = zAxis[2];\n dst[11] = 0;\n dst[12] = eye[0];\n dst[13] = eye[1];\n dst[14] = eye[2];\n dst[15] = 1;\n return dst;\n}\n/**\n * Computes a 4-by-4 view transformation.\n *\n * This is a view matrix which transforms all other objects\n * to be in the space of the view defined by the parameters.\n *\n * @param eye - The position of the object.\n * @param target - The position meant to be aimed at.\n * @param up - A vector pointing up.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The look-at matrix.\n */\nfunction lookAt(eye, target, up, dst) {\n dst = dst || new MatType(16);\n xAxis = xAxis || create$4();\n yAxis = yAxis || create$4();\n zAxis = zAxis || create$4();\n normalize$2(subtract$2(eye, target, zAxis), zAxis);\n normalize$2(cross(up, zAxis, xAxis), xAxis);\n normalize$2(cross(zAxis, xAxis, yAxis), yAxis);\n dst[0] = xAxis[0];\n dst[1] = yAxis[0];\n dst[2] = zAxis[0];\n dst[3] = 0;\n dst[4] = xAxis[1];\n dst[5] = yAxis[1];\n dst[6] = zAxis[1];\n dst[7] = 0;\n dst[8] = xAxis[2];\n dst[9] = yAxis[2];\n dst[10] = zAxis[2];\n dst[11] = 0;\n dst[12] = -(xAxis[0] * eye[0] + xAxis[1] * eye[1] + xAxis[2] * eye[2]);\n dst[13] = -(yAxis[0] * eye[0] + yAxis[1] * eye[1] + yAxis[2] * eye[2]);\n dst[14] = -(zAxis[0] * eye[0] + zAxis[1] * eye[1] + zAxis[2] * eye[2]);\n dst[15] = 1;\n return dst;\n}\n/**\n * Creates a 4-by-4 matrix which translates by the given vector v.\n * @param v - The vector by\n * which to translate.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The translation matrix.\n */\nfunction translation(v, dst) {\n dst = dst || new MatType(16);\n dst[0] = 1;\n dst[1] = 0;\n dst[2] = 0;\n dst[3] = 0;\n dst[4] = 0;\n dst[5] = 1;\n dst[6] = 0;\n dst[7] = 0;\n dst[8] = 0;\n dst[9] = 0;\n dst[10] = 1;\n dst[11] = 0;\n dst[12] = v[0];\n dst[13] = v[1];\n dst[14] = v[2];\n dst[15] = 1;\n return dst;\n}\n/**\n * Translates the given 4-by-4 matrix by the given vector v.\n * @param m - The matrix.\n * @param v - The vector by\n * which to translate.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The translated matrix.\n */\nfunction translate(m, v, dst) {\n dst = dst || new MatType(16);\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n const m00 = m[0];\n const m01 = m[1];\n const m02 = m[2];\n const m03 = m[3];\n const m10 = m[1 * 4 + 0];\n const m11 = m[1 * 4 + 1];\n const m12 = m[1 * 4 + 2];\n const m13 = m[1 * 4 + 3];\n const m20 = m[2 * 4 + 0];\n const m21 = m[2 * 4 + 1];\n const m22 = m[2 * 4 + 2];\n const m23 = m[2 * 4 + 3];\n const m30 = m[3 * 4 + 0];\n const m31 = m[3 * 4 + 1];\n const m32 = m[3 * 4 + 2];\n const m33 = m[3 * 4 + 3];\n if (m !== dst) {\n dst[0] = m00;\n dst[1] = m01;\n dst[2] = m02;\n dst[3] = m03;\n dst[4] = m10;\n dst[5] = m11;\n dst[6] = m12;\n dst[7] = m13;\n dst[8] = m20;\n dst[9] = m21;\n dst[10] = m22;\n dst[11] = m23;\n }\n dst[12] = m00 * v0 + m10 * v1 + m20 * v2 + m30;\n dst[13] = m01 * v0 + m11 * v1 + m21 * v2 + m31;\n dst[14] = m02 * v0 + m12 * v1 + m22 * v2 + m32;\n dst[15] = m03 * v0 + m13 * v1 + m23 * v2 + m33;\n return dst;\n}\n/**\n * Creates a 4-by-4 matrix which rotates around the x-axis by the given angle.\n * @param angleInRadians - The angle by which to rotate (in radians).\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The rotation matrix.\n */\nfunction rotationX(angleInRadians, dst) {\n dst = dst || new MatType(16);\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n dst[0] = 1;\n dst[1] = 0;\n dst[2] = 0;\n dst[3] = 0;\n dst[4] = 0;\n dst[5] = c;\n dst[6] = s;\n dst[7] = 0;\n dst[8] = 0;\n dst[9] = -s;\n dst[10] = c;\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n return dst;\n}\n/**\n * Rotates the given 4-by-4 matrix around the x-axis by the given\n * angle.\n * @param m - The matrix.\n * @param angleInRadians - The angle by which to rotate (in radians).\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The rotated matrix.\n */\nfunction rotateX$1(m, angleInRadians, dst) {\n dst = dst || new MatType(16);\n const m10 = m[4];\n const m11 = m[5];\n const m12 = m[6];\n const m13 = m[7];\n const m20 = m[8];\n const m21 = m[9];\n const m22 = m[10];\n const m23 = m[11];\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n dst[4] = c * m10 + s * m20;\n dst[5] = c * m11 + s * m21;\n dst[6] = c * m12 + s * m22;\n dst[7] = c * m13 + s * m23;\n dst[8] = c * m20 - s * m10;\n dst[9] = c * m21 - s * m11;\n dst[10] = c * m22 - s * m12;\n dst[11] = c * m23 - s * m13;\n if (m !== dst) {\n dst[0] = m[0];\n dst[1] = m[1];\n dst[2] = m[2];\n dst[3] = m[3];\n dst[12] = m[12];\n dst[13] = m[13];\n dst[14] = m[14];\n dst[15] = m[15];\n }\n return dst;\n}\n/**\n * Creates a 4-by-4 matrix which rotates around the y-axis by the given angle.\n * @param angleInRadians - The angle by which to rotate (in radians).\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The rotation matrix.\n */\nfunction rotationY(angleInRadians, dst) {\n dst = dst || new MatType(16);\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n dst[0] = c;\n dst[1] = 0;\n dst[2] = -s;\n dst[3] = 0;\n dst[4] = 0;\n dst[5] = 1;\n dst[6] = 0;\n dst[7] = 0;\n dst[8] = s;\n dst[9] = 0;\n dst[10] = c;\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n return dst;\n}\n/**\n * Rotates the given 4-by-4 matrix around the y-axis by the given\n * angle.\n * @param m - The matrix.\n * @param angleInRadians - The angle by which to rotate (in radians).\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The rotated matrix.\n */\nfunction rotateY$1(m, angleInRadians, dst) {\n dst = dst || new MatType(16);\n const m00 = m[0 * 4 + 0];\n const m01 = m[0 * 4 + 1];\n const m02 = m[0 * 4 + 2];\n const m03 = m[0 * 4 + 3];\n const m20 = m[2 * 4 + 0];\n const m21 = m[2 * 4 + 1];\n const m22 = m[2 * 4 + 2];\n const m23 = m[2 * 4 + 3];\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n dst[0] = c * m00 - s * m20;\n dst[1] = c * m01 - s * m21;\n dst[2] = c * m02 - s * m22;\n dst[3] = c * m03 - s * m23;\n dst[8] = c * m20 + s * m00;\n dst[9] = c * m21 + s * m01;\n dst[10] = c * m22 + s * m02;\n dst[11] = c * m23 + s * m03;\n if (m !== dst) {\n dst[4] = m[4];\n dst[5] = m[5];\n dst[6] = m[6];\n dst[7] = m[7];\n dst[12] = m[12];\n dst[13] = m[13];\n dst[14] = m[14];\n dst[15] = m[15];\n }\n return dst;\n}\n/**\n * Creates a 4-by-4 matrix which rotates around the z-axis by the given angle.\n * @param angleInRadians - The angle by which to rotate (in radians).\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The rotation matrix.\n */\nfunction rotationZ(angleInRadians, dst) {\n dst = dst || new MatType(16);\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n dst[0] = c;\n dst[1] = s;\n dst[2] = 0;\n dst[3] = 0;\n dst[4] = -s;\n dst[5] = c;\n dst[6] = 0;\n dst[7] = 0;\n dst[8] = 0;\n dst[9] = 0;\n dst[10] = 1;\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n return dst;\n}\n/**\n * Rotates the given 4-by-4 matrix around the z-axis by the given\n * angle.\n * @param m - The matrix.\n * @param angleInRadians - The angle by which to rotate (in radians).\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The rotated matrix.\n */\nfunction rotateZ$1(m, angleInRadians, dst) {\n dst = dst || new MatType(16);\n const m00 = m[0 * 4 + 0];\n const m01 = m[0 * 4 + 1];\n const m02 = m[0 * 4 + 2];\n const m03 = m[0 * 4 + 3];\n const m10 = m[1 * 4 + 0];\n const m11 = m[1 * 4 + 1];\n const m12 = m[1 * 4 + 2];\n const m13 = m[1 * 4 + 3];\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n dst[0] = c * m00 + s * m10;\n dst[1] = c * m01 + s * m11;\n dst[2] = c * m02 + s * m12;\n dst[3] = c * m03 + s * m13;\n dst[4] = c * m10 - s * m00;\n dst[5] = c * m11 - s * m01;\n dst[6] = c * m12 - s * m02;\n dst[7] = c * m13 - s * m03;\n if (m !== dst) {\n dst[8] = m[8];\n dst[9] = m[9];\n dst[10] = m[10];\n dst[11] = m[11];\n dst[12] = m[12];\n dst[13] = m[13];\n dst[14] = m[14];\n dst[15] = m[15];\n }\n return dst;\n}\n/**\n * Creates a 4-by-4 matrix which rotates around the given axis by the given\n * angle.\n * @param axis - The axis\n * about which to rotate.\n * @param angleInRadians - The angle by which to rotate (in radians).\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns A matrix which rotates angle radians\n * around the axis.\n */\nfunction axisRotation(axis, angleInRadians, dst) {\n dst = dst || new MatType(16);\n let x = axis[0];\n let y = axis[1];\n let z = axis[2];\n const n = Math.sqrt(x * x + y * y + z * z);\n x /= n;\n y /= n;\n z /= n;\n const xx = x * x;\n const yy = y * y;\n const zz = z * z;\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n const oneMinusCosine = 1 - c;\n dst[0] = xx + (1 - xx) * c;\n dst[1] = x * y * oneMinusCosine + z * s;\n dst[2] = x * z * oneMinusCosine - y * s;\n dst[3] = 0;\n dst[4] = x * y * oneMinusCosine - z * s;\n dst[5] = yy + (1 - yy) * c;\n dst[6] = y * z * oneMinusCosine + x * s;\n dst[7] = 0;\n dst[8] = x * z * oneMinusCosine + y * s;\n dst[9] = y * z * oneMinusCosine - x * s;\n dst[10] = zz + (1 - zz) * c;\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n return dst;\n}\n/**\n * Creates a 4-by-4 matrix which rotates around the given axis by the given\n * angle. (same as axisRotation)\n * @param axis - The axis\n * about which to rotate.\n * @param angleInRadians - The angle by which to rotate (in radians).\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns A matrix which rotates angle radians\n * around the axis.\n */\nconst rotation = axisRotation;\n/**\n * Rotates the given 4-by-4 matrix around the given axis by the\n * given angle.\n * @param m - The matrix.\n * @param axis - The axis\n * about which to rotate.\n * @param angleInRadians - The angle by which to rotate (in radians).\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The rotated matrix.\n */\nfunction axisRotate(m, axis, angleInRadians, dst) {\n dst = dst || new MatType(16);\n let x = axis[0];\n let y = axis[1];\n let z = axis[2];\n const n = Math.sqrt(x * x + y * y + z * z);\n x /= n;\n y /= n;\n z /= n;\n const xx = x * x;\n const yy = y * y;\n const zz = z * z;\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n const oneMinusCosine = 1 - c;\n const r00 = xx + (1 - xx) * c;\n const r01 = x * y * oneMinusCosine + z * s;\n const r02 = x * z * oneMinusCosine - y * s;\n const r10 = x * y * oneMinusCosine - z * s;\n const r11 = yy + (1 - yy) * c;\n const r12 = y * z * oneMinusCosine + x * s;\n const r20 = x * z * oneMinusCosine + y * s;\n const r21 = y * z * oneMinusCosine - x * s;\n const r22 = zz + (1 - zz) * c;\n const m00 = m[0];\n const m01 = m[1];\n const m02 = m[2];\n const m03 = m[3];\n const m10 = m[4];\n const m11 = m[5];\n const m12 = m[6];\n const m13 = m[7];\n const m20 = m[8];\n const m21 = m[9];\n const m22 = m[10];\n const m23 = m[11];\n dst[0] = r00 * m00 + r01 * m10 + r02 * m20;\n dst[1] = r00 * m01 + r01 * m11 + r02 * m21;\n dst[2] = r00 * m02 + r01 * m12 + r02 * m22;\n dst[3] = r00 * m03 + r01 * m13 + r02 * m23;\n dst[4] = r10 * m00 + r11 * m10 + r12 * m20;\n dst[5] = r10 * m01 + r11 * m11 + r12 * m21;\n dst[6] = r10 * m02 + r11 * m12 + r12 * m22;\n dst[7] = r10 * m03 + r11 * m13 + r12 * m23;\n dst[8] = r20 * m00 + r21 * m10 + r22 * m20;\n dst[9] = r20 * m01 + r21 * m11 + r22 * m21;\n dst[10] = r20 * m02 + r21 * m12 + r22 * m22;\n dst[11] = r20 * m03 + r21 * m13 + r22 * m23;\n if (m !== dst) {\n dst[12] = m[12];\n dst[13] = m[13];\n dst[14] = m[14];\n dst[15] = m[15];\n }\n return dst;\n}\n/**\n * Rotates the given 4-by-4 matrix around the given axis by the\n * given angle. (same as rotate)\n * @param m - The matrix.\n * @param axis - The axis\n * about which to rotate.\n * @param angleInRadians - The angle by which to rotate (in radians).\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The rotated matrix.\n */\nconst rotate = axisRotate;\n/**\n * Creates a 4-by-4 matrix which scales in each dimension by an amount given by\n * the corresponding entry in the given vector; assumes the vector has three\n * entries.\n * @param v - A vector of\n * three entries specifying the factor by which to scale in each dimension.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The scaling matrix.\n */\nfunction scaling(v, dst) {\n dst = dst || new MatType(16);\n dst[0] = v[0];\n dst[1] = 0;\n dst[2] = 0;\n dst[3] = 0;\n dst[4] = 0;\n dst[5] = v[1];\n dst[6] = 0;\n dst[7] = 0;\n dst[8] = 0;\n dst[9] = 0;\n dst[10] = v[2];\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n return dst;\n}\n/**\n * Scales the given 4-by-4 matrix in each dimension by an amount\n * given by the corresponding entry in the given vector; assumes the vector has\n * three entries.\n * @param m - The matrix to be modified.\n * @param v - A vector of three entries specifying the\n * factor by which to scale in each dimension.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The scaled matrix.\n */\nfunction scale$2(m, v, dst) {\n dst = dst || new MatType(16);\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n dst[0] = v0 * m[0 * 4 + 0];\n dst[1] = v0 * m[0 * 4 + 1];\n dst[2] = v0 * m[0 * 4 + 2];\n dst[3] = v0 * m[0 * 4 + 3];\n dst[4] = v1 * m[1 * 4 + 0];\n dst[5] = v1 * m[1 * 4 + 1];\n dst[6] = v1 * m[1 * 4 + 2];\n dst[7] = v1 * m[1 * 4 + 3];\n dst[8] = v2 * m[2 * 4 + 0];\n dst[9] = v2 * m[2 * 4 + 1];\n dst[10] = v2 * m[2 * 4 + 2];\n dst[11] = v2 * m[2 * 4 + 3];\n if (m !== dst) {\n dst[12] = m[12];\n dst[13] = m[13];\n dst[14] = m[14];\n dst[15] = m[15];\n }\n return dst;\n}\n/**\n * Creates a 4-by-4 matrix which scales a uniform amount in each dimension.\n * @param s - the amount to scale\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The scaling matrix.\n */\nfunction uniformScaling(s, dst) {\n dst = dst || new MatType(16);\n dst[0] = s;\n dst[1] = 0;\n dst[2] = 0;\n dst[3] = 0;\n dst[4] = 0;\n dst[5] = s;\n dst[6] = 0;\n dst[7] = 0;\n dst[8] = 0;\n dst[9] = 0;\n dst[10] = s;\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n return dst;\n}\n/**\n * Scales the given 4-by-4 matrix in each dimension by a uniform scale.\n * @param m - The matrix to be modified.\n * @param s - The amount to scale.\n * @param dst - matrix to hold result. If not passed a new one is created.\n * @returns The scaled matrix.\n */\nfunction uniformScale(m, s, dst) {\n dst = dst || new MatType(16);\n dst[0] = s * m[0 * 4 + 0];\n dst[1] = s * m[0 * 4 + 1];\n dst[2] = s * m[0 * 4 + 2];\n dst[3] = s * m[0 * 4 + 3];\n dst[4] = s * m[1 * 4 + 0];\n dst[5] = s * m[1 * 4 + 1];\n dst[6] = s * m[1 * 4 + 2];\n dst[7] = s * m[1 * 4 + 3];\n dst[8] = s * m[2 * 4 + 0];\n dst[9] = s * m[2 * 4 + 1];\n dst[10] = s * m[2 * 4 + 2];\n dst[11] = s * m[2 * 4 + 3];\n if (m !== dst) {\n dst[12] = m[12];\n dst[13] = m[13];\n dst[14] = m[14];\n dst[15] = m[15];\n }\n return dst;\n}\n\nvar mat4Impl = /*#__PURE__*/Object.freeze({\n __proto__: null,\n setDefaultType: setDefaultType$3,\n create: create$2,\n set: set$2,\n fromMat3: fromMat3,\n fromQuat: fromQuat,\n negate: negate$1,\n copy: copy$2,\n clone: clone$2,\n equalsApproximately: equalsApproximately$2,\n equals: equals$2,\n identity: identity$1,\n transpose: transpose,\n inverse: inverse$2,\n determinant: determinant,\n invert: invert$1,\n multiply: multiply$2,\n mul: mul$2,\n setTranslation: setTranslation,\n getTranslation: getTranslation,\n getAxis: getAxis,\n setAxis: setAxis,\n getScaling: getScaling,\n perspective: perspective,\n ortho: ortho,\n frustum: frustum,\n aim: aim,\n cameraAim: cameraAim,\n lookAt: lookAt,\n translation: translation,\n translate: translate,\n rotationX: rotationX,\n rotateX: rotateX$1,\n rotationY: rotationY,\n rotateY: rotateY$1,\n rotationZ: rotationZ,\n rotateZ: rotateZ$1,\n axisRotation: axisRotation,\n rotation: rotation,\n axisRotate: axisRotate,\n rotate: rotate,\n scaling: scaling,\n scale: scale$2,\n uniformScaling: uniformScaling,\n uniformScale: uniformScale\n});\n\n/*\n * Copyright 2022 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n/**\n *\n * Quat4 math functions.\n *\n * Almost all functions take an optional `dst` argument. If it is not passed in the\n * functions will create a new `Quat4`. In other words you can do this\n *\n * const v = quat4.cross(v1, v2); // Creates a new Quat4 with the cross product of v1 x v2.\n *\n * or\n *\n * const v = quat4.create();\n * quat4.cross(v1, v2, v); // Puts the cross product of v1 x v2 in v\n *\n * The first style is often easier but depending on where it's used it generates garbage where\n * as there is almost never allocation with the second style.\n *\n * It is always safe to pass any vector as the destination. So for example\n *\n * quat4.cross(v1, v2, v1); // Puts the cross product of v1 x v2 in v1\n *\n */\nlet QuatType = Float32Array;\n/**\n * Sets the type this library creates for a Quat4\n * @param ctor - the constructor for the type. Either `Float32Array`, `Float64Array`, or `Array`\n * @returns previous constructor for Quat4\n */\nfunction setDefaultType$2(ctor) {\n const oldType = QuatType;\n QuatType = ctor;\n return oldType;\n}\n/**\n * Creates a quat4; may be called with x, y, z to set initial values.\n * @param x - Initial x value.\n * @param y - Initial y value.\n * @param z - Initial z value.\n * @param w - Initial w value.\n * @returns the created vector\n */\nfunction create$1(x, y, z, w) {\n const dst = new QuatType(4);\n if (x !== undefined) {\n dst[0] = x;\n if (y !== undefined) {\n dst[1] = y;\n if (z !== undefined) {\n dst[2] = z;\n if (w !== undefined) {\n dst[3] = w;\n }\n }\n }\n }\n return dst;\n}\n\n/*\n * Copyright 2022 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n/**\n * Creates a Quat; may be called with x, y, z to set initial values. (same as create)\n * @param x - Initial x value.\n * @param y - Initial y value.\n * @param z - Initial z value.\n * @param z - Initial w value.\n * @returns the created vector\n */\nconst fromValues$1 = create$1;\n/**\n * Sets the values of a Quat\n * Also see {@link quat.create} and {@link quat.copy}\n *\n * @param x first value\n * @param y second value\n * @param z third value\n * @param w fourth value\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector with its elements set.\n */\nfunction set$1(x, y, z, w, dst) {\n dst = dst || new QuatType(4);\n dst[0] = x;\n dst[1] = y;\n dst[2] = z;\n dst[3] = w;\n return dst;\n}\n/**\n * Sets a quaternion from the given angle and axis,\n * then returns it.\n *\n * @param axis - the axis to rotate around\n * @param angleInRadians - the angle\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns The quaternion that represents the given axis and angle\n **/\nfunction fromAxisAngle(axis, angleInRadians, dst) {\n dst = dst || new QuatType(4);\n const halfAngle = angleInRadians * 0.5;\n const s = Math.sin(halfAngle);\n dst[0] = s * axis[0];\n dst[1] = s * axis[1];\n dst[2] = s * axis[2];\n dst[3] = Math.cos(halfAngle);\n return dst;\n}\n/**\n * Gets the rotation axis and angle\n * @param q - quaternion to compute from\n * @param dst - Vec3 to hold result. If not passed in a new one is created.\n * @return angle and axis\n */\nfunction toAxisAngle(q, dst) {\n dst = dst || create$4(4);\n const angle = Math.acos(q[3]) * 2;\n const s = Math.sin(angle * 0.5);\n if (s > EPSILON) {\n dst[0] = q[0] / s;\n dst[1] = q[1] / s;\n dst[2] = q[2] / s;\n }\n else {\n dst[0] = 1;\n dst[1] = 0;\n dst[2] = 0;\n }\n return { angle, axis: dst };\n}\n/**\n * Returns the angle in degrees between two rotations a and b.\n * @param a - quaternion a\n * @param b - quaternion b\n * @return angle in radians between the two quaternions\n */\nfunction angle(a, b) {\n const d = dot$1(a, b);\n return Math.acos(2 * d * d - 1);\n}\n/**\n * Multiplies two quaternions\n *\n * @param a - the first quaternion\n * @param b - the second quaternion\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns A quaternion that is the result of a * b\n */\nfunction multiply$1(a, b, dst) {\n dst = dst || new QuatType(4);\n const ax = a[0];\n const ay = a[1];\n const az = a[2];\n const aw = a[3];\n const bx = b[0];\n const by = b[1];\n const bz = b[2];\n const bw = b[3];\n dst[0] = ax * bw + aw * bx + ay * bz - az * by;\n dst[1] = ay * bw + aw * by + az * bx - ax * bz;\n dst[2] = az * bw + aw * bz + ax * by - ay * bx;\n dst[3] = aw * bw - ax * bx - ay * by - az * bz;\n return dst;\n}\n/**\n * Multiplies two quaternions\n *\n * @param a - the first quaternion\n * @param b - the second quaternion\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns A quaternion that is the result of a * b\n */\nconst mul$1 = multiply$1;\n/**\n * Rotates the given quaternion around the X axis by the given angle.\n * @param q - quaternion to rotate\n * @param angleInRadians - The angle by which to rotate\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns A quaternion that is the result of a * b\n */\nfunction rotateX(q, angleInRadians, dst) {\n dst = dst || new QuatType(4);\n const halfAngle = angleInRadians * 0.5;\n const qx = q[0];\n const qy = q[1];\n const qz = q[2];\n const qw = q[3];\n const bx = Math.sin(halfAngle);\n const bw = Math.cos(halfAngle);\n dst[0] = qx * bw + qw * bx;\n dst[1] = qy * bw + qz * bx;\n dst[2] = qz * bw - qy * bx;\n dst[3] = qw * bw - qx * bx;\n return dst;\n}\n/**\n * Rotates the given quaternion around the Y axis by the given angle.\n * @param q - quaternion to rotate\n * @param angleInRadians - The angle by which to rotate\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns A quaternion that is the result of a * b\n */\nfunction rotateY(q, angleInRadians, dst) {\n dst = dst || new QuatType(4);\n const halfAngle = angleInRadians * 0.5;\n const qx = q[0];\n const qy = q[1];\n const qz = q[2];\n const qw = q[3];\n const by = Math.sin(halfAngle);\n const bw = Math.cos(halfAngle);\n dst[0] = qx * bw - qz * by;\n dst[1] = qy * bw + qw * by;\n dst[2] = qz * bw + qx * by;\n dst[3] = qw * bw - qy * by;\n return dst;\n}\n/**\n * Rotates the given quaternion around the Z axis by the given angle.\n * @param q - quaternion to rotate\n * @param angleInRadians - The angle by which to rotate\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns A quaternion that is the result of a * b\n */\nfunction rotateZ(q, angleInRadians, dst) {\n dst = dst || new QuatType(4);\n const halfAngle = angleInRadians * 0.5;\n const qx = q[0];\n const qy = q[1];\n const qz = q[2];\n const qw = q[3];\n const bz = Math.sin(halfAngle);\n const bw = Math.cos(halfAngle);\n dst[0] = qx * bw + qy * bz;\n dst[1] = qy * bw - qx * bz;\n dst[2] = qz * bw + qw * bz;\n dst[3] = qw * bw - qz * bz;\n return dst;\n}\n/**\n * Spherically linear interpolate between two quaternions\n *\n * @param a - starting value\n * @param b - ending value\n * @param t - value where 0 = a and 1 = b\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns A quaternion that is the result of a * b\n */\nfunction slerp(a, b, t, dst) {\n dst = dst || new QuatType(4);\n const ax = a[0];\n const ay = a[1];\n const az = a[2];\n const aw = a[3];\n let bx = b[0];\n let by = b[1];\n let bz = b[2];\n let bw = b[3];\n let cosOmega = ax * bx + ay * by + az * bz + aw * bw;\n if (cosOmega < 0) {\n cosOmega = -cosOmega;\n bx = -bx;\n by = -by;\n bz = -bz;\n bw = -bw;\n }\n let scale0;\n let scale1;\n if (1.0 - cosOmega > EPSILON) {\n const omega = Math.acos(cosOmega);\n const sinOmega = Math.sin(omega);\n scale0 = Math.sin((1 - t) * omega) / sinOmega;\n scale1 = Math.sin(t * omega) / sinOmega;\n }\n else {\n scale0 = 1.0 - t;\n scale1 = t;\n }\n dst[0] = scale0 * ax + scale1 * bx;\n dst[1] = scale0 * ay + scale1 * by;\n dst[2] = scale0 * az + scale1 * bz;\n dst[3] = scale0 * aw + scale1 * bw;\n return dst;\n}\n/**\n * Compute the inverse of a quaternion\n *\n * @param q - quaternion to compute the inverse of\n * @returns A quaternion that is the result of a * b\n */\nfunction inverse$1(q, dst) {\n dst = dst || new QuatType(4);\n const a0 = q[0];\n const a1 = q[1];\n const a2 = q[2];\n const a3 = q[3];\n const dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3;\n const invDot = dot ? 1 / dot : 0;\n dst[0] = -a0 * invDot;\n dst[1] = -a1 * invDot;\n dst[2] = -a2 * invDot;\n dst[3] = a3 * invDot;\n return dst;\n}\n/**\n * Compute the conjugate of a quaternion\n * For quaternions with a magnitude of 1 (a unit quaternion)\n * this returns the same as the inverse but is faster to calculate.\n *\n * @param q - quaternion to compute the conjugate of.\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns The conjugate of q\n */\nfunction conjugate(q, dst) {\n dst = dst || new QuatType(4);\n dst[0] = -q[0];\n dst[1] = -q[1];\n dst[2] = -q[2];\n dst[3] = q[3];\n return dst;\n}\n/**\n * Creates a quaternion from the given rotation matrix.\n *\n * The created quaternion is not normalized.\n *\n * @param m - rotation matrix\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns the result\n */\nfunction fromMat(m, dst) {\n dst = dst || new QuatType(4);\n /*\n 0 1 2\n 3 4 5\n 6 7 8\n \n 0 1 2\n 4 5 6\n 8 9 10\n */\n // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes\n // article \"Quaternion Calculus and Fast Animation\".\n const trace = m[0] + m[5] + m[10];\n if (trace > 0.0) {\n // |w| > 1/2, may as well choose w > 1/2\n const root = Math.sqrt(trace + 1); // 2w\n dst[3] = 0.5 * root;\n const invRoot = 0.5 / root; // 1/(4w)\n dst[0] = (m[6] - m[9]) * invRoot;\n dst[1] = (m[8] - m[2]) * invRoot;\n dst[2] = (m[1] - m[4]) * invRoot;\n }\n else {\n // |w| <= 1/2\n let i = 0;\n if (m[5] > m[0]) {\n i = 1;\n }\n if (m[10] > m[i * 4 + i]) {\n i = 2;\n }\n const j = (i + 1) % 3;\n const k = (i + 2) % 3;\n const root = Math.sqrt(m[i * 4 + i] - m[j * 4 + j] - m[k * 4 + k] + 1.0);\n dst[i] = 0.5 * root;\n const invRoot = 0.5 / root;\n dst[3] = (m[j * 4 + k] - m[k * 4 + j]) * invRoot;\n dst[j] = (m[j * 4 + i] + m[i * 4 + j]) * invRoot;\n dst[k] = (m[k * 4 + i] + m[i * 4 + k]) * invRoot;\n }\n return dst;\n}\n/**\n * Creates a quaternion from the given euler angle x, y, z using the provided intrinsic order for the conversion.\n *\n * @param xAngleInRadians - angle to rotate around X axis in radians.\n * @param yAngleInRadians - angle to rotate around Y axis in radians.\n * @param zAngleInRadians - angle to rotate around Z axis in radians.\n * @param order - order to apply euler angles\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns A quaternion representing the same rotation as the euler angles applied in the given order\n */\nfunction fromEuler(xAngleInRadians, yAngleInRadians, zAngleInRadians, order, dst) {\n dst = dst || new QuatType(4);\n const xHalfAngle = xAngleInRadians * 0.5;\n const yHalfAngle = yAngleInRadians * 0.5;\n const zHalfAngle = zAngleInRadians * 0.5;\n const sx = Math.sin(xHalfAngle);\n const cx = Math.cos(xHalfAngle);\n const sy = Math.sin(yHalfAngle);\n const cy = Math.cos(yHalfAngle);\n const sz = Math.sin(zHalfAngle);\n const cz = Math.cos(zHalfAngle);\n switch (order) {\n case 'xyz':\n dst[0] = sx * cy * cz + cx * sy * sz;\n dst[1] = cx * sy * cz - sx * cy * sz;\n dst[2] = cx * cy * sz + sx * sy * cz;\n dst[3] = cx * cy * cz - sx * sy * sz;\n break;\n case 'xzy':\n dst[0] = sx * cy * cz - cx * sy * sz;\n dst[1] = cx * sy * cz - sx * cy * sz;\n dst[2] = cx * cy * sz + sx * sy * cz;\n dst[3] = cx * cy * cz + sx * sy * sz;\n break;\n case 'yxz':\n dst[0] = sx * cy * cz + cx * sy * sz;\n dst[1] = cx * sy * cz - sx * cy * sz;\n dst[2] = cx * cy * sz - sx * sy * cz;\n dst[3] = cx * cy * cz + sx * sy * sz;\n break;\n case 'yzx':\n dst[0] = sx * cy * cz + cx * sy * sz;\n dst[1] = cx * sy * cz + sx * cy * sz;\n dst[2] = cx * cy * sz - sx * sy * cz;\n dst[3] = cx * cy * cz - sx * sy * sz;\n break;\n case 'zxy':\n dst[0] = sx * cy * cz - cx * sy * sz;\n dst[1] = cx * sy * cz + sx * cy * sz;\n dst[2] = cx * cy * sz + sx * sy * cz;\n dst[3] = cx * cy * cz - sx * sy * sz;\n break;\n case 'zyx':\n dst[0] = sx * cy * cz - cx * sy * sz;\n dst[1] = cx * sy * cz + sx * cy * sz;\n dst[2] = cx * cy * sz - sx * sy * cz;\n dst[3] = cx * cy * cz + sx * sy * sz;\n break;\n default:\n throw new Error(`Unknown rotation order: ${order}`);\n }\n return dst;\n}\n/**\n * Copies a quaternion. (same as {@link quat.clone})\n * Also see {@link quat.create} and {@link quat.set}\n * @param q - The quaternion.\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns A quaternion that is a copy of q\n */\nfunction copy$1(q, dst) {\n dst = dst || new QuatType(4);\n dst[0] = q[0];\n dst[1] = q[1];\n dst[2] = q[2];\n dst[3] = q[3];\n return dst;\n}\n/**\n * Clones a quaternion. (same as {@link quat.copy})\n * Also see {@link quat.create} and {@link quat.set}\n * @param q - The quaternion.\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns A copy of q.\n */\nconst clone$1 = copy$1;\n/**\n * Adds two quaternions; assumes a and b have the same dimension.\n * @param a - Operand quaternion.\n * @param b - Operand quaternion.\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns A quaternion that is the sum of a and b.\n */\nfunction add$1(a, b, dst) {\n dst = dst || new QuatType(4);\n dst[0] = a[0] + b[0];\n dst[1] = a[1] + b[1];\n dst[2] = a[2] + b[2];\n dst[3] = a[3] + b[3];\n return dst;\n}\n/**\n * Subtracts two quaternions.\n * @param a - Operand quaternion.\n * @param b - Operand quaternion.\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns A quaternion that is the difference of a and b.\n */\nfunction subtract$1(a, b, dst) {\n dst = dst || new QuatType(4);\n dst[0] = a[0] - b[0];\n dst[1] = a[1] - b[1];\n dst[2] = a[2] - b[2];\n dst[3] = a[3] - b[3];\n return dst;\n}\n/**\n * Subtracts two quaternions.\n * @param a - Operand quaternion.\n * @param b - Operand quaternion.\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns A quaternion that is the difference of a and b.\n */\nconst sub$1 = subtract$1;\n/**\n * Multiplies a quaternion by a scalar.\n * @param v - The quaternion.\n * @param k - The scalar.\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns The scaled quaternion.\n */\nfunction mulScalar$1(v, k, dst) {\n dst = dst || new QuatType(4);\n dst[0] = v[0] * k;\n dst[1] = v[1] * k;\n dst[2] = v[2] * k;\n dst[3] = v[3] * k;\n return dst;\n}\n/**\n * Multiplies a quaternion by a scalar. (same as mulScalar)\n * @param v - The quaternion.\n * @param k - The scalar.\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns The scaled quaternion.\n */\nconst scale$1 = mulScalar$1;\n/**\n * Divides a vector by a scalar.\n * @param v - The vector.\n * @param k - The scalar.\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns The scaled quaternion.\n */\nfunction divScalar$1(v, k, dst) {\n dst = dst || new QuatType(4);\n dst[0] = v[0] / k;\n dst[1] = v[1] / k;\n dst[2] = v[2] / k;\n dst[3] = v[3] / k;\n return dst;\n}\n/**\n * Computes the dot product of two quaternions\n * @param a - Operand quaternion.\n * @param b - Operand quaternion.\n * @returns dot product\n */\nfunction dot$1(a, b) {\n return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]) + (a[3] * b[3]);\n}\n/**\n * Performs linear interpolation on two quaternions.\n * Given quaternions a and b and interpolation coefficient t, returns\n * a + t * (b - a).\n * @param a - Operand quaternion.\n * @param b - Operand quaternion.\n * @param t - Interpolation coefficient.\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns The linear interpolated result.\n */\nfunction lerp$1(a, b, t, dst) {\n dst = dst || new QuatType(4);\n dst[0] = a[0] + t * (b[0] - a[0]);\n dst[1] = a[1] + t * (b[1] - a[1]);\n dst[2] = a[2] + t * (b[2] - a[2]);\n dst[3] = a[3] + t * (b[3] - a[3]);\n return dst;\n}\n/**\n * Computes the length of quaternion\n * @param v - quaternion.\n * @returns length of quaternion.\n */\nfunction length$1(v) {\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n const v3 = v[3];\n return Math.sqrt(v0 * v0 + v1 * v1 + v2 * v2 + v3 * v3);\n}\n/**\n * Computes the length of quaternion (same as length)\n * @param v - quaternion.\n * @returns length of quaternion.\n */\nconst len$1 = length$1;\n/**\n * Computes the square of the length of quaternion\n * @param v - quaternion.\n * @returns square of the length of quaternion.\n */\nfunction lengthSq$1(v) {\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n const v3 = v[3];\n return v0 * v0 + v1 * v1 + v2 * v2 + v3 * v3;\n}\n/**\n * Computes the square of the length of quaternion (same as lengthSq)\n * @param v - quaternion.\n * @returns square of the length of quaternion.\n */\nconst lenSq$1 = lengthSq$1;\n/**\n * Divides a quaternion by its Euclidean length and returns the quotient.\n * @param v - The quaternion.\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns The normalized quaternion.\n */\nfunction normalize$1(v, dst) {\n dst = dst || new QuatType(4);\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n const v3 = v[3];\n const len = Math.sqrt(v0 * v0 + v1 * v1 + v2 * v2 + v3 * v3);\n if (len > 0.00001) {\n dst[0] = v0 / len;\n dst[1] = v1 / len;\n dst[2] = v2 / len;\n dst[3] = v3 / len;\n }\n else {\n dst[0] = 0;\n dst[1] = 0;\n dst[2] = 0;\n dst[3] = 0;\n }\n return dst;\n}\n/**\n * Check if 2 quaternions are approximately equal\n * @param a - Operand quaternion.\n * @param b - Operand quaternion.\n * @returns true if quaternions are approximately equal\n */\nfunction equalsApproximately$1(a, b) {\n return Math.abs(a[0] - b[0]) < EPSILON &&\n Math.abs(a[1] - b[1]) < EPSILON &&\n Math.abs(a[2] - b[2]) < EPSILON &&\n Math.abs(a[3] - b[3]) < EPSILON;\n}\n/**\n * Check if 2 quaternions are exactly equal\n * @param a - Operand quaternion.\n * @param b - Operand quaternion.\n * @returns true if quaternions are exactly equal\n */\nfunction equals$1(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];\n}\n/**\n * Creates an identity quaternion\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns an identity quaternion\n */\nfunction identity(dst) {\n dst = dst || new QuatType(4);\n dst[0] = 0;\n dst[1] = 0;\n dst[2] = 0;\n dst[3] = 1;\n return dst;\n}\nlet tempVec3;\nlet xUnitVec3;\nlet yUnitVec3;\n/**\n * Computes a quaternion to represent the shortest rotation from one vector to another.\n *\n * @param aUnit - the start vector\n * @param bUnit - the end vector\n * @param dst - quaternion to hold result. If not passed in a new one is created.\n * @returns the result\n */\nfunction rotationTo(aUnit, bUnit, dst) {\n dst = dst || new QuatType(4);\n tempVec3 = tempVec3 || create$4();\n xUnitVec3 = xUnitVec3 || create$4(1, 0, 0);\n yUnitVec3 = yUnitVec3 || create$4(0, 1, 0);\n const dot = dot$2(aUnit, bUnit);\n if (dot < -0.999999) {\n cross(xUnitVec3, aUnit, tempVec3);\n if (len$2(tempVec3) < 0.000001) {\n cross(yUnitVec3, aUnit, tempVec3);\n }\n normalize$2(tempVec3, tempVec3);\n fromAxisAngle(tempVec3, Math.PI, dst);\n return dst;\n }\n else if (dot > 0.999999) {\n dst[0] = 0;\n dst[1] = 0;\n dst[2] = 0;\n dst[3] = 1;\n return dst;\n }\n else {\n cross(aUnit, bUnit, tempVec3);\n dst[0] = tempVec3[0];\n dst[1] = tempVec3[1];\n dst[2] = tempVec3[2];\n dst[3] = 1 + dot;\n return normalize$1(dst, dst);\n }\n}\nlet tempQuat1;\nlet tempQuat2;\n/**\n * Performs a spherical linear interpolation with two control points\n *\n * @param a - the first quaternion\n * @param b - the second quaternion\n * @param c - the third quaternion\n * @param d - the fourth quaternion\n * @param t - Interpolation coefficient 0 to 1\n * @returns result\n */\nfunction sqlerp(a, b, c, d, t, dst) {\n dst = dst || new QuatType(4);\n tempQuat1 = tempQuat1 || new QuatType(4);\n tempQuat2 = tempQuat2 || new QuatType(4);\n slerp(a, d, t, tempQuat1);\n slerp(b, c, t, tempQuat2);\n slerp(tempQuat1, tempQuat2, 2 * t * (1 - t), dst);\n return dst;\n}\n\nvar quatImpl = /*#__PURE__*/Object.freeze({\n __proto__: null,\n create: create$1,\n setDefaultType: setDefaultType$2,\n fromValues: fromValues$1,\n set: set$1,\n fromAxisAngle: fromAxisAngle,\n toAxisAngle: toAxisAngle,\n angle: angle,\n multiply: multiply$1,\n mul: mul$1,\n rotateX: rotateX,\n rotateY: rotateY,\n rotateZ: rotateZ,\n slerp: slerp,\n inverse: inverse$1,\n conjugate: conjugate,\n fromMat: fromMat,\n fromEuler: fromEuler,\n copy: copy$1,\n clone: clone$1,\n add: add$1,\n subtract: subtract$1,\n sub: sub$1,\n mulScalar: mulScalar$1,\n scale: scale$1,\n divScalar: divScalar$1,\n dot: dot$1,\n lerp: lerp$1,\n length: length$1,\n len: len$1,\n lengthSq: lengthSq$1,\n lenSq: lenSq$1,\n normalize: normalize$1,\n equalsApproximately: equalsApproximately$1,\n equals: equals$1,\n identity: identity,\n rotationTo: rotationTo,\n sqlerp: sqlerp\n});\n\n/*\n * Copyright 2022 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n/**\n *\n * Vec4 math functions.\n *\n * Almost all functions take an optional `dst` argument. If it is not passed in the\n * functions will create a new `Vec4`. In other words you can do this\n *\n * const v = vec4.cross(v1, v2); // Creates a new Vec4 with the cross product of v1 x v2.\n *\n * or\n *\n * const v = vec4.create();\n * vec4.cross(v1, v2, v); // Puts the cross product of v1 x v2 in v\n *\n * The first style is often easier but depending on where it's used it generates garbage where\n * as there is almost never allocation with the second style.\n *\n * It is always safe to pass any vector as the destination. So for example\n *\n * vec4.cross(v1, v2, v1); // Puts the cross product of v1 x v2 in v1\n *\n */\nlet VecType = Float32Array;\n/**\n * Sets the type this library creates for a Vec4\n * @param ctor - the constructor for the type. Either `Float32Array`, `Float64Array`, or `Array`\n * @returns previous constructor for Vec4\n */\nfunction setDefaultType$1(ctor) {\n const oldType = VecType;\n VecType = ctor;\n return oldType;\n}\n/**\n * Creates a vec4; may be called with x, y, z to set initial values.\n * @param x - Initial x value.\n * @param y - Initial y value.\n * @param z - Initial z value.\n * @param w - Initial w value.\n * @returns the created vector\n */\nfunction create(x, y, z, w) {\n const dst = new VecType(4);\n if (x !== undefined) {\n dst[0] = x;\n if (y !== undefined) {\n dst[1] = y;\n if (z !== undefined) {\n dst[2] = z;\n if (w !== undefined) {\n dst[3] = w;\n }\n }\n }\n }\n return dst;\n}\n\n/*\n * Copyright 2022 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n/**\n * Creates a vec4; may be called with x, y, z to set initial values. (same as create)\n * @param x - Initial x value.\n * @param y - Initial y value.\n * @param z - Initial z value.\n * @param z - Initial w value.\n * @returns the created vector\n */\nconst fromValues = create;\n/**\n * Sets the values of a Vec4\n * Also see {@link vec4.create} and {@link vec4.copy}\n *\n * @param x first value\n * @param y second value\n * @param z third value\n * @param w fourth value\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector with its elements set.\n */\nfunction set(x, y, z, w, dst) {\n dst = dst || new VecType(4);\n dst[0] = x;\n dst[1] = y;\n dst[2] = z;\n dst[3] = w;\n return dst;\n}\n/**\n * Applies Math.ceil to each element of vector\n * @param v - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the ceil of each element of v.\n */\nfunction ceil(v, dst) {\n dst = dst || new VecType(4);\n dst[0] = Math.ceil(v[0]);\n dst[1] = Math.ceil(v[1]);\n dst[2] = Math.ceil(v[2]);\n dst[3] = Math.ceil(v[3]);\n return dst;\n}\n/**\n * Applies Math.floor to each element of vector\n * @param v - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the floor of each element of v.\n */\nfunction floor(v, dst) {\n dst = dst || new VecType(4);\n dst[0] = Math.floor(v[0]);\n dst[1] = Math.floor(v[1]);\n dst[2] = Math.floor(v[2]);\n dst[3] = Math.floor(v[3]);\n return dst;\n}\n/**\n * Applies Math.round to each element of vector\n * @param v - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the round of each element of v.\n */\nfunction round(v, dst) {\n dst = dst || new VecType(4);\n dst[0] = Math.round(v[0]);\n dst[1] = Math.round(v[1]);\n dst[2] = Math.round(v[2]);\n dst[3] = Math.round(v[3]);\n return dst;\n}\n/**\n * Clamp each element of vector between min and max\n * @param v - Operand vector.\n * @param max - Min value, default 0\n * @param min - Max value, default 1\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that the clamped value of each element of v.\n */\nfunction clamp(v, min = 0, max = 1, dst) {\n dst = dst || new VecType(4);\n dst[0] = Math.min(max, Math.max(min, v[0]));\n dst[1] = Math.min(max, Math.max(min, v[1]));\n dst[2] = Math.min(max, Math.max(min, v[2]));\n dst[3] = Math.min(max, Math.max(min, v[3]));\n return dst;\n}\n/**\n * Adds two vectors; assumes a and b have the same dimension.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the sum of a and b.\n */\nfunction add(a, b, dst) {\n dst = dst || new VecType(4);\n dst[0] = a[0] + b[0];\n dst[1] = a[1] + b[1];\n dst[2] = a[2] + b[2];\n dst[3] = a[3] + b[3];\n return dst;\n}\n/**\n * Adds two vectors, scaling the 2nd; assumes a and b have the same dimension.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param scale - Amount to scale b\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the sum of a + b * scale.\n */\nfunction addScaled(a, b, scale, dst) {\n dst = dst || new VecType(4);\n dst[0] = a[0] + b[0] * scale;\n dst[1] = a[1] + b[1] * scale;\n dst[2] = a[2] + b[2] * scale;\n dst[3] = a[3] + b[3] * scale;\n return dst;\n}\n/**\n * Subtracts two vectors.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the difference of a and b.\n */\nfunction subtract(a, b, dst) {\n dst = dst || new VecType(4);\n dst[0] = a[0] - b[0];\n dst[1] = a[1] - b[1];\n dst[2] = a[2] - b[2];\n dst[3] = a[3] - b[3];\n return dst;\n}\n/**\n * Subtracts two vectors.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A vector that is the difference of a and b.\n */\nconst sub = subtract;\n/**\n * Check if 2 vectors are approximately equal\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @returns true if vectors are approximately equal\n */\nfunction equalsApproximately(a, b) {\n return Math.abs(a[0] - b[0]) < EPSILON &&\n Math.abs(a[1] - b[1]) < EPSILON &&\n Math.abs(a[2] - b[2]) < EPSILON &&\n Math.abs(a[3] - b[3]) < EPSILON;\n}\n/**\n * Check if 2 vectors are exactly equal\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @returns true if vectors are exactly equal\n */\nfunction equals(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];\n}\n/**\n * Performs linear interpolation on two vectors.\n * Given vectors a and b and interpolation coefficient t, returns\n * a + t * (b - a).\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param t - Interpolation coefficient.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The linear interpolated result.\n */\nfunction lerp(a, b, t, dst) {\n dst = dst || new VecType(4);\n dst[0] = a[0] + t * (b[0] - a[0]);\n dst[1] = a[1] + t * (b[1] - a[1]);\n dst[2] = a[2] + t * (b[2] - a[2]);\n dst[3] = a[3] + t * (b[3] - a[3]);\n return dst;\n}\n/**\n * Performs linear interpolation on two vectors.\n * Given vectors a and b and interpolation coefficient vector t, returns\n * a + t * (b - a).\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param t - Interpolation coefficients vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns the linear interpolated result.\n */\nfunction lerpV(a, b, t, dst) {\n dst = dst || new VecType(4);\n dst[0] = a[0] + t[0] * (b[0] - a[0]);\n dst[1] = a[1] + t[1] * (b[1] - a[1]);\n dst[2] = a[2] + t[2] * (b[2] - a[2]);\n dst[3] = a[3] + t[3] * (b[3] - a[3]);\n return dst;\n}\n/**\n * Return max values of two vectors.\n * Given vectors a and b returns\n * [max(a[0], b[0]), max(a[1], b[1]), max(a[2], b[2])].\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The max components vector.\n */\nfunction max(a, b, dst) {\n dst = dst || new VecType(4);\n dst[0] = Math.max(a[0], b[0]);\n dst[1] = Math.max(a[1], b[1]);\n dst[2] = Math.max(a[2], b[2]);\n dst[3] = Math.max(a[3], b[3]);\n return dst;\n}\n/**\n * Return min values of two vectors.\n * Given vectors a and b returns\n * [min(a[0], b[0]), min(a[1], b[1]), min(a[2], b[2])].\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The min components vector.\n */\nfunction min(a, b, dst) {\n dst = dst || new VecType(4);\n dst[0] = Math.min(a[0], b[0]);\n dst[1] = Math.min(a[1], b[1]);\n dst[2] = Math.min(a[2], b[2]);\n dst[3] = Math.min(a[3], b[3]);\n return dst;\n}\n/**\n * Multiplies a vector by a scalar.\n * @param v - The vector.\n * @param k - The scalar.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The scaled vector.\n */\nfunction mulScalar(v, k, dst) {\n dst = dst || new VecType(4);\n dst[0] = v[0] * k;\n dst[1] = v[1] * k;\n dst[2] = v[2] * k;\n dst[3] = v[3] * k;\n return dst;\n}\n/**\n * Multiplies a vector by a scalar. (same as mulScalar)\n * @param v - The vector.\n * @param k - The scalar.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The scaled vector.\n */\nconst scale = mulScalar;\n/**\n * Divides a vector by a scalar.\n * @param v - The vector.\n * @param k - The scalar.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The scaled vector.\n */\nfunction divScalar(v, k, dst) {\n dst = dst || new VecType(4);\n dst[0] = v[0] / k;\n dst[1] = v[1] / k;\n dst[2] = v[2] / k;\n dst[3] = v[3] / k;\n return dst;\n}\n/**\n * Inverse a vector.\n * @param v - The vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The inverted vector.\n */\nfunction inverse(v, dst) {\n dst = dst || new VecType(4);\n dst[0] = 1 / v[0];\n dst[1] = 1 / v[1];\n dst[2] = 1 / v[2];\n dst[3] = 1 / v[3];\n return dst;\n}\n/**\n * Invert a vector. (same as inverse)\n * @param v - The vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The inverted vector.\n */\nconst invert = inverse;\n/**\n * Computes the dot product of two vectors\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @returns dot product\n */\nfunction dot(a, b) {\n return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]) + (a[3] * b[3]);\n}\n/**\n * Computes the length of vector\n * @param v - vector.\n * @returns length of vector.\n */\nfunction length(v) {\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n const v3 = v[3];\n return Math.sqrt(v0 * v0 + v1 * v1 + v2 * v2 + v3 * v3);\n}\n/**\n * Computes the length of vector (same as length)\n * @param v - vector.\n * @returns length of vector.\n */\nconst len = length;\n/**\n * Computes the square of the length of vector\n * @param v - vector.\n * @returns square of the length of vector.\n */\nfunction lengthSq(v) {\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n const v3 = v[3];\n return v0 * v0 + v1 * v1 + v2 * v2 + v3 * v3;\n}\n/**\n * Computes the square of the length of vector (same as lengthSq)\n * @param v - vector.\n * @returns square of the length of vector.\n */\nconst lenSq = lengthSq;\n/**\n * Computes the distance between 2 points\n * @param a - vector.\n * @param b - vector.\n * @returns distance between a and b\n */\nfunction distance(a, b) {\n const dx = a[0] - b[0];\n const dy = a[1] - b[1];\n const dz = a[2] - b[2];\n const dw = a[3] - b[3];\n return Math.sqrt(dx * dx + dy * dy + dz * dz + dw * dw);\n}\n/**\n * Computes the distance between 2 points (same as distance)\n * @param a - vector.\n * @param b - vector.\n * @returns distance between a and b\n */\nconst dist = distance;\n/**\n * Computes the square of the distance between 2 points\n * @param a - vector.\n * @param b - vector.\n * @returns square of the distance between a and b\n */\nfunction distanceSq(a, b) {\n const dx = a[0] - b[0];\n const dy = a[1] - b[1];\n const dz = a[2] - b[2];\n const dw = a[3] - b[3];\n return dx * dx + dy * dy + dz * dz + dw * dw;\n}\n/**\n * Computes the square of the distance between 2 points (same as distanceSq)\n * @param a - vector.\n * @param b - vector.\n * @returns square of the distance between a and b\n */\nconst distSq = distanceSq;\n/**\n * Divides a vector by its Euclidean length and returns the quotient.\n * @param v - The vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The normalized vector.\n */\nfunction normalize(v, dst) {\n dst = dst || new VecType(4);\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n const v3 = v[3];\n const len = Math.sqrt(v0 * v0 + v1 * v1 + v2 * v2 + v3 * v3);\n if (len > 0.00001) {\n dst[0] = v0 / len;\n dst[1] = v1 / len;\n dst[2] = v2 / len;\n dst[3] = v3 / len;\n }\n else {\n dst[0] = 0;\n dst[1] = 0;\n dst[2] = 0;\n dst[3] = 0;\n }\n return dst;\n}\n/**\n * Negates a vector.\n * @param v - The vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns -v.\n */\nfunction negate(v, dst) {\n dst = dst || new VecType(4);\n dst[0] = -v[0];\n dst[1] = -v[1];\n dst[2] = -v[2];\n dst[3] = -v[3];\n return dst;\n}\n/**\n * Copies a vector. (same as {@link vec4.clone})\n * Also see {@link vec4.create} and {@link vec4.set}\n * @param v - The vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A copy of v.\n */\nfunction copy(v, dst) {\n dst = dst || new VecType(4);\n dst[0] = v[0];\n dst[1] = v[1];\n dst[2] = v[2];\n dst[3] = v[3];\n return dst;\n}\n/**\n * Clones a vector. (same as {@link vec4.copy})\n * Also see {@link vec4.create} and {@link vec4.set}\n * @param v - The vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns A copy of v.\n */\nconst clone = copy;\n/**\n * Multiplies a vector by another vector (component-wise); assumes a and\n * b have the same length.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The vector of products of entries of a and b.\n */\nfunction multiply(a, b, dst) {\n dst = dst || new VecType(4);\n dst[0] = a[0] * b[0];\n dst[1] = a[1] * b[1];\n dst[2] = a[2] * b[2];\n dst[3] = a[3] * b[3];\n return dst;\n}\n/**\n * Multiplies a vector by another vector (component-wise); assumes a and\n * b have the same length. (same as mul)\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The vector of products of entries of a and b.\n */\nconst mul = multiply;\n/**\n * Divides a vector by another vector (component-wise); assumes a and\n * b have the same length.\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The vector of quotients of entries of a and b.\n */\nfunction divide(a, b, dst) {\n dst = dst || new VecType(4);\n dst[0] = a[0] / b[0];\n dst[1] = a[1] / b[1];\n dst[2] = a[2] / b[2];\n dst[3] = a[3] / b[3];\n return dst;\n}\n/**\n * Divides a vector by another vector (component-wise); assumes a and\n * b have the same length. (same as divide)\n * @param a - Operand vector.\n * @param b - Operand vector.\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The vector of quotients of entries of a and b.\n */\nconst div = divide;\n/**\n * Zero's a vector\n * @param dst - vector to hold result. If not passed in a new one is created.\n * @returns The zeroed vector.\n */\nfunction zero(dst) {\n dst = dst || new VecType(4);\n dst[0] = 0;\n dst[1] = 0;\n dst[2] = 0;\n dst[3] = 0;\n return dst;\n}\n/**\n * transform vec4 by 4x4 matrix\n * @param v - the vector\n * @param m - The matrix.\n * @param dst - optional vec4 to store result. If not passed a new one is created.\n * @returns the transformed vector\n */\nfunction transformMat4(v, m, dst) {\n dst = dst || new VecType(4);\n const x = v[0];\n const y = v[1];\n const z = v[2];\n const w = v[3];\n dst[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;\n dst[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;\n dst[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;\n dst[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;\n return dst;\n}\n\nvar vec4Impl = /*#__PURE__*/Object.freeze({\n __proto__: null,\n create: create,\n setDefaultType: setDefaultType$1,\n fromValues: fromValues,\n set: set,\n ceil: ceil,\n floor: floor,\n round: round,\n clamp: clamp,\n add: add,\n addScaled: addScaled,\n subtract: subtract,\n sub: sub,\n equalsApproximately: equalsApproximately,\n equals: equals,\n lerp: lerp,\n lerpV: lerpV,\n max: max,\n min: min,\n mulScalar: mulScalar,\n scale: scale,\n divScalar: divScalar,\n inverse: inverse,\n invert: invert,\n dot: dot,\n length: length,\n len: len,\n lengthSq: lengthSq,\n lenSq: lenSq,\n distance: distance,\n dist: dist,\n distanceSq: distanceSq,\n distSq: distSq,\n normalize: normalize,\n negate: negate,\n copy: copy,\n clone: clone,\n multiply: multiply,\n mul: mul,\n divide: divide,\n div: div,\n zero: zero,\n transformMat4: transformMat4\n});\n\n/**\n * Sets the type this library creates for all types\n *\n * example:\n *\n * ```\n * setDefaultType(Float64Array);\n * ```\n *\n * @param ctor - the constructor for the type. Either `Float32Array`, `Float64Array`, or `Array`\n */\nfunction setDefaultType(ctor) {\n setDefaultType$4(ctor);\n setDefaultType$3(ctor);\n setDefaultType$2(ctor);\n setDefaultType$6(ctor);\n setDefaultType$5(ctor);\n setDefaultType$1(ctor);\n}\n\nexport { mat3Impl as mat3, mat4Impl as mat4, quatImpl as quat, setDefaultType, utils, vec2Impl as vec2, vec3Impl as vec3, vec4Impl as vec4 };\n//# sourceMappingURL=wgpu-matrix.module.js.map\n","export const cubeVertexSize = 4 * 10; // Byte size of one cube vertex.\nexport const cubePositionOffset = 0;\nexport const cubeColorOffset = 4 * 4; // Byte offset of cube vertex color attribute.\nexport const cubeUVOffset = 4 * 8;\nexport const cubeVertexCount = 36;\n\n// prettier-ignore\nexport const cubeVertexArray = new Float32Array([\n // float4 position, float4 color, float2 uv,\n 1, -1, 1, 1, 1, 0, 1, 1, 0, 1,\n -1, -1, 1, 1, 0, 0, 1, 1, 1, 1,\n -1, -1, -1, 1, 0, 0, 0, 1, 1, 0,\n 1, -1, -1, 1, 1, 0, 0, 1, 0, 0,\n 1, -1, 1, 1, 1, 0, 1, 1, 0, 1,\n -1, -1, -1, 1, 0, 0, 0, 1, 1, 0,\n\n 1, 1, 1, 1, 1, 1, 1, 1, 0, 1,\n 1, -1, 1, 1, 1, 0, 1, 1, 1, 1,\n 1, -1, -1, 1, 1, 0, 0, 1, 1, 0,\n 1, 1, -1, 1, 1, 1, 0, 1, 0, 0,\n 1, 1, 1, 1, 1, 1, 1, 1, 0, 1,\n 1, -1, -1, 1, 1, 0, 0, 1, 1, 0,\n\n -1, 1, 1, 1, 0, 1, 1, 1, 0, 1,\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n 1, 1, -1, 1, 1, 1, 0, 1, 1, 0,\n -1, 1, -1, 1, 0, 1, 0, 1, 0, 0,\n -1, 1, 1, 1, 0, 1, 1, 1, 0, 1,\n 1, 1, -1, 1, 1, 1, 0, 1, 1, 0,\n\n -1, -1, 1, 1, 0, 0, 1, 1, 0, 1,\n -1, 1, 1, 1, 0, 1, 1, 1, 1, 1,\n -1, 1, -1, 1, 0, 1, 0, 1, 1, 0,\n -1, -1, -1, 1, 0, 0, 0, 1, 0, 0,\n -1, -1, 1, 1, 0, 0, 1, 1, 0, 1,\n -1, 1, -1, 1, 0, 1, 0, 1, 1, 0,\n\n 1, 1, 1, 1, 1, 1, 1, 1, 0, 1,\n -1, 1, 1, 1, 0, 1, 1, 1, 1, 1,\n -1, -1, 1, 1, 0, 0, 1, 1, 1, 0,\n -1, -1, 1, 1, 0, 0, 1, 1, 1, 0,\n 1, -1, 1, 1, 1, 0, 1, 1, 0, 0,\n 1, 1, 1, 1, 1, 1, 1, 1, 0, 1,\n\n 1, -1, -1, 1, 1, 0, 0, 1, 0, 1,\n -1, -1, -1, 1, 0, 0, 0, 1, 1, 1,\n -1, 1, -1, 1, 0, 1, 0, 1, 1, 0,\n 1, 1, -1, 1, 1, 1, 0, 1, 0, 0,\n 1, -1, -1, 1, 1, 0, 0, 1, 0, 1,\n -1, 1, -1, 1, 0, 1, 0, 1, 1, 0,\n]);\n","import { mat4 } from 'wgpu-matrix';\n\nimport msdfTextWGSL from './msdfText.wgsl';\n\ntype Mat4 = mat4.default;\n\n// The kerning map stores a spare map of character ID pairs with an associated\n// X offset that should be applied to the character spacing when the second\n// character ID is rendered after the first.\ntype KerningMap = Map>;\n\ninterface MsdfChar {\n id: number;\n index: number;\n char: string;\n width: number;\n height: number;\n xoffset: number;\n yofsset: number;\n xadvance: number;\n chnl: number;\n x: number;\n y: number;\n page: number;\n charIndex: number;\n}\n\nexport class MsdfFont {\n charCount: number;\n defaultChar: MsdfChar;\n constructor(\n public pipeline: GPURenderPipeline,\n public bindGroup: GPUBindGroup,\n public lineHeight: number,\n public chars: { [x: number]: MsdfChar },\n public kernings: KerningMap\n ) {\n const charArray = Object.values(chars);\n this.charCount = charArray.length;\n this.defaultChar = charArray[0];\n }\n\n getChar(charCode: number): MsdfChar {\n let char = this.chars[charCode];\n if (!char) {\n char = this.defaultChar;\n }\n return char;\n }\n\n // Gets the distance in pixels a line should advance for a given character code. If the upcoming\n // character code is given any kerning between the two characters will be taken into account.\n getXAdvance(charCode: number, nextCharCode: number = -1): number {\n const char = this.getChar(charCode);\n if (nextCharCode >= 0) {\n const kerning = this.kernings.get(charCode);\n if (kerning) {\n return char.xadvance + (kerning.get(nextCharCode) ?? 0);\n }\n }\n return char.xadvance;\n }\n}\n\nexport interface MsdfTextMeasurements {\n width: number;\n height: number;\n lineWidths: number[];\n printedCharCount: number;\n}\n\nexport class MsdfText {\n private bufferArray = new Float32Array(24);\n private bufferArrayDirty = true;\n\n constructor(\n public device: GPUDevice,\n private renderBundle: GPURenderBundle,\n public measurements: MsdfTextMeasurements,\n public font: MsdfFont,\n public textBuffer: GPUBuffer\n ) {\n mat4.identity(this.bufferArray);\n this.setColor(1, 1, 1, 1);\n this.setPixelScale(1 / 512);\n this.bufferArrayDirty = true;\n }\n\n getRenderBundle() {\n if (this.bufferArrayDirty) {\n this.bufferArrayDirty = false;\n this.device.queue.writeBuffer(\n this.textBuffer,\n 0,\n this.bufferArray,\n 0,\n this.bufferArray.length\n );\n }\n return this.renderBundle;\n }\n\n setTransform(matrix: Mat4) {\n mat4.copy(matrix, this.bufferArray);\n this.bufferArrayDirty = true;\n }\n\n setColor(r: number, g: number, b: number, a: number = 1.0) {\n this.bufferArray[16] = r;\n this.bufferArray[17] = g;\n this.bufferArray[18] = b;\n this.bufferArray[19] = a;\n this.bufferArrayDirty = true;\n }\n\n setPixelScale(pixelScale: number) {\n this.bufferArray[20] = pixelScale;\n this.bufferArrayDirty = true;\n }\n}\n\nexport interface MsdfTextFormattingOptions {\n centered?: boolean;\n pixelScale?: number;\n color?: [number, number, number, number];\n}\n\nexport class MsdfTextRenderer {\n fontBindGroupLayout: GPUBindGroupLayout;\n textBindGroupLayout: GPUBindGroupLayout;\n pipelinePromise: Promise;\n sampler: GPUSampler;\n cameraUniformBuffer: GPUBuffer;\n\n renderBundleDescriptor: GPURenderBundleEncoderDescriptor;\n cameraArray: Float32Array = new Float32Array(16 * 2);\n\n constructor(\n public device: GPUDevice,\n colorFormat: GPUTextureFormat,\n depthFormat: GPUTextureFormat\n ) {\n this.renderBundleDescriptor = {\n colorFormats: [colorFormat],\n depthStencilFormat: depthFormat,\n };\n\n this.sampler = device.createSampler({\n label: 'MSDF text sampler',\n minFilter: 'linear',\n magFilter: 'linear',\n mipmapFilter: 'linear',\n maxAnisotropy: 16,\n });\n\n this.cameraUniformBuffer = device.createBuffer({\n label: 'MSDF camera uniform buffer',\n size: this.cameraArray.byteLength,\n usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.UNIFORM,\n });\n\n this.fontBindGroupLayout = device.createBindGroupLayout({\n label: 'MSDF font group layout',\n entries: [\n {\n binding: 0,\n visibility: GPUShaderStage.FRAGMENT,\n texture: {},\n },\n {\n binding: 1,\n visibility: GPUShaderStage.FRAGMENT,\n sampler: {},\n },\n {\n binding: 2,\n visibility: GPUShaderStage.VERTEX,\n buffer: { type: 'read-only-storage' },\n },\n ],\n });\n\n this.textBindGroupLayout = device.createBindGroupLayout({\n label: 'MSDF text group layout',\n entries: [\n {\n binding: 0,\n visibility: GPUShaderStage.VERTEX,\n buffer: {},\n },\n {\n binding: 1,\n visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,\n buffer: { type: 'read-only-storage' },\n },\n ],\n });\n\n const shaderModule = device.createShaderModule({\n label: 'MSDF text shader',\n code: msdfTextWGSL,\n });\n\n this.pipelinePromise = device.createRenderPipelineAsync({\n label: `msdf text pipeline`,\n layout: device.createPipelineLayout({\n bindGroupLayouts: [this.fontBindGroupLayout, this.textBindGroupLayout],\n }),\n vertex: {\n module: shaderModule,\n entryPoint: 'vertexMain',\n },\n fragment: {\n module: shaderModule,\n entryPoint: 'fragmentMain',\n targets: [\n {\n format: colorFormat,\n blend: {\n color: {\n srcFactor: 'src-alpha',\n dstFactor: 'one-minus-src-alpha',\n },\n alpha: {\n srcFactor: 'one',\n dstFactor: 'one',\n },\n },\n },\n ],\n },\n primitive: {\n topology: 'triangle-strip',\n stripIndexFormat: 'uint32',\n },\n depthStencil: {\n depthWriteEnabled: false,\n depthCompare: 'less',\n format: depthFormat,\n },\n });\n }\n\n async loadTexture(url: string) {\n const response = await fetch(url);\n const imageBitmap = await createImageBitmap(await response.blob());\n\n const texture = this.device.createTexture({\n label: `MSDF font texture ${url}`,\n size: [imageBitmap.width, imageBitmap.height, 1],\n format: 'rgba8unorm',\n usage:\n GPUTextureUsage.TEXTURE_BINDING |\n GPUTextureUsage.COPY_DST |\n GPUTextureUsage.RENDER_ATTACHMENT,\n });\n this.device.queue.copyExternalImageToTexture(\n { source: imageBitmap },\n { texture },\n [imageBitmap.width, imageBitmap.height]\n );\n return texture;\n }\n\n async createFont(fontJsonUrl: string): Promise {\n const response = await fetch(fontJsonUrl);\n const json = await response.json();\n\n const i = fontJsonUrl.lastIndexOf('/');\n const baseUrl = i !== -1 ? fontJsonUrl.substring(0, i + 1) : undefined;\n\n const pagePromises = [];\n for (const pageUrl of json.pages) {\n pagePromises.push(this.loadTexture(baseUrl + pageUrl));\n }\n\n const charCount = json.chars.length;\n const charsBuffer = this.device.createBuffer({\n label: 'MSDF character layout buffer',\n size: charCount * Float32Array.BYTES_PER_ELEMENT * 8,\n usage: GPUBufferUsage.STORAGE,\n mappedAtCreation: true,\n });\n\n const charsArray = new Float32Array(charsBuffer.getMappedRange());\n\n const u = 1 / json.common.scaleW;\n const v = 1 / json.common.scaleH;\n\n const chars: { [x: number]: MsdfChar } = {};\n\n let offset = 0;\n for (const [i, char] of json.chars.entries()) {\n chars[char.id] = char;\n chars[char.id].charIndex = i;\n charsArray[offset] = char.x * u; // texOffset.x\n charsArray[offset + 1] = char.y * v; // texOffset.y\n charsArray[offset + 2] = char.width * u; // texExtent.x\n charsArray[offset + 3] = char.height * v; // texExtent.y\n charsArray[offset + 4] = char.width; // size.x\n charsArray[offset + 5] = char.height; // size.y\n charsArray[offset + 6] = char.xoffset; // offset.x\n charsArray[offset + 7] = -char.yoffset; // offset.y\n offset += 8;\n }\n\n charsBuffer.unmap();\n\n const pageTextures = await Promise.all(pagePromises);\n\n const bindGroup = this.device.createBindGroup({\n label: 'msdf font bind group',\n layout: this.fontBindGroupLayout,\n entries: [\n {\n binding: 0,\n // TODO: Allow multi-page fonts\n resource: pageTextures[0].createView(),\n },\n {\n binding: 1,\n resource: this.sampler,\n },\n {\n binding: 2,\n resource: { buffer: charsBuffer },\n },\n ],\n });\n\n const kernings = new Map();\n\n if (json.kernings) {\n for (const kearning of json.kernings) {\n let charKerning = kernings.get(kearning.first);\n if (!charKerning) {\n charKerning = new Map();\n kernings.set(kearning.first, charKerning);\n }\n charKerning.set(kearning.second, kearning.amount);\n }\n }\n\n return new MsdfFont(\n await this.pipelinePromise,\n bindGroup,\n json.common.lineHeight,\n chars,\n kernings\n );\n }\n\n formatText(\n font: MsdfFont,\n text: string,\n options: MsdfTextFormattingOptions = {}\n ): MsdfText {\n const textBuffer = this.device.createBuffer({\n label: 'msdf text buffer',\n size: (text.length + 6) * Float32Array.BYTES_PER_ELEMENT * 4,\n usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,\n mappedAtCreation: true,\n });\n\n const textArray = new Float32Array(textBuffer.getMappedRange());\n let offset = 24; // Accounts for the values managed by MsdfText internally.\n\n let measurements: MsdfTextMeasurements;\n if (options.centered) {\n measurements = this.measureText(font, text);\n\n this.measureText(\n font,\n text,\n (textX: number, textY: number, line: number, char: MsdfChar) => {\n const lineOffset =\n measurements.width * -0.5 -\n (measurements.width - measurements.lineWidths[line]) * -0.5;\n\n textArray[offset] = textX + lineOffset;\n textArray[offset + 1] = textY + measurements.height * 0.5;\n textArray[offset + 2] = char.charIndex;\n offset += 4;\n }\n );\n } else {\n measurements = this.measureText(\n font,\n text,\n (textX: number, textY: number, line: number, char: MsdfChar) => {\n textArray[offset] = textX;\n textArray[offset + 1] = textY;\n textArray[offset + 2] = char.charIndex;\n offset += 4;\n }\n );\n }\n\n textBuffer.unmap();\n\n const bindGroup = this.device.createBindGroup({\n label: 'msdf text bind group',\n layout: this.textBindGroupLayout,\n entries: [\n {\n binding: 0,\n resource: { buffer: this.cameraUniformBuffer },\n },\n {\n binding: 1,\n resource: { buffer: textBuffer },\n },\n ],\n });\n\n const encoder = this.device.createRenderBundleEncoder(\n this.renderBundleDescriptor\n );\n encoder.setPipeline(font.pipeline);\n encoder.setBindGroup(0, font.bindGroup);\n encoder.setBindGroup(1, bindGroup);\n encoder.draw(4, measurements.printedCharCount);\n const renderBundle = encoder.finish();\n\n const msdfText = new MsdfText(\n this.device,\n renderBundle,\n measurements,\n font,\n textBuffer\n );\n if (options.pixelScale !== undefined) {\n msdfText.setPixelScale(options.pixelScale);\n }\n\n if (options.color !== undefined) {\n msdfText.setColor(...options.color);\n }\n\n return msdfText;\n }\n\n measureText(\n font: MsdfFont,\n text: string,\n charCallback?: (x: number, y: number, line: number, char: MsdfChar) => void\n ): MsdfTextMeasurements {\n let maxWidth = 0;\n const lineWidths: number[] = [];\n\n let textOffsetX = 0;\n let textOffsetY = 0;\n let line = 0;\n let printedCharCount = 0;\n let nextCharCode = text.charCodeAt(0);\n for (let i = 0; i < text.length; ++i) {\n const charCode = nextCharCode;\n nextCharCode = i < text.length - 1 ? text.charCodeAt(i + 1) : -1;\n\n switch (charCode) {\n case 10: // Newline\n lineWidths.push(textOffsetX);\n line++;\n maxWidth = Math.max(maxWidth, textOffsetX);\n textOffsetX = 0;\n textOffsetY -= font.lineHeight;\n case 13: // CR\n break;\n case 32: // Space\n // For spaces, advance the offset without actually adding a character.\n textOffsetX += font.getXAdvance(charCode);\n break;\n default: {\n if (charCallback) {\n charCallback(\n textOffsetX,\n textOffsetY,\n line,\n font.getChar(charCode)\n );\n }\n textOffsetX += font.getXAdvance(charCode, nextCharCode);\n printedCharCount++;\n }\n }\n }\n\n lineWidths.push(textOffsetX);\n maxWidth = Math.max(maxWidth, textOffsetX);\n\n return {\n width: maxWidth,\n height: lineWidths.length * font.lineHeight,\n lineWidths,\n printedCharCount,\n };\n }\n\n updateCamera(projection: Mat4, view: Mat4) {\n this.cameraArray.set(projection, 0);\n this.cameraArray.set(view, 16);\n this.device.queue.writeBuffer(\n this.cameraUniformBuffer,\n 0,\n this.cameraArray\n );\n }\n\n render(renderPass: GPURenderPassEncoder, ...text: MsdfText[]) {\n const renderBundles = text.map((t) => t.getRenderBundle());\n renderPass.executeBundles(renderBundles);\n }\n}\n","import { mat4, vec3 } from 'wgpu-matrix';\n\nimport {\n cubeVertexArray,\n cubeVertexSize,\n cubeUVOffset,\n cubePositionOffset,\n cubeVertexCount,\n} from '../../meshes/cube';\nimport { MsdfTextRenderer } from './msdfText';\n\nimport basicVertWGSL from '../../shaders/basic.vert.wgsl';\nimport vertexPositionColorWGSL from '../../shaders/vertexPositionColor.frag.wgsl';\n\nconst canvas = document.querySelector('canvas') as HTMLCanvasElement;\nconst adapter = await navigator.gpu.requestAdapter();\nconst device = await adapter.requestDevice();\n\nconst context = canvas.getContext('webgpu') as GPUCanvasContext;\n\nconst devicePixelRatio = window.devicePixelRatio || 1;\ncanvas.width = canvas.clientWidth * devicePixelRatio;\ncanvas.height = canvas.clientHeight * devicePixelRatio;\nconst presentationFormat = navigator.gpu.getPreferredCanvasFormat();\nconst depthFormat = 'depth24plus';\n\ncontext.configure({\n device,\n format: presentationFormat,\n alphaMode: 'premultiplied',\n});\n\nconst textRenderer = new MsdfTextRenderer(\n device,\n presentationFormat,\n depthFormat\n);\nconst font = await textRenderer.createFont(\n new URL(\n '../../assets/font/ya-hei-ascii-msdf.json',\n import.meta.url\n ).toString()\n);\n\nfunction getTextTransform(\n position: [number, number, number],\n rotation?: [number, number, number]\n) {\n const textTransform = mat4.create();\n mat4.identity(textTransform);\n mat4.translate(textTransform, position, textTransform);\n if (rotation && rotation[0] != 0) {\n mat4.rotateX(textTransform, rotation[0], textTransform);\n }\n if (rotation && rotation[1] != 0) {\n mat4.rotateY(textTransform, rotation[1], textTransform);\n }\n if (rotation && rotation[2] != 0) {\n mat4.rotateZ(textTransform, rotation[2], textTransform);\n }\n return textTransform;\n}\n\nconst textTransforms = [\n getTextTransform([0, 0, 1.1]),\n getTextTransform([0, 0, -1.1], [0, Math.PI, 0]),\n getTextTransform([1.1, 0, 0], [0, Math.PI / 2, 0]),\n getTextTransform([-1.1, 0, 0], [0, -Math.PI / 2, 0]),\n getTextTransform([0, 1.1, 0], [-Math.PI / 2, 0, 0]),\n getTextTransform([0, -1.1, 0], [Math.PI / 2, 0, 0]),\n];\n\nconst titleText = textRenderer.formatText(font, `WebGPU`, {\n centered: true,\n pixelScale: 1 / 128,\n});\nconst largeText = textRenderer.formatText(\n font,\n `\nWebGPU exposes an API for performing operations, such as rendering\nand computation, on a Graphics Processing Unit.\n\nGraphics Processing Units, or GPUs for short, have been essential\nin enabling rich rendering and computational applications in personal\ncomputing. WebGPU is an API that exposes the capabilities of GPU\nhardware for the Web. The API is designed from the ground up to\nefficiently map to (post-2014) native GPU APIs. WebGPU is not related\nto WebGL and does not explicitly target OpenGL ES.\n\nWebGPU sees physical GPU hardware as GPUAdapters. It provides a\nconnection to an adapter via GPUDevice, which manages resources, and\nthe device’s GPUQueues, which execute commands. GPUDevice may have\nits own memory with high-speed access to the processing units.\nGPUBuffer and GPUTexture are the physical resources backed by GPU\nmemory. GPUCommandBuffer and GPURenderBundle are containers for\nuser-recorded commands. GPUShaderModule contains shader code. The\nother resources, such as GPUSampler or GPUBindGroup, configure the\nway physical resources are used by the GPU.\n\nGPUs execute commands encoded in GPUCommandBuffers by feeding data\nthrough a pipeline, which is a mix of fixed-function and programmable\nstages. Programmable stages execute shaders, which are special\nprograms designed to run on GPU hardware. Most of the state of a\npipeline is defined by a GPURenderPipeline or a GPUComputePipeline\nobject. The state not included in these pipeline objects is set\nduring encoding with commands, such as beginRenderPass() or\nsetBlendConstant().`,\n { pixelScale: 1 / 256 }\n);\n\nconst text = [\n textRenderer.formatText(font, 'Front', {\n centered: true,\n pixelScale: 1 / 128,\n color: [1, 0, 0, 1],\n }),\n textRenderer.formatText(font, 'Back', {\n centered: true,\n pixelScale: 1 / 128,\n color: [0, 1, 1, 1],\n }),\n textRenderer.formatText(font, 'Right', {\n centered: true,\n pixelScale: 1 / 128,\n color: [0, 1, 0, 1],\n }),\n textRenderer.formatText(font, 'Left', {\n centered: true,\n pixelScale: 1 / 128,\n color: [1, 0, 1, 1],\n }),\n textRenderer.formatText(font, 'Top', {\n centered: true,\n pixelScale: 1 / 128,\n color: [0, 0, 1, 1],\n }),\n textRenderer.formatText(font, 'Bottom', {\n centered: true,\n pixelScale: 1 / 128,\n color: [1, 1, 0, 1],\n }),\n\n titleText,\n largeText,\n];\n\n// Create a vertex buffer from the cube data.\nconst verticesBuffer = device.createBuffer({\n size: cubeVertexArray.byteLength,\n usage: GPUBufferUsage.VERTEX,\n mappedAtCreation: true,\n});\nnew Float32Array(verticesBuffer.getMappedRange()).set(cubeVertexArray);\nverticesBuffer.unmap();\n\nconst pipeline = device.createRenderPipeline({\n layout: 'auto',\n vertex: {\n module: device.createShaderModule({\n code: basicVertWGSL,\n }),\n buffers: [\n {\n arrayStride: cubeVertexSize,\n attributes: [\n {\n // position\n shaderLocation: 0,\n offset: cubePositionOffset,\n format: 'float32x4',\n },\n {\n // uv\n shaderLocation: 1,\n offset: cubeUVOffset,\n format: 'float32x2',\n },\n ],\n },\n ],\n },\n fragment: {\n module: device.createShaderModule({\n code: vertexPositionColorWGSL,\n }),\n targets: [\n {\n format: presentationFormat,\n },\n ],\n },\n primitive: {\n // Backface culling since the cube is solid piece of geometry.\n // Faces pointing away from the camera will be occluded by faces\n // pointing toward the camera.\n cullMode: 'back',\n },\n\n // Enable depth testing so that the fragment closest to the camera\n // is rendered in front.\n depthStencil: {\n depthWriteEnabled: true,\n depthCompare: 'less',\n format: depthFormat,\n },\n});\n\nconst depthTexture = device.createTexture({\n size: [canvas.width, canvas.height],\n format: depthFormat,\n usage: GPUTextureUsage.RENDER_ATTACHMENT,\n});\n\nconst uniformBufferSize = 4 * 16; // 4x4 matrix\nconst uniformBuffer = device.createBuffer({\n size: uniformBufferSize,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n});\n\nconst uniformBindGroup = device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [\n {\n binding: 0,\n resource: {\n buffer: uniformBuffer,\n },\n },\n ],\n});\n\nconst renderPassDescriptor: GPURenderPassDescriptor = {\n colorAttachments: [\n {\n view: undefined, // Assigned later\n\n clearValue: [0, 0, 0, 1],\n loadOp: 'clear',\n storeOp: 'store',\n },\n ],\n depthStencilAttachment: {\n view: depthTexture.createView(),\n\n depthClearValue: 1.0,\n depthLoadOp: 'clear',\n depthStoreOp: 'store',\n },\n};\n\nconst aspect = canvas.width / canvas.height;\nconst projectionMatrix = mat4.perspective((2 * Math.PI) / 5, aspect, 1, 100.0);\nconst modelViewProjectionMatrix = mat4.create();\n\nconst start = Date.now();\nfunction getTransformationMatrix() {\n const now = Date.now() / 5000;\n const viewMatrix = mat4.identity();\n mat4.translate(viewMatrix, vec3.fromValues(0, 0, -5), viewMatrix);\n\n const modelMatrix = mat4.identity();\n mat4.translate(modelMatrix, vec3.fromValues(0, 2, -3), modelMatrix);\n mat4.rotate(\n modelMatrix,\n vec3.fromValues(Math.sin(now), Math.cos(now), 0),\n 1,\n modelMatrix\n );\n\n // Update the matrix for the cube\n mat4.multiply(projectionMatrix, viewMatrix, modelViewProjectionMatrix);\n mat4.multiply(\n modelViewProjectionMatrix,\n modelMatrix,\n modelViewProjectionMatrix\n );\n\n // Update the projection and view matrices for the text\n textRenderer.updateCamera(projectionMatrix, viewMatrix);\n\n // Update the transform of all the text surrounding the cube\n const textMatrix = mat4.create();\n for (const [index, transform] of textTransforms.entries()) {\n mat4.multiply(modelMatrix, transform, textMatrix);\n text[index].setTransform(textMatrix);\n }\n\n // Update the transform of the larger block of text\n const crawl = ((Date.now() - start) / 2500) % 14;\n mat4.identity(textMatrix);\n mat4.rotateX(textMatrix, -Math.PI / 8, textMatrix);\n mat4.translate(textMatrix, [0, crawl - 3, 0], textMatrix);\n titleText.setTransform(textMatrix);\n mat4.translate(textMatrix, [-3, -0.1, 0], textMatrix);\n largeText.setTransform(textMatrix);\n\n return modelViewProjectionMatrix as Float32Array;\n}\n\nfunction frame() {\n const transformationMatrix = getTransformationMatrix();\n device.queue.writeBuffer(\n uniformBuffer,\n 0,\n transformationMatrix.buffer,\n transformationMatrix.byteOffset,\n transformationMatrix.byteLength\n );\n renderPassDescriptor.colorAttachments[0].view = context\n .getCurrentTexture()\n .createView();\n\n const commandEncoder = device.createCommandEncoder();\n const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);\n passEncoder.setPipeline(pipeline);\n passEncoder.setBindGroup(0, uniformBindGroup);\n passEncoder.setVertexBuffer(0, verticesBuffer);\n passEncoder.draw(cubeVertexCount, 1, 0, 0);\n\n textRenderer.render(passEncoder, ...text);\n\n passEncoder.end();\n device.queue.submit([commandEncoder.finish()]);\n\n requestAnimationFrame(frame);\n}\nrequestAnimationFrame(frame);\n"],"names":["mat4","vec3"],"mappings":"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O;AACvC,QAAQ,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO;AACvC,QAAQ,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO;AACvC,QAAQ,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO;AACvC,QAAQ,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO;AACvC,QAAQ,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO;AACvC,QAAQ,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO;AACvC,QAAQ,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO;AACvC,QAAQ,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO;AACzC,QAAQ,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO;AACzC,QAAQ,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO;AACzC,QAAQ,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO;AACzC,QAAQ,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO;AACzC,QAAQ,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC;AAC1C,CAAC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,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AACjB,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AACjB,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AACjB,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AACjB,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AACjB,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AACjB,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AACjB,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AACjB,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AACjB,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AACjB,IAAI,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC;AAClB,IAAI,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC;AAClB,IAAI,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC;AAClB,IAAI,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC;AAClB,IAAI,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC;AAClB,IAAI,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC;AAClB,IAAI,OAAO,GAAG,CAAC;AACf,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE;AAC3B,IAAI,GAAG,GAAG,GAAG,IAAI,IAAI,OAAO,CAAC,EAAE,CAAC,CAAC;AACjC,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3B,IAAI,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3B,IAAI,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3B,IAAI,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3B,IAAI,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3B,IAAI,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3B,IAAI,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3B,IAAI,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3B,IAAI,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3B,IAAI,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3B,IAAI,MAAM,KAAK,GAAG,GAAG,GAAG,GAAG,CAAC;AAC5B,IAAI,MAAM,KAAK,GAAG,GAAG,GAAG,GAAG,CAAC;AAC5B,IAAI,MAAM,KAAK,GAAG,GAAG,GAAG,GAAG,CAAC;AAC5B,IAAI,MAAM,KAAK,GAAG,GAAG,GAAG,GAAG,CAAC;AAC5B,IAAI,MAAM,KAAK,GAAG,GAAG,GAAG,GAAG,CAAC;AAC5B,IAAI,MAAM,KAAK,GAAG,GAAG,GAAG,GAAG,CAAC;AAC5B,IAAI,MAAM,KAAK,GAAG,GAAG,GAAG,GAAG,CAAC;AAC5B,IAAI,MAAM,KAAK,GAAG,GAAG,GAAG,GAAG,CAAC;AAC5B,IAAI,MAAM,KAAK,GAAG,GAAG,GAAG,GAAG,CAAC;AAC5B,IAAI,MAAM,KAAK,GAAG,GAAG,GAAG,GAAG,CAAC;AAC5B,IAAI,MAAM,KAAK,GAAG,GAAG,GAAG,GAAG,CAAC;AAC5B,IAAI,MAAM,KAAK,GAAG,GAAG,GAAG,GAAG,C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C,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,IAAI,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3B,IAAI,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3B,IAAI,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3B,IAAI,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3B,IAAI,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3B,IAAI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AAC,CAAC,CAAC;AACrB,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACzB,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACzB,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACzB,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACzB,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACzB,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACzB,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACzB,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACzB,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;AAC1B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;AAC1B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;AAC1B,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;AAC1B,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3D,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3D,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3D,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3D,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3D,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3D,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3D,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3D,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3D,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3D,IAAI,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC5D,IAAI,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC5D,IAAI,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC5D,IAAI,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC5D,IAAI,GAAG,CAAC,EAAE,CAAC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GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACrB,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACrB,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACrB,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;AACtB,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;AACtB,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC/C,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC/C,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC/C,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC/C,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC/C,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC/C,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC/C,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC/C,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC/C,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC/C,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AAC,EAAE,CAAC,EAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;IAChC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;IAChC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAEhC,IAAA,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAEhC,IAAA,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAEhC,IAAA,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;IAChC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAEhC,IAAA,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAEhC,IAAA,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;IAChC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC;AAChC,IAAA,CAAC,CAAC,EAAE,CAAC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","x_google_ignoreList":[0]} \ No newline at end of file diff --git a/sample/textRenderingMsdf/main.ts b/sample/textRenderingMsdf/main.ts new file mode 100644 index 00000000..e83e2116 --- /dev/null +++ b/sample/textRenderingMsdf/main.ts @@ -0,0 +1,327 @@ +import { mat4, vec3 } from 'wgpu-matrix'; + +import { + cubeVertexArray, + cubeVertexSize, + cubeUVOffset, + cubePositionOffset, + cubeVertexCount, +} from '../../meshes/cube'; +import { MsdfTextRenderer } from './msdfText'; + +import basicVertWGSL from '../../shaders/basic.vert.wgsl'; +import vertexPositionColorWGSL from '../../shaders/vertexPositionColor.frag.wgsl'; + +const canvas = document.querySelector('canvas') as HTMLCanvasElement; +const adapter = await navigator.gpu.requestAdapter(); +const device = await adapter.requestDevice(); + +const context = canvas.getContext('webgpu') as GPUCanvasContext; + +const devicePixelRatio = window.devicePixelRatio || 1; +canvas.width = canvas.clientWidth * devicePixelRatio; +canvas.height = canvas.clientHeight * devicePixelRatio; +const presentationFormat = navigator.gpu.getPreferredCanvasFormat(); +const depthFormat = 'depth24plus'; + +context.configure({ + device, + format: presentationFormat, + alphaMode: 'premultiplied', +}); + +const textRenderer = new MsdfTextRenderer( + device, + presentationFormat, + depthFormat +); +const font = await textRenderer.createFont( + new URL( + '../../assets/font/ya-hei-ascii-msdf.json', + import.meta.url + ).toString() +); + +function getTextTransform( + position: [number, number, number], + rotation?: [number, number, number] +) { + const textTransform = mat4.create(); + mat4.identity(textTransform); + mat4.translate(textTransform, position, textTransform); + if (rotation && rotation[0] != 0) { + mat4.rotateX(textTransform, rotation[0], textTransform); + } + if (rotation && rotation[1] != 0) { + mat4.rotateY(textTransform, rotation[1], textTransform); + } + if (rotation && rotation[2] != 0) { + mat4.rotateZ(textTransform, rotation[2], textTransform); + } + return textTransform; +} + +const textTransforms = [ + getTextTransform([0, 0, 1.1]), + getTextTransform([0, 0, -1.1], [0, Math.PI, 0]), + getTextTransform([1.1, 0, 0], [0, Math.PI / 2, 0]), + getTextTransform([-1.1, 0, 0], [0, -Math.PI / 2, 0]), + getTextTransform([0, 1.1, 0], [-Math.PI / 2, 0, 0]), + getTextTransform([0, -1.1, 0], [Math.PI / 2, 0, 0]), +]; + +const titleText = textRenderer.formatText(font, `WebGPU`, { + centered: true, + pixelScale: 1 / 128, +}); +const largeText = textRenderer.formatText( + font, + ` +WebGPU exposes an API for performing operations, such as rendering +and computation, on a Graphics Processing Unit. + +Graphics Processing Units, or GPUs for short, have been essential +in enabling rich rendering and computational applications in personal +computing. WebGPU is an API that exposes the capabilities of GPU +hardware for the Web. The API is designed from the ground up to +efficiently map to (post-2014) native GPU APIs. WebGPU is not related +to WebGL and does not explicitly target OpenGL ES. + +WebGPU sees physical GPU hardware as GPUAdapters. It provides a +connection to an adapter via GPUDevice, which manages resources, and +the device’s GPUQueues, which execute commands. GPUDevice may have +its own memory with high-speed access to the processing units. +GPUBuffer and GPUTexture are the physical resources backed by GPU +memory. GPUCommandBuffer and GPURenderBundle are containers for +user-recorded commands. GPUShaderModule contains shader code. The +other resources, such as GPUSampler or GPUBindGroup, configure the +way physical resources are used by the GPU. + +GPUs execute commands encoded in GPUCommandBuffers by feeding data +through a pipeline, which is a mix of fixed-function and programmable +stages. Programmable stages execute shaders, which are special +programs designed to run on GPU hardware. Most of the state of a +pipeline is defined by a GPURenderPipeline or a GPUComputePipeline +object. The state not included in these pipeline objects is set +during encoding with commands, such as beginRenderPass() or +setBlendConstant().`, + { pixelScale: 1 / 256 } +); + +const text = [ + textRenderer.formatText(font, 'Front', { + centered: true, + pixelScale: 1 / 128, + color: [1, 0, 0, 1], + }), + textRenderer.formatText(font, 'Back', { + centered: true, + pixelScale: 1 / 128, + color: [0, 1, 1, 1], + }), + textRenderer.formatText(font, 'Right', { + centered: true, + pixelScale: 1 / 128, + color: [0, 1, 0, 1], + }), + textRenderer.formatText(font, 'Left', { + centered: true, + pixelScale: 1 / 128, + color: [1, 0, 1, 1], + }), + textRenderer.formatText(font, 'Top', { + centered: true, + pixelScale: 1 / 128, + color: [0, 0, 1, 1], + }), + textRenderer.formatText(font, 'Bottom', { + centered: true, + pixelScale: 1 / 128, + color: [1, 1, 0, 1], + }), + + titleText, + largeText, +]; + +// Create a vertex buffer from the cube data. +const verticesBuffer = device.createBuffer({ + size: cubeVertexArray.byteLength, + usage: GPUBufferUsage.VERTEX, + mappedAtCreation: true, +}); +new Float32Array(verticesBuffer.getMappedRange()).set(cubeVertexArray); +verticesBuffer.unmap(); + +const pipeline = device.createRenderPipeline({ + layout: 'auto', + vertex: { + module: device.createShaderModule({ + code: basicVertWGSL, + }), + buffers: [ + { + arrayStride: cubeVertexSize, + attributes: [ + { + // position + shaderLocation: 0, + offset: cubePositionOffset, + format: 'float32x4', + }, + { + // uv + shaderLocation: 1, + offset: cubeUVOffset, + format: 'float32x2', + }, + ], + }, + ], + }, + fragment: { + module: device.createShaderModule({ + code: vertexPositionColorWGSL, + }), + targets: [ + { + format: presentationFormat, + }, + ], + }, + primitive: { + // Backface culling since the cube is solid piece of geometry. + // Faces pointing away from the camera will be occluded by faces + // pointing toward the camera. + cullMode: 'back', + }, + + // Enable depth testing so that the fragment closest to the camera + // is rendered in front. + depthStencil: { + depthWriteEnabled: true, + depthCompare: 'less', + format: depthFormat, + }, +}); + +const depthTexture = device.createTexture({ + size: [canvas.width, canvas.height], + format: depthFormat, + usage: GPUTextureUsage.RENDER_ATTACHMENT, +}); + +const uniformBufferSize = 4 * 16; // 4x4 matrix +const uniformBuffer = device.createBuffer({ + size: uniformBufferSize, + usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, +}); + +const uniformBindGroup = device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [ + { + binding: 0, + resource: { + buffer: uniformBuffer, + }, + }, + ], +}); + +const renderPassDescriptor: GPURenderPassDescriptor = { + colorAttachments: [ + { + view: undefined, // Assigned later + + clearValue: [0, 0, 0, 1], + loadOp: 'clear', + storeOp: 'store', + }, + ], + depthStencilAttachment: { + view: depthTexture.createView(), + + depthClearValue: 1.0, + depthLoadOp: 'clear', + depthStoreOp: 'store', + }, +}; + +const aspect = canvas.width / canvas.height; +const projectionMatrix = mat4.perspective((2 * Math.PI) / 5, aspect, 1, 100.0); +const modelViewProjectionMatrix = mat4.create(); + +const start = Date.now(); +function getTransformationMatrix() { + const now = Date.now() / 5000; + const viewMatrix = mat4.identity(); + mat4.translate(viewMatrix, vec3.fromValues(0, 0, -5), viewMatrix); + + const modelMatrix = mat4.identity(); + mat4.translate(modelMatrix, vec3.fromValues(0, 2, -3), modelMatrix); + mat4.rotate( + modelMatrix, + vec3.fromValues(Math.sin(now), Math.cos(now), 0), + 1, + modelMatrix + ); + + // Update the matrix for the cube + mat4.multiply(projectionMatrix, viewMatrix, modelViewProjectionMatrix); + mat4.multiply( + modelViewProjectionMatrix, + modelMatrix, + modelViewProjectionMatrix + ); + + // Update the projection and view matrices for the text + textRenderer.updateCamera(projectionMatrix, viewMatrix); + + // Update the transform of all the text surrounding the cube + const textMatrix = mat4.create(); + for (const [index, transform] of textTransforms.entries()) { + mat4.multiply(modelMatrix, transform, textMatrix); + text[index].setTransform(textMatrix); + } + + // Update the transform of the larger block of text + const crawl = ((Date.now() - start) / 2500) % 14; + mat4.identity(textMatrix); + mat4.rotateX(textMatrix, -Math.PI / 8, textMatrix); + mat4.translate(textMatrix, [0, crawl - 3, 0], textMatrix); + titleText.setTransform(textMatrix); + mat4.translate(textMatrix, [-3, -0.1, 0], textMatrix); + largeText.setTransform(textMatrix); + + return modelViewProjectionMatrix as Float32Array; +} + +function frame() { + const transformationMatrix = getTransformationMatrix(); + device.queue.writeBuffer( + uniformBuffer, + 0, + transformationMatrix.buffer, + transformationMatrix.byteOffset, + transformationMatrix.byteLength + ); + renderPassDescriptor.colorAttachments[0].view = context + .getCurrentTexture() + .createView(); + + const commandEncoder = device.createCommandEncoder(); + const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); + passEncoder.setPipeline(pipeline); + passEncoder.setBindGroup(0, uniformBindGroup); + passEncoder.setVertexBuffer(0, verticesBuffer); + passEncoder.draw(cubeVertexCount, 1, 0, 0); + + textRenderer.render(passEncoder, ...text); + + passEncoder.end(); + device.queue.submit([commandEncoder.finish()]); + + requestAnimationFrame(frame); +} +requestAnimationFrame(frame); diff --git a/sample/textRenderingMsdf/meta.ts b/sample/textRenderingMsdf/meta.ts new file mode 100644 index 00000000..d05a5590 --- /dev/null +++ b/sample/textRenderingMsdf/meta.ts @@ -0,0 +1,18 @@ +export default { + name: 'Text Rendering - MSDF', + description: `This example uses multichannel signed distance fields (MSDF) to render text. MSDF +fonts are more complex to implement than using Canvas 2D to generate text, but the resulting +text looks smoother while using less memory than the Canvas 2D approach, especially at high +zoom levels. They can be used to render larger amounts of text efficiently. + +The font texture is generated using [Don McCurdy's MSDF font generation tool](https://msdf-bmfont.donmccurdy.com/)`, + filename: __DIRNAME__, + sources: [ + { path: 'main.ts' }, + { path: 'msdfText.ts' }, + { path: 'msdfText.wgsl' }, + { path: '../../shaders/basic.vert.wgsl' }, + { path: '../../shaders/vertexPositionColor.frag.wgsl' }, + { path: '../../meshes/cube.ts' }, + ], +}; diff --git a/sample/textRenderingMsdf/msdfText.ts b/sample/textRenderingMsdf/msdfText.ts new file mode 100644 index 00000000..065213a7 --- /dev/null +++ b/sample/textRenderingMsdf/msdfText.ts @@ -0,0 +1,513 @@ +import { mat4 } from 'wgpu-matrix'; + +import msdfTextWGSL from './msdfText.wgsl'; + +type Mat4 = mat4.default; + +// The kerning map stores a spare map of character ID pairs with an associated +// X offset that should be applied to the character spacing when the second +// character ID is rendered after the first. +type KerningMap = Map>; + +interface MsdfChar { + id: number; + index: number; + char: string; + width: number; + height: number; + xoffset: number; + yofsset: number; + xadvance: number; + chnl: number; + x: number; + y: number; + page: number; + charIndex: number; +} + +export class MsdfFont { + charCount: number; + defaultChar: MsdfChar; + constructor( + public pipeline: GPURenderPipeline, + public bindGroup: GPUBindGroup, + public lineHeight: number, + public chars: { [x: number]: MsdfChar }, + public kernings: KerningMap + ) { + const charArray = Object.values(chars); + this.charCount = charArray.length; + this.defaultChar = charArray[0]; + } + + getChar(charCode: number): MsdfChar { + let char = this.chars[charCode]; + if (!char) { + char = this.defaultChar; + } + return char; + } + + // Gets the distance in pixels a line should advance for a given character code. If the upcoming + // character code is given any kerning between the two characters will be taken into account. + getXAdvance(charCode: number, nextCharCode: number = -1): number { + const char = this.getChar(charCode); + if (nextCharCode >= 0) { + const kerning = this.kernings.get(charCode); + if (kerning) { + return char.xadvance + (kerning.get(nextCharCode) ?? 0); + } + } + return char.xadvance; + } +} + +export interface MsdfTextMeasurements { + width: number; + height: number; + lineWidths: number[]; + printedCharCount: number; +} + +export class MsdfText { + private bufferArray = new Float32Array(24); + private bufferArrayDirty = true; + + constructor( + public device: GPUDevice, + private renderBundle: GPURenderBundle, + public measurements: MsdfTextMeasurements, + public font: MsdfFont, + public textBuffer: GPUBuffer + ) { + mat4.identity(this.bufferArray); + this.setColor(1, 1, 1, 1); + this.setPixelScale(1 / 512); + this.bufferArrayDirty = true; + } + + getRenderBundle() { + if (this.bufferArrayDirty) { + this.bufferArrayDirty = false; + this.device.queue.writeBuffer( + this.textBuffer, + 0, + this.bufferArray, + 0, + this.bufferArray.length + ); + } + return this.renderBundle; + } + + setTransform(matrix: Mat4) { + mat4.copy(matrix, this.bufferArray); + this.bufferArrayDirty = true; + } + + setColor(r: number, g: number, b: number, a: number = 1.0) { + this.bufferArray[16] = r; + this.bufferArray[17] = g; + this.bufferArray[18] = b; + this.bufferArray[19] = a; + this.bufferArrayDirty = true; + } + + setPixelScale(pixelScale: number) { + this.bufferArray[20] = pixelScale; + this.bufferArrayDirty = true; + } +} + +export interface MsdfTextFormattingOptions { + centered?: boolean; + pixelScale?: number; + color?: [number, number, number, number]; +} + +export class MsdfTextRenderer { + fontBindGroupLayout: GPUBindGroupLayout; + textBindGroupLayout: GPUBindGroupLayout; + pipelinePromise: Promise; + sampler: GPUSampler; + cameraUniformBuffer: GPUBuffer; + + renderBundleDescriptor: GPURenderBundleEncoderDescriptor; + cameraArray: Float32Array = new Float32Array(16 * 2); + + constructor( + public device: GPUDevice, + colorFormat: GPUTextureFormat, + depthFormat: GPUTextureFormat + ) { + this.renderBundleDescriptor = { + colorFormats: [colorFormat], + depthStencilFormat: depthFormat, + }; + + this.sampler = device.createSampler({ + label: 'MSDF text sampler', + minFilter: 'linear', + magFilter: 'linear', + mipmapFilter: 'linear', + maxAnisotropy: 16, + }); + + this.cameraUniformBuffer = device.createBuffer({ + label: 'MSDF camera uniform buffer', + size: this.cameraArray.byteLength, + usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.UNIFORM, + }); + + this.fontBindGroupLayout = device.createBindGroupLayout({ + label: 'MSDF font group layout', + entries: [ + { + binding: 0, + visibility: GPUShaderStage.FRAGMENT, + texture: {}, + }, + { + binding: 1, + visibility: GPUShaderStage.FRAGMENT, + sampler: {}, + }, + { + binding: 2, + visibility: GPUShaderStage.VERTEX, + buffer: { type: 'read-only-storage' }, + }, + ], + }); + + this.textBindGroupLayout = device.createBindGroupLayout({ + label: 'MSDF text group layout', + entries: [ + { + binding: 0, + visibility: GPUShaderStage.VERTEX, + buffer: {}, + }, + { + binding: 1, + visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, + buffer: { type: 'read-only-storage' }, + }, + ], + }); + + const shaderModule = device.createShaderModule({ + label: 'MSDF text shader', + code: msdfTextWGSL, + }); + + this.pipelinePromise = device.createRenderPipelineAsync({ + label: `msdf text pipeline`, + layout: device.createPipelineLayout({ + bindGroupLayouts: [this.fontBindGroupLayout, this.textBindGroupLayout], + }), + vertex: { + module: shaderModule, + entryPoint: 'vertexMain', + }, + fragment: { + module: shaderModule, + entryPoint: 'fragmentMain', + targets: [ + { + format: colorFormat, + blend: { + color: { + srcFactor: 'src-alpha', + dstFactor: 'one-minus-src-alpha', + }, + alpha: { + srcFactor: 'one', + dstFactor: 'one', + }, + }, + }, + ], + }, + primitive: { + topology: 'triangle-strip', + stripIndexFormat: 'uint32', + }, + depthStencil: { + depthWriteEnabled: false, + depthCompare: 'less', + format: depthFormat, + }, + }); + } + + async loadTexture(url: string) { + const response = await fetch(url); + const imageBitmap = await createImageBitmap(await response.blob()); + + const texture = this.device.createTexture({ + label: `MSDF font texture ${url}`, + size: [imageBitmap.width, imageBitmap.height, 1], + format: 'rgba8unorm', + usage: + GPUTextureUsage.TEXTURE_BINDING | + GPUTextureUsage.COPY_DST | + GPUTextureUsage.RENDER_ATTACHMENT, + }); + this.device.queue.copyExternalImageToTexture( + { source: imageBitmap }, + { texture }, + [imageBitmap.width, imageBitmap.height] + ); + return texture; + } + + async createFont(fontJsonUrl: string): Promise { + const response = await fetch(fontJsonUrl); + const json = await response.json(); + + const i = fontJsonUrl.lastIndexOf('/'); + const baseUrl = i !== -1 ? fontJsonUrl.substring(0, i + 1) : undefined; + + const pagePromises = []; + for (const pageUrl of json.pages) { + pagePromises.push(this.loadTexture(baseUrl + pageUrl)); + } + + const charCount = json.chars.length; + const charsBuffer = this.device.createBuffer({ + label: 'MSDF character layout buffer', + size: charCount * Float32Array.BYTES_PER_ELEMENT * 8, + usage: GPUBufferUsage.STORAGE, + mappedAtCreation: true, + }); + + const charsArray = new Float32Array(charsBuffer.getMappedRange()); + + const u = 1 / json.common.scaleW; + const v = 1 / json.common.scaleH; + + const chars: { [x: number]: MsdfChar } = {}; + + let offset = 0; + for (const [i, char] of json.chars.entries()) { + chars[char.id] = char; + chars[char.id].charIndex = i; + charsArray[offset] = char.x * u; // texOffset.x + charsArray[offset + 1] = char.y * v; // texOffset.y + charsArray[offset + 2] = char.width * u; // texExtent.x + charsArray[offset + 3] = char.height * v; // texExtent.y + charsArray[offset + 4] = char.width; // size.x + charsArray[offset + 5] = char.height; // size.y + charsArray[offset + 6] = char.xoffset; // offset.x + charsArray[offset + 7] = -char.yoffset; // offset.y + offset += 8; + } + + charsBuffer.unmap(); + + const pageTextures = await Promise.all(pagePromises); + + const bindGroup = this.device.createBindGroup({ + label: 'msdf font bind group', + layout: this.fontBindGroupLayout, + entries: [ + { + binding: 0, + // TODO: Allow multi-page fonts + resource: pageTextures[0].createView(), + }, + { + binding: 1, + resource: this.sampler, + }, + { + binding: 2, + resource: { buffer: charsBuffer }, + }, + ], + }); + + const kernings = new Map(); + + if (json.kernings) { + for (const kearning of json.kernings) { + let charKerning = kernings.get(kearning.first); + if (!charKerning) { + charKerning = new Map(); + kernings.set(kearning.first, charKerning); + } + charKerning.set(kearning.second, kearning.amount); + } + } + + return new MsdfFont( + await this.pipelinePromise, + bindGroup, + json.common.lineHeight, + chars, + kernings + ); + } + + formatText( + font: MsdfFont, + text: string, + options: MsdfTextFormattingOptions = {} + ): MsdfText { + const textBuffer = this.device.createBuffer({ + label: 'msdf text buffer', + size: (text.length + 6) * Float32Array.BYTES_PER_ELEMENT * 4, + usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST, + mappedAtCreation: true, + }); + + const textArray = new Float32Array(textBuffer.getMappedRange()); + let offset = 24; // Accounts for the values managed by MsdfText internally. + + let measurements: MsdfTextMeasurements; + if (options.centered) { + measurements = this.measureText(font, text); + + this.measureText( + font, + text, + (textX: number, textY: number, line: number, char: MsdfChar) => { + const lineOffset = + measurements.width * -0.5 - + (measurements.width - measurements.lineWidths[line]) * -0.5; + + textArray[offset] = textX + lineOffset; + textArray[offset + 1] = textY + measurements.height * 0.5; + textArray[offset + 2] = char.charIndex; + offset += 4; + } + ); + } else { + measurements = this.measureText( + font, + text, + (textX: number, textY: number, line: number, char: MsdfChar) => { + textArray[offset] = textX; + textArray[offset + 1] = textY; + textArray[offset + 2] = char.charIndex; + offset += 4; + } + ); + } + + textBuffer.unmap(); + + const bindGroup = this.device.createBindGroup({ + label: 'msdf text bind group', + layout: this.textBindGroupLayout, + entries: [ + { + binding: 0, + resource: { buffer: this.cameraUniformBuffer }, + }, + { + binding: 1, + resource: { buffer: textBuffer }, + }, + ], + }); + + const encoder = this.device.createRenderBundleEncoder( + this.renderBundleDescriptor + ); + encoder.setPipeline(font.pipeline); + encoder.setBindGroup(0, font.bindGroup); + encoder.setBindGroup(1, bindGroup); + encoder.draw(4, measurements.printedCharCount); + const renderBundle = encoder.finish(); + + const msdfText = new MsdfText( + this.device, + renderBundle, + measurements, + font, + textBuffer + ); + if (options.pixelScale !== undefined) { + msdfText.setPixelScale(options.pixelScale); + } + + if (options.color !== undefined) { + msdfText.setColor(...options.color); + } + + return msdfText; + } + + measureText( + font: MsdfFont, + text: string, + charCallback?: (x: number, y: number, line: number, char: MsdfChar) => void + ): MsdfTextMeasurements { + let maxWidth = 0; + const lineWidths: number[] = []; + + let textOffsetX = 0; + let textOffsetY = 0; + let line = 0; + let printedCharCount = 0; + let nextCharCode = text.charCodeAt(0); + for (let i = 0; i < text.length; ++i) { + const charCode = nextCharCode; + nextCharCode = i < text.length - 1 ? text.charCodeAt(i + 1) : -1; + + switch (charCode) { + case 10: // Newline + lineWidths.push(textOffsetX); + line++; + maxWidth = Math.max(maxWidth, textOffsetX); + textOffsetX = 0; + textOffsetY -= font.lineHeight; + case 13: // CR + break; + case 32: // Space + // For spaces, advance the offset without actually adding a character. + textOffsetX += font.getXAdvance(charCode); + break; + default: { + if (charCallback) { + charCallback( + textOffsetX, + textOffsetY, + line, + font.getChar(charCode) + ); + } + textOffsetX += font.getXAdvance(charCode, nextCharCode); + printedCharCount++; + } + } + } + + lineWidths.push(textOffsetX); + maxWidth = Math.max(maxWidth, textOffsetX); + + return { + width: maxWidth, + height: lineWidths.length * font.lineHeight, + lineWidths, + printedCharCount, + }; + } + + updateCamera(projection: Mat4, view: Mat4) { + this.cameraArray.set(projection, 0); + this.cameraArray.set(view, 16); + this.device.queue.writeBuffer( + this.cameraUniformBuffer, + 0, + this.cameraArray + ); + } + + render(renderPass: GPURenderPassEncoder, ...text: MsdfText[]) { + const renderBundles = text.map((t) => t.getRenderBundle()); + renderPass.executeBundles(renderBundles); + } +} diff --git a/sample/textRenderingMsdf/msdfText.wgsl b/sample/textRenderingMsdf/msdfText.wgsl new file mode 100644 index 00000000..87dfeb36 --- /dev/null +++ b/sample/textRenderingMsdf/msdfText.wgsl @@ -0,0 +1,79 @@ +// Positions for simple quad geometry +const pos = array(vec2f(0, -1), vec2f(1, -1), vec2f(0, 0), vec2f(1, 0)); + +struct VertexInput { + @builtin(vertex_index) vertex : u32, + @builtin(instance_index) instance : u32, +}; + +struct VertexOutput { + @builtin(position) position : vec4f, + @location(0) texcoord : vec2f, +}; + +struct Char { + texOffset: vec2f, + texExtent: vec2f, + size: vec2f, + offset: vec2f, +}; + +struct FormattedText { + transform: mat4x4f, + color: vec4f, + scale: f32, + chars: array, +}; + +struct Camera { + projection: mat4x4f, + view: mat4x4f, +}; + +// Font bindings +@group(0) @binding(0) var fontTexture: texture_2d; +@group(0) @binding(1) var fontSampler: sampler; +@group(0) @binding(2) var chars: array; + +// Text bindings +@group(1) @binding(0) var camera: Camera; +@group(1) @binding(1) var text: FormattedText; + +@vertex +fn vertexMain(input : VertexInput) -> VertexOutput { + let textElement = text.chars[input.instance]; + let char = chars[u32(textElement.z)]; + let charPos = (pos[input.vertex] * char.size + textElement.xy + char.offset) * text.scale; + + var output : VertexOutput; + output.position = camera.projection * camera.view * text.transform * vec4f(charPos, 0, 1); + + output.texcoord = pos[input.vertex] * vec2f(1, -1); + output.texcoord *= char.texExtent; + output.texcoord += char.texOffset; + return output; +} + +fn sampleMsdf(texcoord: vec2f) -> f32 { + let c = textureSample(fontTexture, fontSampler, texcoord); + return max(min(c.r, c.g), min(max(c.r, c.g), c.b)); +} + +// Antialiasing technique from https://drewcassidy.me/2020/06/26/sdf-antialiasing/ +@fragment +fn fragmentMain(input : VertexOutput) -> @location(0) vec4f { + let dist = 0.5 - sampleMsdf(input.texcoord); + + // sdf distance per pixel (gradient vector) + let ddist = vec2f(dpdx(dist), dpdy(dist)); + + // distance to edge in pixels (scalar) + let pixelDist = dist / length(ddist); + + let alpha = saturate(0.5 - pixelDist); + if (alpha < 0.001) { + discard; + } + + return vec4f(text.color.rgb, text.color.a * alpha); +} \ No newline at end of file diff --git a/samples/textRenderingMsdf/index.html b/samples/textRenderingMsdf/index.html new file mode 100644 index 00000000..aaa6026d --- /dev/null +++ b/samples/textRenderingMsdf/index.html @@ -0,0 +1,9 @@ + + + + + +