Add gyro and webgl demo
This commit is contained in:
parent
611cee6f40
commit
1635eb9ede
43
cg/webgl/index.html
Normal file
43
cg/webgl/index.html
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
background-color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view {
|
||||||
|
display: flex;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-aspect-ratio: 1) {
|
||||||
|
.view-canvas {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-aspect-ratio: 1) {
|
||||||
|
.view-canvas {
|
||||||
|
width: 100vh;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="view">
|
||||||
|
<canvas id="canvas" class="view-canvas" width="64" height="64"></canvas>
|
||||||
|
</div>
|
||||||
|
<script src="./m4.js"></script>
|
||||||
|
<script src="./webgl.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
1467
cg/webgl/m4.js
Normal file
1467
cg/webgl/m4.js
Normal file
File diff suppressed because it is too large
Load Diff
323
cg/webgl/webgl.js
Normal file
323
cg/webgl/webgl.js
Normal file
@ -0,0 +1,323 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const v3 = {
|
||||||
|
add: function (v1, v2) {
|
||||||
|
return [v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]];
|
||||||
|
},
|
||||||
|
normalize: function (v) {
|
||||||
|
return v3.scale(v, 1 / v3.norm(v));
|
||||||
|
},
|
||||||
|
norm: function (v) {
|
||||||
|
return Math.sqrt(Math.pow(v[0], 2) + Math.pow(v[1], 2) + Math.pow(v[2], 2));
|
||||||
|
},
|
||||||
|
scale: function (v, f) {
|
||||||
|
return [v[0] * f, v[1] * f, v[2] * f];
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function getGyroPermission(){
|
||||||
|
if(!DeviceOrientationEvent.requestPermission){
|
||||||
|
return Promise.resolve("granted")
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return DeviceOrientationEvent.requestPermission()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createShader(gl, type, source) {
|
||||||
|
const shader = gl.createShader(type);
|
||||||
|
gl.shaderSource(shader, source);
|
||||||
|
gl.compileShader(shader);
|
||||||
|
|
||||||
|
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||||
|
throw new Error(gl.getShaderInfoLog(shader));
|
||||||
|
}
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createProgram(gl, shaders) {
|
||||||
|
const program = gl.createProgram();
|
||||||
|
for (const shader of shaders) {
|
||||||
|
gl.attachShader(program, shader);
|
||||||
|
}
|
||||||
|
gl.linkProgram(program);
|
||||||
|
|
||||||
|
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
||||||
|
throw new Error(gl.getProgramInfoLog(program));
|
||||||
|
}
|
||||||
|
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initIsocahedron(vertices, elements) {
|
||||||
|
const t = 1 + Math.sqrt(5) / 2;
|
||||||
|
|
||||||
|
vertices.push(
|
||||||
|
v3.normalize([-1, t, 0]),
|
||||||
|
v3.normalize([1, t, 0]),
|
||||||
|
v3.normalize([-1, -t, 0]),
|
||||||
|
v3.normalize([1, -t, 0]),
|
||||||
|
v3.normalize([0, -1, t]),
|
||||||
|
v3.normalize([0, 1, t]),
|
||||||
|
v3.normalize([0, -1, -t]),
|
||||||
|
v3.normalize([0, 1, -t]),
|
||||||
|
v3.normalize([t, 0, -1]),
|
||||||
|
v3.normalize([t, 0, 1]),
|
||||||
|
v3.normalize([-t, 0, -1]),
|
||||||
|
v3.normalize([-t, 0, 1]),
|
||||||
|
);
|
||||||
|
|
||||||
|
elements.push(
|
||||||
|
0, 11, 5,
|
||||||
|
0, 5, 1,
|
||||||
|
0, 1, 7,
|
||||||
|
0, 7, 10,
|
||||||
|
0, 10, 11,
|
||||||
|
1, 5, 9,
|
||||||
|
5, 11, 4,
|
||||||
|
11, 10, 2,
|
||||||
|
10, 7, 6,
|
||||||
|
7, 1, 8,
|
||||||
|
3, 9, 4,
|
||||||
|
3, 4, 2,
|
||||||
|
3, 2, 6,
|
||||||
|
3, 6, 8,
|
||||||
|
3, 8, 9,
|
||||||
|
4, 9, 5,
|
||||||
|
2, 4, 11,
|
||||||
|
6, 2, 10,
|
||||||
|
8, 6, 7,
|
||||||
|
9, 8, 1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMidpoint(vertices, midpoints, i0, i1) {
|
||||||
|
const k = `${i0}_${i1}`;
|
||||||
|
if (midpoints.has(k)) {
|
||||||
|
return vertices[midpoints[k]];
|
||||||
|
}
|
||||||
|
|
||||||
|
const p0 = vertices[i0];
|
||||||
|
const p1 = vertices[i1];
|
||||||
|
|
||||||
|
const midpoint = v3.normalize(v3.scale(v3.add(p0, p1), 0.5));
|
||||||
|
const midpointIndex = vertices.length;
|
||||||
|
midpoints.set(k, midpointIndex);
|
||||||
|
vertices.push(midpoint);
|
||||||
|
return midpointIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
function subdivideIsocahedron(vertices, elements, midpoints) {
|
||||||
|
const newElements = [];
|
||||||
|
for (let i = 0; i < elements.length; i += 3) {
|
||||||
|
const p0 = elements[i];
|
||||||
|
const p1 = elements[i + 1];
|
||||||
|
const p2 = elements[i + 2];
|
||||||
|
const m0 = getMidpoint(vertices, midpoints, p0, p1);
|
||||||
|
const m1 = getMidpoint(vertices, midpoints, p1, p2);
|
||||||
|
const m2 = getMidpoint(vertices, midpoints, p2, p0);
|
||||||
|
|
||||||
|
newElements.push(
|
||||||
|
m0, m1, m2,
|
||||||
|
p0, m0, m2,
|
||||||
|
p1, m1, m0,
|
||||||
|
p2, m2, m1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return newElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateIsocahedron() {
|
||||||
|
const r = 1;
|
||||||
|
const n = 3;
|
||||||
|
const tau = 2 * Math.PI;
|
||||||
|
|
||||||
|
const vertices = [];
|
||||||
|
const normals = [];
|
||||||
|
let elements = [];
|
||||||
|
|
||||||
|
initIsocahedron(vertices, elements);
|
||||||
|
const midpoints = new Map();
|
||||||
|
for (let i = 0; i < 1; i++) {
|
||||||
|
elements = subdivideIsocahedron(vertices, elements, midpoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
vertices: [].concat(...vertices),
|
||||||
|
// as we want to approximate a unit sphere, all the vertices are unit vectors
|
||||||
|
normals: [].concat(...vertices),
|
||||||
|
elements
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const canvas = document.querySelector("#canvas");
|
||||||
|
const gl = canvas.getContext("webgl");
|
||||||
|
|
||||||
|
const vertexShader = createShader(gl, gl.VERTEX_SHADER, `
|
||||||
|
attribute vec4 a_position;
|
||||||
|
attribute vec3 a_normal;
|
||||||
|
|
||||||
|
uniform mat4 u_matrix;
|
||||||
|
uniform mat4 u_world;
|
||||||
|
uniform mat4 u_worldIT;
|
||||||
|
uniform vec3 u_light;
|
||||||
|
uniform vec3 u_camera;
|
||||||
|
|
||||||
|
varying vec3 v_normal;
|
||||||
|
varying vec3 v_surfaceToLight;
|
||||||
|
varying vec3 v_surfaceToView;
|
||||||
|
varying vec3 v_pos;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = u_matrix * a_position;
|
||||||
|
v_pos = a_position.rgb;
|
||||||
|
v_pos.r = abs(v_pos.r);
|
||||||
|
v_pos.g = abs(v_pos.g);
|
||||||
|
v_pos.b = abs(v_pos.b);
|
||||||
|
|
||||||
|
v_normal = mat3(u_worldIT) * a_normal;
|
||||||
|
|
||||||
|
vec3 surfaceWorldPos = (u_world * a_position).xyz;
|
||||||
|
v_surfaceToLight = u_light - surfaceWorldPos;
|
||||||
|
|
||||||
|
v_surfaceToView = u_camera - surfaceWorldPos;
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, `
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
varying vec3 v_normal;
|
||||||
|
varying vec3 v_surfaceToLight;
|
||||||
|
varying vec3 v_surfaceToView;
|
||||||
|
varying vec3 v_pos;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec3 halfVector = normalize(normalize(v_surfaceToLight) + normalize(v_surfaceToView));
|
||||||
|
|
||||||
|
float ka = 0.3;
|
||||||
|
float kd = 0.8;
|
||||||
|
float ks = 0.6;
|
||||||
|
float gamma = 100.0;
|
||||||
|
|
||||||
|
gl_FragColor = vec4(v_pos, 1.0);
|
||||||
|
gl_FragColor.rgb *= ka + (kd * dot(normalize(v_normal), normalize(v_surfaceToLight)));
|
||||||
|
gl_FragColor.rgb += ks * pow(max(0.0, dot(normalize(v_normal), halfVector)), gamma);
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
const program = createProgram(gl, [vertexShader, fragmentShader]);
|
||||||
|
|
||||||
|
const {vertices, normals, elements} = generateIsocahedron();
|
||||||
|
|
||||||
|
const positionBuffer = gl.createBuffer();
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
|
||||||
|
|
||||||
|
const normalBuffer = gl.createBuffer();
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normals), gl.STATIC_DRAW);
|
||||||
|
|
||||||
|
const elementBuffer = gl.createBuffer();
|
||||||
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
|
||||||
|
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(elements), gl.STATIC_DRAW);
|
||||||
|
|
||||||
|
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
|
||||||
|
|
||||||
|
gl.enable(gl.DEPTH_TEST);
|
||||||
|
gl.enable(gl.CULL_FACE);
|
||||||
|
|
||||||
|
const positionAttribLocation = gl.getAttribLocation(program, "a_position");
|
||||||
|
const normalAttribLocation = gl.getAttribLocation(program, "a_normal");
|
||||||
|
|
||||||
|
const matrixLocation = gl.getUniformLocation(program, "u_matrix");
|
||||||
|
const worldMatrixLocation = gl.getUniformLocation(program, "u_world");
|
||||||
|
const worldITMatrixLocation = gl.getUniformLocation(program, "u_worldIT");
|
||||||
|
const lightVecLocation = gl.getUniformLocation(program, "u_light");
|
||||||
|
const cameraVecLocation = gl.getUniformLocation(program, "u_camera");
|
||||||
|
|
||||||
|
const aspectRatio = gl.canvas.width / gl.canvas.height;
|
||||||
|
const zNear = 1;
|
||||||
|
const zFar = 2000;
|
||||||
|
|
||||||
|
const rotation = [0, 0, 0];
|
||||||
|
|
||||||
|
gl.useProgram(program);
|
||||||
|
|
||||||
|
gl.enableVertexAttribArray(positionAttribLocation);
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
|
||||||
|
gl.vertexAttribPointer(
|
||||||
|
positionAttribLocation,
|
||||||
|
3, // element size
|
||||||
|
gl.FLOAT,
|
||||||
|
false, // normalize
|
||||||
|
0, // stride
|
||||||
|
0 // offset
|
||||||
|
);
|
||||||
|
|
||||||
|
gl.enableVertexAttribArray(normalAttribLocation);
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
|
||||||
|
gl.vertexAttribPointer(normalAttribLocation, 3, gl.FLOAT, false, 0, 0);
|
||||||
|
|
||||||
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
|
||||||
|
|
||||||
|
function drawScene () {
|
||||||
|
window.requestAnimationFrame(drawScene);
|
||||||
|
|
||||||
|
const t = performance.now() / 1000;
|
||||||
|
|
||||||
|
const lightPos = [10, 10, 30];
|
||||||
|
const projectionMatrix = m4.perspective(Math.PI / 180 * 60, aspectRatio, zNear, zFar);
|
||||||
|
const cameraPos = [0, 0, 30];
|
||||||
|
const target = [0, 0, 0];
|
||||||
|
const up = [0, 1, 0];
|
||||||
|
const cameraMatrix = m4.lookAt(cameraPos, target, up);
|
||||||
|
const viewMatrix = m4.inverse(cameraMatrix);
|
||||||
|
let worldMatrix = m4.identity();
|
||||||
|
worldMatrix = m4.xRotate(worldMatrix, rotation[0]);
|
||||||
|
worldMatrix = m4.yRotate(worldMatrix, rotation[1]);
|
||||||
|
worldMatrix = m4.zRotate(worldMatrix, rotation[2]);
|
||||||
|
worldMatrix = m4.scale(worldMatrix, 12, 12, 12);
|
||||||
|
|
||||||
|
const worldITMatrix = m4.transpose(m4.inverse(worldMatrix));
|
||||||
|
const viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix);
|
||||||
|
const worldViewProjectionMatrix = m4.multiply(viewProjectionMatrix, worldMatrix);
|
||||||
|
|
||||||
|
/*
|
||||||
|
let matrix = projectionMatrix;
|
||||||
|
matrix = m4.translate(matrix, 0, 0, -30);
|
||||||
|
matrix = m4.xRotate(matrix, rotation[0]);
|
||||||
|
matrix = m4.yRotate(matrix, rotation[1]);
|
||||||
|
matrix = m4.zRotate(matrix, rotation[2]);
|
||||||
|
matrix = m4.scale(matrix, 10, 10, 10);
|
||||||
|
*/
|
||||||
|
gl.uniformMatrix4fv(matrixLocation, false, worldViewProjectionMatrix);
|
||||||
|
gl.uniformMatrix4fv(worldMatrixLocation, false, worldMatrix);
|
||||||
|
gl.uniformMatrix4fv(worldITMatrixLocation, false, worldITMatrix);
|
||||||
|
gl.uniform3fv(lightVecLocation, lightPos);
|
||||||
|
gl.uniform3fv(cameraVecLocation, cameraPos);
|
||||||
|
|
||||||
|
gl.clearColor(0, 0, 0, 1);
|
||||||
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
gl.drawElements(
|
||||||
|
gl.TRIANGLES,
|
||||||
|
elements.length, // count
|
||||||
|
gl.UNSIGNED_SHORT,
|
||||||
|
0, // offset
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawScene();
|
||||||
|
|
||||||
|
canvas.addEventListener("click", e => {
|
||||||
|
getGyroPermission()
|
||||||
|
.then(response => {
|
||||||
|
window.addEventListener("deviceorientation", e => {
|
||||||
|
rotation[0] = 2 * (-e.beta / 180 * Math.PI);
|
||||||
|
rotation[1] = 2 * (-e.gamma / 180 * Math.PI);
|
||||||
|
rotation[2] = 2 * (-e.alpha / 180 * Math.PI + Math.PI / 2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
BIN
gyro/AufnahmeLIna.mp3
Normal file
BIN
gyro/AufnahmeLIna.mp3
Normal file
Binary file not shown.
130
gyro/Untitled-1.html
Normal file
130
gyro/Untitled-1.html
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h1>colles gyro dingens</h1>
|
||||||
|
|
||||||
|
<marquee>ich bin der Davidmann2</marquee>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>
|
||||||
|
status
|
||||||
|
</legend>
|
||||||
|
<strong id="status">
|
||||||
|
loading
|
||||||
|
</strong>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>
|
||||||
|
gyro
|
||||||
|
</legend>
|
||||||
|
<strong id="gyro">
|
||||||
|
loading
|
||||||
|
</strong>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>
|
||||||
|
gyro
|
||||||
|
</legend>
|
||||||
|
<strong id="gyro2">
|
||||||
|
loading
|
||||||
|
</strong>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function loadAudioFile(fileName){
|
||||||
|
return (
|
||||||
|
fetch(fileName)
|
||||||
|
.then(response=>{
|
||||||
|
return(response.arrayBuffer())
|
||||||
|
})
|
||||||
|
.then(arrayBuffer=>{
|
||||||
|
return(ctx.decodeAudioData(arrayBuffer))
|
||||||
|
})
|
||||||
|
.then(audioBuffer=>{
|
||||||
|
loaded++
|
||||||
|
document.getElementById("status").innerHTML = "loaded " + loaded + "/" + fileNames.length
|
||||||
|
return(audioBuffer)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const fileNames = ["AufnahmeLIna.mp3", "blatters.mp3"]
|
||||||
|
let buffers = null
|
||||||
|
let loaded = 0
|
||||||
|
Promise.all(fileNames.map(loadAudioFile))
|
||||||
|
.then(audioBuffers=>{
|
||||||
|
document.getElementById("status").innerHTML = "Done loading"
|
||||||
|
buffers = audioBuffers
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let samples = null
|
||||||
|
const ctx = new AudioContext()
|
||||||
|
function playStuff(){
|
||||||
|
console.log("imStuff")
|
||||||
|
if(samples == null){
|
||||||
|
samples = []
|
||||||
|
for(const buffer of buffers){
|
||||||
|
const sample = ctx.createBufferSource()
|
||||||
|
sample.buffer = buffer
|
||||||
|
|
||||||
|
const gain = ctx.createGain()
|
||||||
|
|
||||||
|
sample.connect(gain)
|
||||||
|
gain.connect(ctx.destination)
|
||||||
|
|
||||||
|
sample.start()
|
||||||
|
samples.push({sample:sample, gainNode:gain})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function stopStuff(){
|
||||||
|
for(sample of samples){
|
||||||
|
sample.sample.stop()
|
||||||
|
}
|
||||||
|
samples = null
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function getGyroPermission(){
|
||||||
|
if(!DeviceOrientationEvent.requestPermission){
|
||||||
|
return Promise.resolve("granted")
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return DeviceOrientationEvent.requestPermission()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function initGyro(){
|
||||||
|
//alert(DeviceOrientationEvent.requestPermission())
|
||||||
|
getGyroPermission().then(response => {
|
||||||
|
window.addEventListener("deviceorientation", e => {
|
||||||
|
document.querySelector("#gyro").innerHTML = e.alpha / 360
|
||||||
|
document.querySelector("#gyro2").innerHTML = (e.beta + 180) / 360
|
||||||
|
if(samples != null){
|
||||||
|
samples[0].gainNode.gain.value = e.alpha / 360
|
||||||
|
samples[1].gainNode.gain.value = (e.beta + 180) / 360
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button onclick="playStuff()">PLAY</button>
|
||||||
|
|
||||||
|
<button onclick="stopStuff()">STOP</button>
|
||||||
|
|
||||||
|
<button onclick="initGyro()">START GYRO</button>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
BIN
gyro/blatters.mp3
Normal file
BIN
gyro/blatters.mp3
Normal file
Binary file not shown.
26
gyro/index.html
Normal file
26
gyro/index.html
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<h1>Is it working?</h1>
|
||||||
|
<button id="perm">click me for permissions</button>
|
||||||
|
<div style="color: red" id="disp">lalala</div>
|
||||||
|
<script>
|
||||||
|
document.querySelector("#perm").addEventListener("click", e => {
|
||||||
|
const ac = new AudioContext();
|
||||||
|
const osc = ac.createOscillator();
|
||||||
|
|
||||||
|
osc.type = "square";
|
||||||
|
osc.frequency.setValueAtTime(440, ac.currentTime);
|
||||||
|
osc.connect(ac.destination);
|
||||||
|
osc.start();
|
||||||
|
|
||||||
|
DeviceMotionEvent.requestPermission().then(response => {
|
||||||
|
window.addEventListener("devicemotion", e => {
|
||||||
|
document.querySelector("#disp").innerHTML = Math.round(e.acceleration.x);
|
||||||
|
osc.frequency.setValueAtTime(440 * Math.pow(2, e.acceleration.x / 10), ac.currentTime);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
x
Reference in New Issue
Block a user