|
|
|
@ -1,6 +1,7 @@
|
|
|
|
|
import * as THREE from 'three';
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
import { UpdateRequest, Update } from "/proto/mmelodies.proto";
|
|
|
|
|
import { radToDeg } from 'three/src/math/MathUtils';
|
|
|
|
|
|
|
|
|
|
// Subscribe to the audioprocess event
|
|
|
|
|
let socket: WebSocket | null = null;
|
|
|
|
@ -83,7 +84,8 @@ declare global {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (window.AbsoluteOrientationSensor) {
|
|
|
|
|
const sensor = new window.AbsoluteOrientationSensor();
|
|
|
|
|
// Create an AbsoluteOrientationSensor object
|
|
|
|
|
const sensor = new window.AbsoluteOrientationSensor({ frequency: 60, referenceFrame: 'device' });
|
|
|
|
|
|
|
|
|
|
Promise.all([
|
|
|
|
|
// @ts-ignore
|
|
|
|
@ -93,167 +95,81 @@ if (window.AbsoluteOrientationSensor) {
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
navigator.permissions.query({ name: "gyroscope" }),
|
|
|
|
|
]).then((results: PermissionStatus[]) => {
|
|
|
|
|
if (results.every((result) => result.state === "granted")) {
|
|
|
|
|
sensor.start();
|
|
|
|
|
console.log("started")
|
|
|
|
|
// …
|
|
|
|
|
} else {
|
|
|
|
|
if (!results.every((result) => result.state === "granted")) {
|
|
|
|
|
console.log("No permissions to use AbsoluteOrientationSensor.");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
console.log('AbsoluteOrientationSensor is not supported in this browser.');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create a renderer
|
|
|
|
|
const sceneWidth = 100;
|
|
|
|
|
const sceneHeight = 100;
|
|
|
|
|
const downscaling = 1; // 1 is no downscaling and higher is more downscaling
|
|
|
|
|
const renderer = new THREE.WebGLRenderer({ alpha: true });
|
|
|
|
|
renderer.setSize(sceneWidth, sceneHeight);
|
|
|
|
|
renderer.setPixelRatio(window.devicePixelRatio / downscaling);
|
|
|
|
|
(document.getElementById("gyroBox") || document.body).appendChild(renderer.domElement);
|
|
|
|
|
// Create a renderer
|
|
|
|
|
const sceneSize = new THREE.Vector3(100, 100, 100);
|
|
|
|
|
const renderer = new THREE.WebGLRenderer({alpha: true});
|
|
|
|
|
renderer.setSize(sceneSize.x, sceneSize.y);
|
|
|
|
|
renderer.setPixelRatio(window.devicePixelRatio / 2.5);
|
|
|
|
|
const scene = new THREE.Scene();
|
|
|
|
|
|
|
|
|
|
const axes = new THREE.AxesHelper(5);
|
|
|
|
|
scene.add(axes);
|
|
|
|
|
|
|
|
|
|
const camera = new THREE.PerspectiveCamera(75, sceneSize.x/sceneSize.y, 0.1, 1000);
|
|
|
|
|
camera.translateOnAxis(scene.up.clone(), 2);
|
|
|
|
|
camera.lookAt(axes.position);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Create a scene
|
|
|
|
|
const scene = new THREE.Scene();
|
|
|
|
|
// Get the checkbox element
|
|
|
|
|
const gyroBox = document.getElementById("gyroBox");
|
|
|
|
|
const checkbox = document.getElementById('gyro') as HTMLInputElement;
|
|
|
|
|
|
|
|
|
|
// Create a camera
|
|
|
|
|
const camera = new THREE.PerspectiveCamera(50, sceneWidth / sceneHeight, 0.1, 1000);
|
|
|
|
|
// Move the camera backwards
|
|
|
|
|
camera.position.y = 2;
|
|
|
|
|
// Point the camera towards the origin
|
|
|
|
|
camera.lookAt(new THREE.Vector3(0, 0, 0));
|
|
|
|
|
(gyroBox || document.body).appendChild(renderer.domElement);
|
|
|
|
|
gyroBox?.hidden == false;
|
|
|
|
|
|
|
|
|
|
// Create an arrow
|
|
|
|
|
|
|
|
|
|
// Define a vector representing the initial state (e.g., pointing up)
|
|
|
|
|
let xVec = new THREE.Vector3(1, 0, 0); // x-arrow pointing in positive x-direction
|
|
|
|
|
let yVec = new THREE.Vector3(0, 1, 0); // y-arrow pointing in positive y-direction
|
|
|
|
|
let zVec = new THREE.Vector3(0, 0, 1); // z-arrow pointing in positive z-direction
|
|
|
|
|
// Profiling
|
|
|
|
|
let sampleCount = 0; // Number of frames since the last second
|
|
|
|
|
let sampleSec = 0; // Time last second was recorded for a frame
|
|
|
|
|
|
|
|
|
|
// Animation loop
|
|
|
|
|
let setFPS = 60; // Desired framerate
|
|
|
|
|
let fps = 0; // Startup fps
|
|
|
|
|
|
|
|
|
|
// Create an arrow
|
|
|
|
|
const origin = new THREE.Vector3(0, 0, 0);
|
|
|
|
|
const length = 1;
|
|
|
|
|
const xColor = 0xff0000;
|
|
|
|
|
const yColor = 0x00ff00;
|
|
|
|
|
const zColor = 0x0000ff;
|
|
|
|
|
const xArrow = new THREE.ArrowHelper(xVec, origin, length, xColor);
|
|
|
|
|
const yArrow = new THREE.ArrowHelper(yVec, origin, length, yColor);
|
|
|
|
|
const zArrow = new THREE.ArrowHelper(zVec, origin, length, zColor);
|
|
|
|
|
let orientation = new THREE.Quaternion();
|
|
|
|
|
// Initialize default orientation
|
|
|
|
|
let calibratedDirection: THREE.Vector3 | null;
|
|
|
|
|
let currentDirection: THREE.Vector3 | null;
|
|
|
|
|
let relativeDirection: THREE.Vector3 | null;
|
|
|
|
|
|
|
|
|
|
// Add the arrow to the scene
|
|
|
|
|
scene.add(xArrow, yArrow, zArrow);
|
|
|
|
|
|
|
|
|
|
// Profiling
|
|
|
|
|
let frameTime = 0; // Time last frame was taken
|
|
|
|
|
let frameCount = 0; // Number of frames since the last second
|
|
|
|
|
let frameSec = 0; // Time last second was recorded for a frame
|
|
|
|
|
|
|
|
|
|
let sampleTime = 0; // Time last frame was taken
|
|
|
|
|
let sampleCount = 0; // Number of frames since the last second
|
|
|
|
|
let sampleSec = 0; // Time last second was recorded for a frame
|
|
|
|
|
|
|
|
|
|
// Animation loop
|
|
|
|
|
let setFPS = 60; // Desired framerate
|
|
|
|
|
let fps = 0; // Startup fps
|
|
|
|
|
let clock = new THREE.Clock();
|
|
|
|
|
let delta = 0;
|
|
|
|
|
|
|
|
|
|
function animate() {
|
|
|
|
|
requestAnimationFrame(animate);
|
|
|
|
|
delta += clock.getDelta();
|
|
|
|
|
|
|
|
|
|
if (delta > 1 / fps) {
|
|
|
|
|
|
|
|
|
|
// Orient and render the cursor
|
|
|
|
|
orientCursor();
|
|
|
|
|
render();
|
|
|
|
|
|
|
|
|
|
// Profiling
|
|
|
|
|
let currTime = Date.now();
|
|
|
|
|
if (currTime - frameTime >= 1000) {
|
|
|
|
|
console.log("Frames: " + frameCount)
|
|
|
|
|
frameCount = 0;
|
|
|
|
|
frameTime = currTime;
|
|
|
|
|
const render = (direction: THREE.Quaternion | null) => {
|
|
|
|
|
if (!direction) {
|
|
|
|
|
direction = new THREE.Quaternion().identity();
|
|
|
|
|
}
|
|
|
|
|
else { frameCount++; }
|
|
|
|
|
delta %= 1 / fps;
|
|
|
|
|
|
|
|
|
|
axes.setRotationFromQuaternion(direction);
|
|
|
|
|
|
|
|
|
|
renderer.render(scene, camera);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function render() {
|
|
|
|
|
// Render the scene with the camera
|
|
|
|
|
renderer.render(scene, camera);
|
|
|
|
|
}
|
|
|
|
|
// Initialize default orientation
|
|
|
|
|
let initialOrientation: THREE.Quaternion | null = null;
|
|
|
|
|
let relOrientation: THREE.Quaternion | null = null;
|
|
|
|
|
|
|
|
|
|
function orientCursor() {
|
|
|
|
|
if (initialOrientation !== null) {
|
|
|
|
|
relOrientation = new THREE.Quaternion().multiplyQuaternions(orientation, initialOrientation?.clone().invert());
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
relOrientation = orientation;
|
|
|
|
|
console.log("fallback orientation")
|
|
|
|
|
}
|
|
|
|
|
// Create a vector for each arrow's initial orientation
|
|
|
|
|
let xInit = new THREE.Vector3(1, 0, 0); // x-arrow pointing in positive x-direction
|
|
|
|
|
let yInit = new THREE.Vector3(0, 1, 0); // y-arrow pointing in positive y-direction
|
|
|
|
|
let zInit = new THREE.Vector3(0, 0, 1); // z-arrow pointing in positive z-direction
|
|
|
|
|
|
|
|
|
|
// Apply the orientation quaternion to the initial vectors
|
|
|
|
|
let xOrient = xInit.clone().applyQuaternion(relOrientation);
|
|
|
|
|
let yOrient = yInit.clone().applyQuaternion(relOrientation);
|
|
|
|
|
let zOrient = zInit.clone().applyQuaternion(relOrientation);
|
|
|
|
|
|
|
|
|
|
// Set the direction of the arrows
|
|
|
|
|
xArrow.setDirection(xOrient);
|
|
|
|
|
yArrow.setDirection(yOrient);
|
|
|
|
|
zArrow.setDirection(zOrient);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function calibrate() {
|
|
|
|
|
if (initialOrientation == null) {
|
|
|
|
|
console.log("Oriented");
|
|
|
|
|
initialOrientation = orientation;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if AbsoluteOrientationSensor is defined
|
|
|
|
|
if (window.AbsoluteOrientationSensor) {
|
|
|
|
|
// Create an AbsoluteOrientationSensor object
|
|
|
|
|
const sensor = new window.AbsoluteOrientationSensor({ frequency: 60, referenceFrame: 'device' });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Add an event listener for sensor readings
|
|
|
|
|
sensor.addEventListener('reading', () => {
|
|
|
|
|
// Apply the sensor's quaternion to the vector
|
|
|
|
|
orientation = new THREE.Quaternion(...sensor.quaternion);
|
|
|
|
|
// Normalize the quaternion
|
|
|
|
|
orientation.normalize;
|
|
|
|
|
const orientation = new THREE.Quaternion(...sensor.quaternion).normalize();
|
|
|
|
|
// Set the initial orientation if it's not set already
|
|
|
|
|
calibrate();
|
|
|
|
|
currentDirection = scene.up.clone().applyQuaternion(orientation);
|
|
|
|
|
if (!calibratedDirection) {
|
|
|
|
|
calibratedDirection = currentDirection;
|
|
|
|
|
console.log("cal", calibratedDirection);
|
|
|
|
|
}
|
|
|
|
|
relativeDirection = calibratedDirection.clone().sub(currentDirection).normalize();
|
|
|
|
|
const relativeOrientation = new THREE.Quaternion().setFromUnitVectors(calibratedDirection, currentDirection);
|
|
|
|
|
render(relativeOrientation);
|
|
|
|
|
// Profiling
|
|
|
|
|
let currTime = new Date().getTime()
|
|
|
|
|
let currTime = new Date().getTime();
|
|
|
|
|
if (sampleSec < currTime - 1000) {
|
|
|
|
|
console.log("Samples: " + sampleCount)
|
|
|
|
|
console.log("Samples:", sampleCount)
|
|
|
|
|
sampleCount = 0;
|
|
|
|
|
sampleSec = currTime;
|
|
|
|
|
}
|
|
|
|
|
else { sampleCount++; }
|
|
|
|
|
sampleTime = currTime;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Get the button element
|
|
|
|
|
const checkbox = document.getElementById('gyro') as HTMLInputElement;
|
|
|
|
|
console.log("checkboxgotted: " + checkbox)
|
|
|
|
|
|
|
|
|
|
// Check if the button was found
|
|
|
|
|
if (checkbox) {
|
|
|
|
|
// Add a click event listener to the button
|
|
|
|
@ -262,15 +178,13 @@ if (window.AbsoluteOrientationSensor) {
|
|
|
|
|
if (!this.checked) {
|
|
|
|
|
sensor.stop();
|
|
|
|
|
console.log("stopped");
|
|
|
|
|
orientation = new THREE.Quaternion();
|
|
|
|
|
fps = 0;
|
|
|
|
|
initialOrientation = null;
|
|
|
|
|
orientCursor();
|
|
|
|
|
render();
|
|
|
|
|
render(null);
|
|
|
|
|
} else {
|
|
|
|
|
// Otherwise, start the sensor
|
|
|
|
|
sensor.start();
|
|
|
|
|
console.log("started");
|
|
|
|
|
calibratedDirection = null;
|
|
|
|
|
fps = setFPS;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
@ -279,9 +193,8 @@ if (window.AbsoluteOrientationSensor) {
|
|
|
|
|
console.log(checkbox)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Start the animation loop
|
|
|
|
|
animate();
|
|
|
|
|
render();
|
|
|
|
|
// Render the first frame
|
|
|
|
|
render(null);
|
|
|
|
|
} else {
|
|
|
|
|
// Log a message to the console if AbsoluteOrientationSensor is not supported
|
|
|
|
|
console.log('AbsoluteOrientationSensor is not supported in this browser.');
|
|
|
|
|