matrix-engine-wgpu
Version:
Networking implemented - based on kurento openvidu server. fix arcball camera,instanced draws added also effect pipeline blend with instancing option.Normalmap added, Fixed shadows casting vs camera/video texture, webGPU powered pwa application. Crazy fas
1,596 lines (1,544 loc) • 1.02 MB
JavaScript
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
"use strict";
var _cameraTexture = require("./examples/camera-texture.js");
var _glbLoader = require("./examples/glb-loader.js");
var _loadObjFile = require("./examples/load-obj-file.js");
var _loadObjsSequence = require("./examples/load-objs-sequence.js");
var _unlitTextures = require("./examples/unlit-textures.js");
var _videoTexture = require("./examples/video-texture.js");
var _utils = require("./src/engine/utils.js");
/**
* @examples
* MATRIX_ENGINE_WGPU EXAMPLE WORKSPACE
* Nikola Lukic 2024
*/
// import {loadJamb} from "./examples/load-jamb.js";
function destroyJambDoms() {
if ((0, _utils.byId)('hud')) (0, _utils.byId)('hud').remove();
if ((0, _utils.byId)('jambTable')) (0, _utils.byId)('jambTable').remove();
if ((0, _utils.byId)('topTitleDOM')) (0, _utils.byId)('topTitleDOM').remove();
}
(0, _utils.byId)('loadObjFile').addEventListener("click", () => {
// byId('loadObjFile').setAttribute('disabled', true)
// byId('unlitTextures').removeAttribute('disabled')
if (typeof app !== "undefined") app.destroyProgram();
destroyJambDoms();
(0, _loadObjFile.loadObjFile)();
});
(0, _utils.byId)('unlitTextures').addEventListener("click", () => {
// byId('unlitTextures').setAttribute('disabled', true)
// byId('loadObjFile').removeAttribute('disabled')
if (typeof app !== "undefined") app.destroyProgram();
destroyJambDoms();
(0, _unlitTextures.unlitTextures)();
});
(0, _utils.byId)('camera-texture').addEventListener("click", () => {
if (typeof app !== "undefined") app.destroyProgram();
destroyJambDoms();
(0, _cameraTexture.loadCameraTexture)();
});
(0, _utils.byId)('video-texture').addEventListener("click", () => {
if (typeof app !== "undefined") app.destroyProgram();
destroyJambDoms();
(0, _videoTexture.loadVideoTexture)();
});
(0, _utils.byId)('glb-loader').addEventListener("click", () => {
if (typeof app !== "undefined") app.destroyProgram();
// destroyJambDoms();
(0, _glbLoader.loadGLBLoader)();
});
(0, _utils.byId)('jamb').addEventListener("click", () => {
open("https://maximumroulette.com/apps/webgpu/");
});
(0, _utils.byId)('objs-anim').addEventListener("click", () => {
// byId('unlitTextures').setAttribute('disabled', true)
// byId('loadObjFile').setAttribute('disabled', true)
// byId('jamb').removeAttribute('disabled')
if (typeof app !== "undefined") app.destroyProgram();
destroyJambDoms();
(0, _loadObjsSequence.loadObjsSequence)();
});
},{"./examples/camera-texture.js":2,"./examples/glb-loader.js":3,"./examples/load-obj-file.js":4,"./examples/load-objs-sequence.js":5,"./examples/unlit-textures.js":6,"./examples/video-texture.js":7,"./src/engine/utils.js":48}],2:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.loadCameraTexture = void 0;
var _world = _interopRequireDefault(require("../src/world.js"));
var _loaderObj = require("../src/engine/loader-obj.js");
var _utils = require("../src/engine/utils.js");
var _raycast = require("../src/engine/raycast.js");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var loadCameraTexture = function () {
let cameraTexture = new _world.default({
useSingleRenderPass: true,
canvasSize: 'fullscreen',
mainCameraParams: {
type: 'WASD',
responseCoef: 1000
},
clearColor: {
r: 0,
b: 0.122,
g: 0.122,
a: 1
}
}, () => {
cameraTexture.addLight();
addEventListener('AmmoReady', () => {
(0, _loaderObj.downloadMeshes)({
welcomeText: "./res/meshes/blender/piramyd.obj",
armor: "./res/meshes/obj/armor.obj",
sphere: "./res/meshes/blender/sphere.obj",
cube: "./res/meshes/blender/cube.obj"
}, onLoadObj, {
scale: [1, 1, 1]
});
});
function onLoadObj(m) {
cameraTexture.myLoadedMeshes = m;
for (var key in m) {
console.log(`%c Loaded objs: ${key} `, _utils.LOG_MATRIX);
}
cameraTexture.addMeshObj({
position: {
x: 0,
y: 2,
z: -10
},
rotation: {
x: 0,
y: 0,
z: 0
},
rotationSpeed: {
x: 0,
y: 0,
z: 0
},
texturesPaths: ['./res/meshes/blender/cube.png'],
name: 'MyVideoTex',
mesh: m.cube,
physics: {
enabled: true,
geometry: "Cube"
}
// raycast: { enabled: true , radius: 2 }
});
var TEST = cameraTexture.getSceneObjectByName('MyVideoTex');
setTimeout(() => {
console.log(`%c Test video-texture...`, _utils.LOG_MATRIX);
TEST.loadVideoTexture({
type: 'camera'
});
}, 4000);
}
});
window.app = cameraTexture;
};
exports.loadCameraTexture = loadCameraTexture;
},{"../src/engine/loader-obj.js":40,"../src/engine/raycast.js":47,"../src/engine/utils.js":48,"../src/world.js":71}],3:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.loadGLBLoader = loadGLBLoader;
var _world = _interopRequireDefault(require("../src/world.js"));
var _loaderObj = require("../src/engine/loader-obj.js");
var _utils = require("../src/engine/utils.js");
var _bvh = require("../src/engine/loaders/bvh.js");
var _webgpuGltf = require("../src/engine/loaders/webgpu-gltf.js");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @Note
* “Character and animation assets from Mixamo,
* used under Adobe’s royalty‑free license.
* Redistribution of raw assets is not permitted.”
**/
function loadGLBLoader() {
let TEST_ANIM = new _world.default({
useSingleRenderPass: true,
canvasSize: 'fullscreen',
mainCameraParams: {
type: 'WASD',
responseCoef: 1000
},
clearColor: {
r: 0,
b: 0.122,
g: 0.122,
a: 1
}
}, () => {
addEventListener('AmmoReady', async () => {
setTimeout(() => {
app.cameras.WASD.yaw = -0.03;
app.cameras.WASD.pitch = -0.49;
app.cameras.WASD.position[2] = 0;
app.cameras.WASD.position[1] = 23;
}, 2000);
(0, _loaderObj.downloadMeshes)({
cube: "./res/meshes/blender/cube.obj"
}, onGround, {
scale: [120, 0.5, 120]
});
// // Monster1
var glbFile01 = await fetch("res/meshes/glb/monster.glb").then(res => res.arrayBuffer().then(buf => (0, _webgpuGltf.uploadGLBModel)(buf, TEST_ANIM.device)));
TEST_ANIM.addGlbObj({
material: {
type: 'standard',
useTextureFromGlb: true
},
scale: [20, 20, 20],
position: {
x: 0,
y: -4,
z: -70
},
name: 'firstGlb',
texturesPaths: ['./res/meshes/glb/textures/mutant_origin.png']
}, null, glbFile01);
var glbFile02 = await fetch("res/meshes/glb/monster.glb").then(res => res.arrayBuffer().then(buf => (0, _webgpuGltf.uploadGLBModel)(buf, TEST_ANIM.device)));
TEST_ANIM.addGlbObj({
material: {
type: 'power',
useTextureFromGlb: true
},
scale: [20, 20, 20],
position: {
x: -40,
y: -4,
z: -70
},
name: 'firstGlb',
texturesPaths: ['./res/meshes/glb/textures/mutant_origin.png']
}, null, glbFile02);
var glbFile03 = await fetch("res/meshes/glb/monster.glb").then(res => res.arrayBuffer().then(buf => (0, _webgpuGltf.uploadGLBModel)(buf, TEST_ANIM.device)));
TEST_ANIM.addGlbObj({
material: {
type: 'pong',
useTextureFromGlb: true
},
scale: [20, 20, 20],
position: {
x: 40,
y: -4,
z: -70
},
name: 'firstGlb',
texturesPaths: ['./res/meshes/glb/textures/mutant_origin.png']
}, null, glbFile03);
// woman
var glbFile11 = await fetch("res/meshes/glb/woman1.glb").then(res => res.arrayBuffer().then(buf => (0, _webgpuGltf.uploadGLBModel)(buf, TEST_ANIM.device)));
TEST_ANIM.addGlbObj({
material: {
type: 'normalmap',
useTextureFromGlb: true
},
scale: [20, 20, 20],
position: {
x: 0,
y: -4,
z: -20
},
name: 'woman1',
texturesPaths: ['./res/meshes/glb/textures/mutant_origin.png']
}, null, glbFile11);
var glbFile02 = await fetch("res/meshes/glb/woman1.glb").then(res => res.arrayBuffer().then(buf => (0, _webgpuGltf.uploadGLBModel)(buf, TEST_ANIM.device)));
TEST_ANIM.addGlbObj({
material: {
type: 'power',
useTextureFromGlb: true
},
scale: [20, 20, 20],
position: {
x: -40,
y: -4,
z: -20
},
name: 'woman1',
texturesPaths: ['./res/meshes/glb/textures/mutant_origin.png']
}, null, glbFile02);
var glbFile03 = await fetch("res/meshes/glb/woman1.glb").then(res => res.arrayBuffer().then(buf => (0, _webgpuGltf.uploadGLBModel)(buf, TEST_ANIM.device)));
TEST_ANIM.addGlbObj({
material: {
type: 'pong',
useTextureFromGlb: true
},
scale: [20, 20, 20],
position: {
x: 40,
y: -4,
z: -20
},
name: 'woman1',
texturesPaths: ['./res/meshes/glb/textures/mutant_origin.png']
}, null, glbFile03);
var glbFileWhouse = await fetch("res/meshes/glb/wood-house-1.glb").then(res => res.arrayBuffer().then(buf => (0, _webgpuGltf.uploadGLBModel)(buf, TEST_ANIM.device)));
TEST_ANIM.addGlbObj({
material: {
type: 'pong',
useTextureFromGlb: true
},
scale: [20, 20, 20],
position: {
x: 40,
y: -4,
z: -20
},
name: 'glbFileWhouse',
texturesPaths: ['./res/meshes/glb/textures/mutant_origin.png']
}, null, glbFileWhouse);
// this is future load and replace skeletal anim.
// const path = 'https://raw.githubusercontent.com/zlatnaspirala/Matrix-Engine-BVH-test/main/javascript-bvh/example.bvh';
// const path = 'res/meshes/glb/glb-test1.bvh';
// loadBVH(path).then(async (BVHANIM) => {
// var glbFile = await fetch(
// "res/meshes/glb/test.glb")
// .then(res => res.arrayBuffer().then(buf => uploadGLBModel(buf, TEST_ANIM.device)));
// TEST_ANIM.addGlbObj({
// // scale: [1,1,1],
// scale: [10, 10, 10],
// name: 'firstGlb',
// texturesPaths: ['./res/textures/rust.jpg'],
// }, BVHANIM, glbFile);
// });
});
function onGround(m) {
TEST_ANIM.addLight();
TEST_ANIM.addMeshObj({
position: {
x: 0,
y: -5,
z: -10
},
rotation: {
x: 0,
y: 0,
z: 0
},
rotationSpeed: {
x: 0,
y: 0,
z: 0
},
texturesPaths: ['./res/meshes/blender/cube.png'],
name: 'ground',
mesh: m.cube,
physics: {
enabled: false,
mass: 0,
geometry: "Cube"
}
});
app.lightContainer[0].position[1] = 25;
}
});
// just for dev
window.app = TEST_ANIM;
}
// loadGLBLoader()
},{"../src/engine/loader-obj.js":40,"../src/engine/loaders/bvh.js":42,"../src/engine/loaders/webgpu-gltf.js":43,"../src/engine/utils.js":48,"../src/world.js":71}],4:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.loadObjFile = void 0;
var _world = _interopRequireDefault(require("../src/world.js"));
var _loaderObj = require("../src/engine/loader-obj.js");
var _utils = require("../src/engine/utils.js");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
// import {addRaycastsAABBListener} from "../src/engine/raycast.js";
var loadObjFile = function () {
let loadObjFile = new _world.default({
useSingleRenderPass: true,
canvasSize: 'fullscreen',
mainCameraParams: {
type: 'WASD',
responseCoef: 1000
},
clearColor: {
r: 0,
b: 0.122,
g: 0.122,
a: 1
}
}, () => {
addEventListener('AmmoReady', () => {
(0, _loaderObj.downloadMeshes)({
ball: "./res/meshes/blender/sphere.obj",
cube: "./res/meshes/blender/cube.obj"
}, onLoadObj, {
scale: [1, 1, 1]
});
(0, _loaderObj.downloadMeshes)({
cube: "./res/meshes/blender/cube.obj"
}, onGround, {
scale: [20, 1, 20]
});
});
function onGround(m) {
setTimeout(() => {
app.cameras.WASD.yaw = -0.03;
app.cameras.WASD.pitch = -0.49;
app.cameras.WASD.position[2] = 0;
app.cameras.WASD.position[1] = 3.76;
}, 600);
loadObjFile.addMeshObj({
position: {
x: 0,
y: -5,
z: -10
},
rotation: {
x: 0,
y: 0,
z: 0
},
rotationSpeed: {
x: 0,
y: 0,
z: 0
},
texturesPaths: ['./res/meshes/blender/cube.png'],
name: 'ground',
mesh: m.cube,
physics: {
enabled: false,
mass: 0,
geometry: "Cube"
}
// raycast: { enabled: true , radius: 2 }
});
}
function onLoadObj(m) {
loadObjFile.myLoadedMeshes = m;
loadObjFile.addMeshObj({
material: {
type: 'standard'
},
position: {
x: 0,
y: 2,
z: -20
},
rotation: {
x: 0,
y: 0,
z: 0
},
rotationSpeed: {
x: 0,
y: 0,
z: 0
},
texturesPaths: ['./res/meshes/blender/cube.png'],
name: 'cube1',
mesh: m.cube,
physics: {
enabled: false,
geometry: "Cube"
}
// raycast: { enabled: true , radius: 2 }
});
loadObjFile.addMeshObj({
material: {
type: 'standard'
},
position: {
x: 0,
y: -1,
z: -20
},
rotation: {
x: 0,
y: 0,
z: 0
},
rotationSpeed: {
x: 0,
y: 111,
z: 0
},
texturesPaths: ['./res/meshes/blender/cube.png'],
name: 'ball1',
mesh: m.ball,
physics: {
enabled: false,
geometry: "Sphere"
}
});
var TEST = loadObjFile.getSceneObjectByName('cube2');
console.log(`%c Test access scene ${TEST} object.`, _utils.LOG_MATRIX);
loadObjFile.addLight();
loadObjFile.lightContainer[0].behavior.setOsc0(-1, 1, 0.1);
loadObjFile.lightContainer[0].behavior.value_ = -1;
loadObjFile.lightContainer[0].updater.push(light => {
light.position[0] = light.behavior.setPath0();
});
loadObjFile.lightContainer[0].position[1] = 9;
}
});
// just for dev
window.app = loadObjFile;
};
exports.loadObjFile = loadObjFile;
},{"../src/engine/loader-obj.js":40,"../src/engine/utils.js":48,"../src/world.js":71}],5:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.loadObjsSequence = void 0;
var _world = _interopRequireDefault(require("../src/world.js"));
var _loaderObj = require("../src/engine/loader-obj.js");
var _utils = require("../src/engine/utils.js");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var loadObjsSequence = function () {
let loadObjFile = new _world.default({
useSingleRenderPass: true,
canvasSize: 'fullscreen',
mainCameraParams: {
type: 'WASD',
responseCoef: 1000
}
}, () => {
addEventListener('AmmoReady', () => {
// requied now
loadObjFile.addLight();
// adapt
app.lightContainer[0].position[2] = -20;
app.lightContainer[0].position[1] = 25;
app.lightContainer[0].intensity = 10;
(0, _loaderObj.downloadMeshes)({
cube: "./res/meshes/blender/cube.obj"
}, onGround, {
scale: [20, 1, 20]
});
(0, _loaderObj.downloadMeshes)((0, _loaderObj.makeObjSeqArg)({
id: "swat-walk-pistol",
path: "res/meshes/objs-sequence/swat-walk-pistol",
from: 1,
to: 20
}), onLoadObj, {
scale: [0.1, 0.1, 0.1]
});
});
function onLoadObj(m) {
console.log(`%c Loaded objs: ${m} `, _utils.LOG_MATRIX);
var objAnim = {
id: "swat-walk-pistol",
meshList: m,
currentAni: 1,
animations: {
active: 'walk',
walk: {
from: 1,
to: 20,
speed: 3
},
walkPistol: {
from: 36,
to: 60,
speed: 3
}
}
};
loadObjFile.addMeshObj({
position: {
x: 0,
y: 0,
z: -20
},
rotation: {
x: 0,
y: 0,
z: 0
},
rotationSpeed: {
x: 0,
y: 0,
z: 0
},
scale: [100, 100, 100],
texturesPaths: ['./res/meshes/blender/swat.png'],
name: 'swat',
mesh: m['swat-walk-pistol'],
physics: {
enabled: false,
geometry: "Cube"
},
objAnim: objAnim
});
setTimeout(() => {
app.cameras.WASD.pitch = -0.2605728267949113;
app.cameras.WASD.yaw = -0.0580;
app.cameras.WASD.position[1] = 15;
app.cameras.WASD.position[2] = 11;
app.getSceneObjectByName('swat').objAnim.play('walk');
}, 200);
}
function onGround(m) {
setTimeout(() => {
app.cameras.WASD.yaw = -0.03;
app.cameras.WASD.pitch = -0.49;
app.cameras.WASD.position[2] = 0;
app.cameras.WASD.position[1] = 3.76;
}, 500);
loadObjFile.addMeshObj({
position: {
x: 0,
y: -1,
z: -10
},
rotation: {
x: 0,
y: 0,
z: 0
},
rotationSpeed: {
x: 0,
y: 0,
z: 0
},
texturesPaths: ['./res/meshes/blender/cube.png'],
name: 'ground',
mesh: m.cube,
physics: {
enabled: false,
mass: 0,
geometry: "Cube"
}
// raycast: { enabled: true , radius: 2 }
});
}
});
// Just for dev - easy console access
window.app = loadObjFile;
};
exports.loadObjsSequence = loadObjsSequence;
},{"../src/engine/loader-obj.js":40,"../src/engine/utils.js":48,"../src/world.js":71}],6:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.unlitTextures = void 0;
var _world = _interopRequireDefault(require("../src/world.js"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var unlitTextures = function () {
let unlitTextures = new _world.default({
useSingleRenderPass: false,
canvasSize: 'fullscreen'
}, () => {
addEventListener('AmmoReady', () => {
let c = {
scale: 2,
position: {
x: -3,
y: 0,
z: -10
},
rotation: {
x: 0,
y: 0,
z: 0
},
rotationSpeed: {
x: 10,
y: 0,
z: 0
},
texturesPaths: ['./res/textures/rust.jpg']
};
let o = {
scale: 2,
position: {
x: 3,
y: 0,
z: -10
},
rotation: {
x: 0,
y: 0,
z: 0
},
rotationSpeed: {
x: 10,
y: 0,
z: 0
},
texturesPaths: ['./res/textures/default.png']
};
unlitTextures.addCube(o);
unlitTextures.addBall(c);
// just to fix warns
unlitTextures.addLight();
});
});
window.app = unlitTextures;
};
exports.unlitTextures = unlitTextures;
},{"../src/world.js":71}],7:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.loadVideoTexture = void 0;
var _world = _interopRequireDefault(require("../src/world.js"));
var _loaderObj = require("../src/engine/loader-obj.js");
var _utils = require("../src/engine/utils.js");
var _raycast = require("../src/engine/raycast.js");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
// @group(0) @binding(5) var<uniform> postFXMode: u32;
var loadVideoTexture = function () {
let videoTexture = new _world.default({
useSingleRenderPass: true,
canvasSize: 'fullscreen',
mainCameraParams: {
type: 'WASD',
responseCoef: 1000
},
clearColor: {
r: 0,
b: 0.122,
g: 0.122,
a: 1
}
}, () => {
// For now one light perscene must be added.
// if you dont wanna light just use intesity = 0
// videoTexture is app main instance
videoTexture.addLight();
(0, _raycast.addRaycastsAABBListener)();
videoTexture.canvas.addEventListener("ray.hit.event", e => {
console.log('test ray after shadows merge');
});
addEventListener('AmmoReady', () => {
(0, _loaderObj.downloadMeshes)({
welcomeText: "./res/meshes/blender/piramyd.obj",
armor: "./res/meshes/obj/armor.obj",
sphere: "./res/meshes/blender/sphere.obj",
cube: "./res/meshes/blender/cube.obj"
}, onLoadObj, {
scale: [1, 1, 1]
});
});
function onLoadObj(m) {
videoTexture.myLoadedMeshes = m;
for (var key in m) {
console.log(`%c Loaded objs: ${key} `, _utils.LOG_MATRIX);
}
videoTexture.addMeshObj({
position: {
x: 0,
y: 2,
z: -10
},
rotation: {
x: 0,
y: 0,
z: 0
},
rotationSpeed: {
x: 0,
y: 0,
z: 0
},
texturesPaths: ['./res/meshes/blender/cube.png'],
name: 'MyVideoTex',
mesh: m.cube,
physics: {
enabled: true,
geometry: "Cube"
},
raycast: {
enabled: true,
radius: 12
}
});
var TEST = videoTexture.getSceneObjectByName('MyVideoTex');
console.log(`%c Test video-texture...`, _utils.LOG_MATRIX);
TEST.loadVideoTexture({
type: 'video',
src: 'res/videos/tunel.mp4'
});
}
});
window.app = videoTexture;
};
exports.loadVideoTexture = loadVideoTexture;
},{"../src/engine/loader-obj.js":40,"../src/engine/raycast.js":47,"../src/engine/utils.js":48,"../src/world.js":71}],8:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _bvhLoader = require("./module/bvh-loader");
var _default = exports.default = _bvhLoader.MEBvh;
},{"./module/bvh-loader":9}],9:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.MEBvhJoint = exports.MEBvh = void 0;
exports.degToRad = degToRad;
exports.dot3vs1 = dot3vs1;
exports.euler2mat = euler2mat;
exports.mat2euler = mat2euler;
exports.multiply = multiply;
var _webgpuMatrix = require("webgpu-matrix");
/**
* @description Manual convert python script BVH
* from https://github.com/dabeschte/npybvh to the JS.
* @author Nikola Lukic
* @license GPL-V3
*/
function degToRad(degrees) {
return degrees * Math.PI / 180;
}
;
function arraySum3(a, b) {
var rez1 = a[0] + b[0];
var rez2 = a[1] + b[1];
var rez3 = a[2] + b[2];
return [rez1, rez2, rez3];
}
function deg2rad(degrees) {
return degrees * (Math.PI / 180);
}
function npdeg2rad(degrees) {
return [degrees[0] * (Math.PI / 180), degrees[1] * (Math.PI / 180), degrees[2] * (Math.PI / 180)];
}
function rad2deg(radians) {
return radians * (180 / Math.PI);
}
function byId(id) {
return document.getElementById(id);
}
// fix for .dot N-dim vs 1D-dim Array
function dot3vs1(a, b) {
var aNumRows = a.length,
aNumCols = a[0].length,
bNumRows = b.length;
var REZ1 = 0,
REZ2 = 0,
REZ3 = 0;
if (aNumRows == 3 && aNumCols == 3 && bNumRows == 3) {
for (var j = 0; j < a.length; j++) {
// First root of 3x3 a.
REZ1 += a[0][j] * b[j];
REZ2 += a[1][j] * b[j];
REZ3 += a[2][j] * b[j];
}
var finalRez = [REZ1, REZ2, REZ3];
return finalRez;
} else {
console.error("Bad arguments for dot3vs1");
}
}
function multiply(a, b) {
var aNumRows = a.length,
aNumCols = a[0].length,
bNumRows = b.length,
bNumCols = b[0].length,
m = new Array(aNumRows);
for (var r = 0; r < aNumRows; ++r) {
m[r] = new Array(bNumCols);
for (var c = 0; c < bNumCols; ++c) {
m[r][c] = 0;
for (var i = 0; i < aNumCols; ++i) {
m[r][c] += a[r][i] * b[i][c];
}
}
}
return m;
}
/**
* @description
* Euler's rotation theorem tells us that any rotation in 3D can be described by 3
* angles. Let's call the 3 angles the *Euler angle vector* and call the angles
* in the vector :Math:`alpha`, :Math:`beta` and :Math:`gamma`. The vector is [
* :Math:`alpha`, :Math:`beta`. :Math:`gamma` ] and, in this description, the
* order of the parameters specifies the order in which the rotations occur (so
* the rotation corresponding to :Math:`alpha` is applied first).
* @source https://github.com/matthew-brett/transforms3d/blob/master/transforms3d/euler.py
*/
// map axes strings to/from tuples of inner axis, parity, repetition, frame
var _AXES2TUPLE = {
'sxyz': [0, 0, 0, 0],
'sxyx': [0, 0, 1, 0],
'sxzy': [0, 1, 0, 0],
'sxzx': [0, 1, 1, 0],
'syzx': [1, 0, 0, 0],
'syzy': [1, 0, 1, 0],
'syxz': [1, 1, 0, 0],
'syxy': [1, 1, 1, 0],
'szxy': [2, 0, 0, 0],
'szxz': [2, 0, 1, 0],
'szyx': [2, 1, 0, 0],
'szyz': [2, 1, 1, 0],
'rzyx': [0, 0, 0, 1],
'rxyx': [0, 0, 1, 1],
'ryzx': [0, 1, 0, 1],
'rxzx': [0, 1, 1, 1],
'rxzy': [1, 0, 0, 1],
'ryzy': [1, 0, 1, 1],
'rzxy': [1, 1, 0, 1],
'ryxy': [1, 1, 1, 1],
'ryxz': [2, 0, 0, 1],
'rzxz': [2, 0, 1, 1],
'rxyz': [2, 1, 0, 1],
'rzyz': [2, 1, 1, 1]
};
// axis sequences for Euler angles
var _NEXT_AXIS = [1, 2, 0, 1];
function euler2mat(ai, aj, ak, axes) {
if (typeof axes === 'undefined') var axes = 'sxyz';
// Return rotation matrix from Euler angles and axis sequence.
// Parameters
/*
ai : float
First rotation angle (according to `axes`).
aj : float
Second rotation angle (according to `axes`).
ak : float
Third rotation angle (according to `axes`).
axes : str, optional
Axis specification; one of 24 axis sequences as string or encoded
tuple - e.g. ``sxyz`` (the default).
Returns
-------
mat : array (3, 3)
Rotation matrix or affine.
Examples
--------
>>> R = euler2mat(1, 2, 3, 'syxz')
>>> np.allclose(np.sum(R[0]), -1.34786452)
True
>>> R = euler2mat(1, 2, 3, (0, 1, 0, 1))
>>> np.allclose(np.sum(R[0]), -0.383436184)
True */
try {
var firstaxis = _AXES2TUPLE[axes][0],
parity = _AXES2TUPLE[axes][1],
repetition = _AXES2TUPLE[axes][2],
frame = _AXES2TUPLE[axes][3];
} catch (AttributeError) {
// _TUPLE2AXES[axes] # validation
// firstaxis, parity, repetition, frame = axes
console.error("AttributeError: ", AttributeError);
}
var i = firstaxis;
var j = _NEXT_AXIS[i + parity];
var k = _NEXT_AXIS[i - parity + 1];
if (frame) {
ai = ak;
ak = ai;
}
if (parity) {
ai = -ai;
aj = -aj;
ak = -ak;
}
var si = Math.sin(ai);
var sj = Math.sin(aj);
var sk = Math.sin(ak);
var ci = Math.cos(ai);
var cj = Math.cos(aj);
var ck = Math.cos(ak);
var cc = ci * ck;
var cs = ci * sk;
var sc = si * ck;
var ss = si * sk;
// M = np.eye(3)
var M = [[1., 0., 0], [0., 1., 0], [0., 0., 1]];
if (repetition) {
M[i][i] = cj;
M[i][j] = sj * si;
M[i][k] = sj * ci;
M[j][i] = sj * sk;
M[j][j] = -cj * ss + cc;
M[j][k] = -cj * cs - sc;
M[k][i] = -sj * ck;
M[k][j] = cj * sc + cs;
M[k][k] = cj * cc - ss;
} else {
M[i][i] = cj * ck;
M[i][j] = sj * sc - cs;
M[i][k] = sj * cc + ss;
M[j][i] = cj * sk;
M[j][j] = sj * ss + cc;
M[j][k] = sj * cs - sc;
M[k][i] = -sj;
M[k][j] = cj * si;
M[k][k] = cj * ci;
}
return M;
}
/**
* @description
* How to calculate the angle from rotation matrix.
*/
function mat2euler(M, rad2deg_flag) {
var pitch_1, pitch_2, roll_1, roll_2, yaw_1, yaw_2, pitch, roll, yaw;
if (M[2][0] != 1 & M[2][0] != -1) {
pitch_1 = -1 * Math.asin(M[2][0]);
pitch_2 = Math.PI - pitch_1;
roll_1 = Math.atan2(M[2][1] / Math.cos(pitch_1), M[2][2] / Math.cos(pitch_1));
roll_2 = Math.atan2(M[2][1] / Math.cos(pitch_2), M[2][2] / Math.cos(pitch_2));
yaw_1 = Math.atan2(M[1][0] / Math.cos(pitch_1), M[0][0] / Math.cos(pitch_1));
yaw_2 = Math.atan2(M[1][0] / Math.cos(pitch_2), M[0][0] / Math.cos(pitch_2));
pitch = pitch_1;
roll = roll_1;
yaw = yaw_1;
} else {
yaw = 0;
if (M[2][0] == -1) {
pitch = Math.PI / 2;
roll = yaw + Math.atan2(M[0][1], M[0][2]);
} else {
pitch = -Math.PI / 2;
roll = -1 * yaw + Math.atan2(-1 * M[0][1], -1 * M[0][2]);
}
}
if (typeof rad2deg_flag !== "undefined") {
// convert from radians to degrees
roll = roll * 180 / Math.PI;
pitch = pitch * 180 / Math.PI;
yaw = yaw * 180 / Math.PI;
}
return [roll, pitch, yaw];
}
class MEBvhJoint {
constructor(name, parent) {
this.name = name;
this.parent = parent;
this.offset = [[0, 0, 0], [0, 0, 0], [0, 0, 0]];
this.channels = [];
this.children = [];
// New: where in the frame array this joint’s channels start ???
this.channelOffset = 0;
}
add_child(child) {
this.children.push(child);
}
__repr__() {
return this.name;
}
position_animated() {
var detFlag = false;
for (const item in this.channels) {
if (this.channels[item].endsWith("position") == true) {
detFlag = true;
}
}
return detFlag;
}
rotation_animated() {
var detFlag = false;
for (const item in this.channels) {
if (this.channels[item].endsWith("rotation") == true) {
detFlag = true;
}
}
return detFlag;
}
createIdentityMatrix() {
// Returns a flat Float32Array of length 16 (column-major)
return new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
}
matrixFromKeyframe(frameData) {
const m = this.createIdentityMatrix();
let t = [0, 0, 0];
let r = [0, 0, 0];
for (let i = 0; i < this.channels.length; i++) {
const channel = this.channels[i];
const value = frameData[this.channelOffset + i];
// channelOffset = index into frameData where this joint’s values start
switch (channel) {
case 'Xposition':
t[0] = value;
break;
case 'Yposition':
t[1] = value;
break;
case 'Zposition':
t[2] = value;
break;
case 'Xrotation':
r[0] = degToRad(value);
break;
case 'Yrotation':
r[1] = degToRad(value);
break;
case 'Zrotation':
r[2] = degToRad(value);
break;
}
}
// Apply translation
_webgpuMatrix.mat4.translate(m, t, m);
// Apply rotations in BVH order (important!)
_webgpuMatrix.mat4.rotateX(m, r[0], m);
_webgpuMatrix.mat4.rotateY(m, r[1], m);
_webgpuMatrix.mat4.rotateZ(m, r[2], m);
return m;
}
}
exports.MEBvhJoint = MEBvhJoint;
class MEBvh {
constructor() {
this.joints = {};
this.root = null;
this.keyframes = null;
this.frames = 0;
this.fps = 0;
this.myName = "MATRIX-ENGINE-BVH";
// new
this.jointOrder = []; // array to store joints in order
}
computeJointOrder() {
this.jointOrder = [];
const traverse = joint => {
this.jointOrder.push(joint.name);
for (const child of joint.children) {
traverse(child);
}
};
traverse(this.root); // root is your MEBvhJoint
}
computeChannelOffsets() {
let offset = 0;
const walk = joint => {
joint.channelOffset = offset; // assign
offset += joint.channels.length; // advance
for (const child of joint.children) {
walk(child);
}
};
if (this.root) walk(this.root);
this.totalChannels = offset; // store total for frame allocation
}
async parse_file(link) {
return new Promise((resolve, reject) => {
fetch(link).then(event => {
event.text().then(text => {
var hierarchy = text.split("MOTION")[0];
var motion = text.split("MOTION")[1];
var newLog = document.createElement("div");
newLog.innerHTML += '<h2>Hierarchy</h2>';
newLog.innerHTML += '<p>' + hierarchy + '</p>';
var newLog2 = document.createElement("span");
newLog2.innerHTML += '<h2>Motion</h2>';
newLog2.innerHTML += '<p class="paragraf fixHeight" >' + motion + '</p>';
if (byId && byId('log') !== null) {
byId('log').appendChild(newLog2);
byId('log').appendChild(newLog);
}
this._parse_hierarchy(hierarchy);
this.computeJointOrder();
this.computeChannelOffsets(); // <— must do this here NEW
this.parse_motion(motion);
resolve();
});
});
});
}
_parse_hierarchy(text) {
var lines = text.split(/\s*\n+\s*/);
var joint_stack = [];
for (var key in lines) {
var line = lines[key];
var words = line.split(/\s+/);
var instruction = words[0];
var parent = null;
if (instruction == "JOINT" || instruction == "ROOT") {
if (instruction == "JOINT") {
// -1 py -> last item
parent = joint_stack[joint_stack.length - 1];
} else {
parent = null;
}
var joint = new MEBvhJoint(words[1], parent);
this.joints[joint.name] = joint;
if (parent != null) {
parent.add_child(joint);
}
joint_stack.push(joint);
if (instruction == "ROOT") {
this.root = joint;
}
} else if (instruction == "CHANNELS") {
for (var j = 2; j < words.length; j++) {
joint_stack[joint_stack.length - 1].channels.push(words[j]);
}
} else if (instruction == "OFFSET") {
for (var j = 1; j < words.length; j++) {
joint_stack[joint_stack.length - 1].offset[j - 1] = parseFloat(words[j]);
}
} else if (instruction == "End") {
var joint = new MEBvhJoint(joint_stack[joint_stack.length - 1].name + "_end", joint_stack[joint_stack.length - 1]);
joint_stack[joint_stack.length - 1].add_child(joint);
joint_stack.push(joint);
this.joints[joint.name] = joint;
} else if (instruction == "}") {
joint_stack.pop();
}
}
}
_add_pose_recursive(joint, offset, poses) {
var newLog1 = document.createElement("span");
newLog1.innerHTML += '<h2>add_pose_recursive</h2>';
newLog1.innerHTML += '<p class="paragraf" >Joint Name: ' + joint.name + '</p>';
newLog1.innerHTML += '<p>joint.parent : ' + (joint.parent != null ? joint.parent.name : 'null') + '</p>';
newLog1.innerHTML += '<p>joint.offset : ' + joint.offset + '</p>';
newLog1.innerHTML += '<p>joint.children.length : ' + joint.children.length + '</p>';
joint.children.length != 0 ? newLog1.innerHTML += '<p> Childrens: ' : newLog1.innerHTML += 'No Childrens ';
joint.children.forEach(iJoint => {
newLog1.innerHTML += ' ' + iJoint['name'] + ' , ';
});
newLog1.innerHTML += '</p>';
newLog1.innerHTML += '<p>Argument offset : ' + offset + '</p>';
byId('log').appendChild(newLog1);
var pose = arraySum3(joint.offset, offset);
poses.push(pose);
for (var c in joint.children) {
this._add_pose_recursive(joint.children[c], pose, poses);
}
}
plot_hierarchy() {
// import matplotlib.pyplot as plt
// from mpl_toolkits.mplot3d import axes3d, Axes3D
var poses = [];
this._add_pose_recursive(this.root, [0, 0, 0], poses);
// pos = np.array(poses);
/* Draw staff DISABLED
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(pos[:, 0], pos[:, 2], pos[:, 1])
ax.set_xlim(-30, 30)
ax.set_ylim(-30, 30)
ax.set_zlim(-30, 30)
plt.show() */
}
parse_motion(text) {
var lines = text.split(/\s*\n+\s*/);
var frame = 0;
for (var key in lines) {
var line = lines[key];
if (line == "") {
continue;
}
var words = line.split(/\s+/);
if (line.startsWith("Frame Time:")) {
this.fps = Math.round(1 / parseFloat(words[2]));
continue;
}
if (line.startsWith("Frames:")) {
this.frames = parseInt(words[1]);
continue;
}
if (this.keyframes == null) {
// OK this is just costruction (define) with random values.
var localArr = Array.from(Array(this.frames), () => new Array(words.length));
this.keyframes = localArr;
}
for (var angle_index = 0; angle_index < words.length; angle_index++) {
this.keyframes[frame][angle_index] = parseFloat(words[angle_index]);
}
frame += 1;
}
}
_extract_rotation(frame_pose, index_offset, joint) {
var local_rotation = [0, 0, 0],
M_rotation;
for (var key in joint.channels) {
var channel = joint.channels[key];
if (channel.endsWith("position")) {
continue;
}
if (channel == "Xrotation") {
local_rotation[0] = frame_pose[index_offset];
} else if (channel == "Yrotation") {
local_rotation[1] = frame_pose[index_offset];
} else if (channel == "Zrotation") {
local_rotation[2] = frame_pose[index_offset];
} else {
console.warn("Unknown channel {channel}");
// raise Exception(f"Unknown channel {channel}");
}
index_offset += 1;
}
local_rotation = npdeg2rad(local_rotation);
M_rotation = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
for (key in joint.channels) {
var channel = joint.channels[key];
if (channel.endsWith("position")) {
continue;
}
var euler_rot;
if (channel == "Xrotation") {
// console.warn("local_rotation " + local_rotation);
euler_rot = [local_rotation[0], 0., 0.];
} else if (channel == "Yrotation") {
euler_rot = [0., local_rotation[1], 0.];
} else if (channel == "Zrotation") {
euler_rot = [0., 0., local_rotation[2]];
} else {
console.warn("Unknown channel {channel}");
}
var M_channel = euler2mat(euler_rot[0], euler_rot[1], euler_rot[2], euler_rot[3]);
var M_rotation = multiply(M_rotation, M_channel);
}
return [M_rotation, index_offset];
}
_extract_position(joint, frame_pose, index_offset) {
var offset_position = [0, 0, 0];
for (var key in joint.channels) {
var channel = joint.channels[key];
if (channel.endsWith("rotation")) {
continue;
}
if (channel == "Xposition") {
offset_position[0] = frame_pose[index_offset];
} else if (channel == "Yposition") {
offset_position[1] = frame_pose[index_offset];
} else if (channel == "Zposition") {
offset_position[2] = frame_pose[index_offset];
} else {
console.warn("Unknown channel {channel}");
// raise Exception(f"Unknown channel {channel}")
}
index_offset += 1;
}
return [offset_position, index_offset];
}
_recursive_apply_frame(joint, frame_pose, index_offset, p, r, M_parent, p_parent) {
var joint_index;
if (joint.position_animated()) {
var local = this._extract_position(joint, frame_pose, index_offset);
var offset_position = local[0],
index_offset = local[1];
} else {
var offset_position = [0, 0, 0];
}
if (joint.channels.length == 0) {
var local2 = 0;
for (var item in this.joints) {
if (joint.name == item) {
joint_index = local2;
}
local2++;
}
p[joint_index] = arraySum3(p_parent, dot3vs1(M_parent, joint.offset));
r[joint_index] = mat2euler(M_parent);
return index_offset;
}
if (joint.rotation_animated()) {
var local2 = this._extract_rotation(frame_pose, index_offset, joint);
var M_rotation = local2[0];
index_offset = local2[1];
} else {
var M_rotation = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
}
var M = multiply(M_parent, M_rotation);
// https://www.khanacademy.org/math/precalculus/x9e81a4f98389efdf:matrices/x9e81a4f98389efdf:adding-and-subtracting-matrices/e/matrix_addition_and_subtraction
var position = arraySum3(p_parent, dot3vs1(M_parent, joint.offset));
position = arraySum3(position, offset_position);
var rotation = mat2euler(M, "rad2deg");
// just find by id
var local = 0;
for (const item in this.joints) {
if (joint.name == item) {
joint_index = local;
}
local++;
}
p[joint_index] = position;
r[joint_index] = rotation;
for (var c in joint.children) {
index_offset = this._recursive_apply_frame(joint.children[c], frame_pose, index_offset, p, r, M, position);
}
return index_offset;
}
frame_pose(frame) {
var jointLength = 0;
for (var x in this.joints) {
jointLength++;
}
var p = Array.from(Array(jointLength), () => [0, 0, 0]);
var r = Array.from(Array(jointLength), () => [0, 0, 0]);
var frame_pose = this.keyframes[frame];
var M_parent = [[0, 0, 0], [0, 0, 0], [0, 0, 0]];
M_parent[0][0] = 1;
M_parent[1][1] = 1;
M_parent[2][2] = 1;
this._recursive_apply_frame(this.root, frame_pose, 0, p, r, M_parent, [0, 0, 0]);
return [p, r];
}
all_frame_poses() {
var jointLength = 0;
for (var x in this.joints) {
jointLength++;
}
var p = Array.from({
length: this.frames
}, () => Array.from({
length: jointLength
}, () => [0, 0, 0]));
var r = Array.from({
length: this.frames
}, () => Array.from({
length: jointLength
}, () => [0, 0, 0]));
for (var frame = 0; frame < this.keyframes.length; frame++) {
var local3 = this.frame_pose(frame);
p[frame] = local3[0];
r[frame] = local3[1];
}
return [p, r];
}
_plot_pose(p, r, fig, ax) {
/*
_plot_pose(p, r, fig=None, ax=None) {
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d, Axes3D
if fig is None:
fig = plt.figure()
if ax is None:
ax = fig.add_subplot(111, projection='3d')
ax.cla()
ax.scatter(p[:, 0], p[:, 2], p[:, 1])
ax.set_xlim(-30, 30)
ax.set_ylim(-30, 30)
ax.set_zlim(-1, 59)
plt.draw()
plt.pause(0.001)
*/
}
// Meybe helps for draw
// plot_frame(frame, fig=None, ax=None) {
plot_frame(frame, fig, ax) {
// ????
// p, (r = this.frame_pose(frame));
// this._plot_pose(p, r, fig, ax);
}
joint_names() {
var keys = [];
for (var key in this.joints) {
keys.push(key);
}
return keys;
}
plot_all_frames() {
/*
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d, Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
for i in range(self.frames) {
self.plot_frame(i, fig, ax);
}
*/
}
__repr__() {
return `BVH.JS ${this.joints.keys().length} joints, ${this.frames} frames`;
}
}
exports.MEBvh = MEBvh;
},{"webgpu-matrix":21}],10:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.RANDOM = exports.EPSILON = exports.ARRAY_TYPE = exports.ANGLE_ORDER = void 0;
exports.equals = equals;
exports.round = round;
exports.setMatrixArrayType = setMatrixArrayType;
exports.toDegree = toDegree;
exports.toRadian = toRadian;
/**
* Common utilities
* @module glMatrix
*/
// Configuration Constants
var EPSILON = exports.EPSILON = 0.000001;
var ARRAY_TYPE = exports.ARRAY_TYPE = typeof Float32Array !== "undefined" ? Float32Array : Array;
var RANDOM = exports.RANDOM = Math.random;
var ANGLE_ORDER = exports.ANGLE_ORDER = "zyx";
/**
* Symmetric round
* see https://www.npmjs.com/package/round-half-up-symmetric#user-content-detailed-background
*
* @param {Number} a value to round
*/
function round(a) {
if (a >= 0) return Math.round(a);
return a % 0.5 === 0 ? Math.floor(a) : Math.round(a);
}
/**
* Sets the type of array used when creating new vectors and matrices
*
* @param {Float32ArrayConstructor | ArrayConstructor} type Array type, such as Float32Array or Array
*/
function setMatrixArrayType(type) {
exports.ARRAY_TYPE = ARRAY_TYPE = type;
}
var degree = Math.PI / 180;
var radian = 180 / Math.PI;
/**
* Convert Degree To Radian
*
* @param {Number} a Angle in Degrees
*/
function toRadian(a) {
return a * degree;
}
/**
* Convert Radian To Degree
*
* @param {Number} a Angle in Radians
*/
function toDegree(a) {
return a * radian;
}
/**
* Tests whether or not the arguments have approximately the same value, within an absolute
* or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less
* than or equal to 1.0, and a relative tolerance is used for larger values)
*
* @param {Number} a The first number to test.
* @param {Number} b The second number to test.
* @param {Number} tolerance Absolute or relative tolerance (default glMatrix.EPSILON)
* @returns {Boolean} True if the numbers are approximately equal, false otherwise.
*/
function equals(a, b) {
var tolerance = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : EPSILON;
return Math.abs(a - b) <= tolerance * Math.max(1, Math.abs(a), Math.abs(b));
}
},{}],11:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.vec4 = exports.vec3 = exports.vec2 = exports.quat2 = exports.quat = exports.mat4 = exports.mat3 = exports.mat2d = exports.mat2 = exports.glMatrix = void 0;
var glMatrix = _interopRequireWildcard(require("./common.js"));
exports.glMatrix = glMatrix;
var mat2 = _interopRequireWildcard(require("./mat2.js"));
exports.mat2 = mat2;
var mat2d = _interopRequireWildcard(require("./mat2d.js"));
exports.mat2d = mat2d;
var mat3 = _interopRequireWildcard(require("./mat3.js"));
exports.mat3 = mat3;
var mat4 = _interopRequireWildcard(require("./mat4.js"));
exports.mat4 = mat4;
var quat = _interopRequireWildcard(require("./quat.js"));
exports.quat = quat;
var quat2 = _interopRequireWildcard(require("./quat2.js"));
exports.quat2 = quat2;
var vec2 = _interopRequireWildcard(require("./vec2.js"));
exports.vec2 = vec2;
var vec3 = _interopRequireWildcard(require("./vec3.js"));
exports.vec3 = vec3;
var vec4 = _interopRequireWildcard(require("./vec4.js"));
exports.vec4 = vec4;
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnPr