Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Partially refactor JS utilities to support future webapps in separate folder structure #1364

Merged
merged 6 commits into from
Jul 12, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
src/esp/bindings_js/utils/*
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ repos:
- eslint-plugin-prettier@3.1.0
- eslint-plugin-html@6.0.0
- prettier@1.18.2
exclude: examples/web_apps|src/esp/bindings_js/utils

- repo: https://github.com/shellcheck-py/shellcheck-py
rev: v0.7.2.1
Expand Down
112 changes: 112 additions & 0 deletions src/esp/bindings_js/utils/WindowlessEmscriptenApplication.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
ldcWV marked this conversation as resolved.
Show resolved Hide resolved
This file is part of Magnum.

Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021 Vladimír Vondruš <mosra@centrum.cz>

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.
*/

function createMagnumModule(init) {
const offscreen = new OffscreenCanvas(256, 256);

const module = Object.assign({}, Module);

Object.assign(module, {
preRun: [],
postRun: [],

arguments: [],

// printErr: function(_message) {
// if(module.log) {
// module.log.innerHTML += Array.prototype.slice.call(arguments).join(' ')
// .replace(/[\"&<>]/g, function (a) {
// return { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' }[a];
// }) + '\n';
// }
// },

// print: function(_message) {
// if(module.log) {
// module.log.innerHTML += Array.prototype.slice.call(arguments).join(' ')
// .replace(/[\"&<>]/g, function (a) {
// return { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' }[a];
// }) + '\n';
// }
// },

/* onAbort not handled here, as the output is printed directly on the page */

canvas: offscreen,
status: document.getElementById("status"),
statusDescription: document.getElementById("status-description"),

setStatus: function(message) {
if (module.status) {
module.status.innerHTML = message;
}
},

setStatusDescription: function(message) {
if (module.statusDescription) {
module.statusDescription.innerHTML = message;
}
},

totalDependencies: 0,

monitorRunDependencies: function(left) {
this.totalDependencies = Math.max(this.totalDependencies, left);

if (left) {
module.setStatus("Downloading...");
module.setStatusDescription(
this.totalDependencies - left + " / " + this.totalDependencies
);
} else {
module.setStatus("Download complete");
module.setStatusDescription("");
}
}
});

Object.assign(module, init);

module.setStatus("Downloading...");

return module;
}

/* Default global Module object */
var Module = createMagnumModule();

/* UMD export */
if (typeof exports === "object" && typeof module === "object") {
/* CommonJS/Node */
module.exports = createMagnumModule;
} else if (typeof define === "function" && define["amd"]) {
/* AMD */
define([], function() {
return createMagnumModule;
});
} else if (typeof exports === "object") {
/* CommonJS strict */
exports["createMagnumModule"] = createMagnumModule;
}
68 changes: 68 additions & 0 deletions src/esp/bindings_js/utils/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright (c) Facebook, Inc. and its affiliates.
ldcWV marked this conversation as resolved.
Show resolved Hide resolved
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.

/**
* Check whether web assembly is supported on the current browser or not.
* Returns false if not otherwise true.
*/
function checkWebAssemblySupport() {
try {
if (
typeof WebAssembly === "object" &&
typeof WebAssembly.instantiate === "function"
) {
const module = new WebAssembly.Module(
Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00)
);
if (module instanceof WebAssembly.Module) {
return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
}
}
} catch (e) {
return false;
}
return false;
}

/**
* Checks for WebGL2 support in current browser.
* Returns 0 if there is no support, 1 if support is there but disabled otherwise 2.
*/
function checkWebgl2Support() {
let canvas;
let ctx;
let hasWebgl = false;

try {
canvas = document.createElement("canvas");
ctx = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
} catch (e) {
return;
}

if (ctx !== undefined) {
hasWebgl = true;
}

canvas = undefined;
if (!hasWebgl) {
if (typeof WebGL2RenderingContext !== "undefined") {
return 1;
} else {
return 0;
}
} else {
return 2;
}
}

function buildConfigFromURLParameters(config = {}) {
for (let arg of window.location.search.substr(1).split("&")) {
let [key, value] = arg.split("=");
if (key && value) {
config[key] = decodeURIComponent(value);
}
}
return config;
}
71 changes: 71 additions & 0 deletions src/esp/bindings_js/utils/vr_utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
const VIEW_SENSORS = ["left_eye", "right_eye"];
ldcWV marked this conversation as resolved.
Show resolved Hide resolved

function getEyeSensorSpecs() {
const specs = new Module.VectorSensorSpec();
{
const spec = new Module.CameraSensorSpec();
spec.uuid = "left_eye";
spec.sensorType = Module.SensorType.COLOR;
spec.sensorSubType = Module.SensorSubType.PINHOLE;
spec.resolution = [1024, 1024];
ldcWV marked this conversation as resolved.
Show resolved Hide resolved
specs.push_back(spec);
}
{
const spec = new Module.CameraSensorSpec();
spec.uuid = "right_eye";
spec.sensorType = Module.SensorType.COLOR;
spec.sensorSubType = Module.SensorSubType.PINHOLE;
spec.resolution = [1024, 1024];
specs.push_back(spec);
}
return specs;
}

// Given the WebXR viewer pose, update the positions/orientations of the view
// sensors
function updateHeadPose(pose, agent) {
const FWD = Module.Vector3.zAxis(1);
const FWD_ANGLE = Math.atan2(FWD.z(), FWD.x());
const DOWN = Module.Vector3.yAxis(-1);
const viewYawOffset = 0;

const headRotation = Module.toQuaternion(
pointToArray(pose.transform.orientation)
);
const pointingVec = headRotation.transformVector(FWD);
const pointingAngle =
Math.atan2(pointingVec.z(), pointingVec.x()) - FWD_ANGLE;

const agentQuat = Module.Quaternion.rotation(
new Module.Rad(pointingAngle + viewYawOffset),
DOWN
);
const inverseAgentRot = Module.Quaternion.rotation(
new Module.Rad(-pointingAngle),
DOWN
);

let state = new Module.AgentState();
agent.getState(state);
state.rotation = Module.toVec4f(agentQuat);
agent.setState(state, false);

for (var iView = 0; iView < pose.views.length; ++iView) {
const view = pose.views[iView];

const sensor = agent.getSubtreeSensors().get(VIEW_SENSORS[iView]);

const pos = pointToArray(view.transform.position).slice(0, -1); // don't need w for position
sensor.setLocalTransform(
Module.toVec3f(
inverseAgentRot.transformVector(new Module.Vector3(...pos))
),
Module.toVec4f(
Module.Quaternion.mul(
inverseAgentRot,
Module.toQuaternion(pointToArray(view.transform.orientation))
)
)
);
}
}