gravitacija-perspektive/danijela.js

245 lines
5.3 KiB
JavaScript

const osc = require('osc')
const midi = require('midi')
const Quat = require('quaternion');
// Stevilke senzorjev
const INDEX_GLAVA = 1
const INDEX_ROKA = 2
const INDEX_BEKAP = 3
// CC kanali za midi mapping (kanal, CC kanal)
const midiKanal = 176;
// CC kanali senzorjev
const midiKanalSenzor = {
1: 20,
2: 21,
3: 22
}
const senzorCCKanal = {
1: 75,
2: 76,
3: 77
}
const senzorCCMute = {
1: 78,
2: 79,
3: 80
}
const senzorCCkalibracija = {
1: 81,
2: 82,
3: 83
}
const DEBUG = {
midi: true,
osc: false
}
// Kalibracijsko izhodisce
const izhodisceQ = {
1: new Quat(),
2: new Quat(),
3: new Quat()
}
const prejsnjiQ = {
1: new Quat(),
2: new Quat(),
3: new Quat()
}
const eulerRotacija = {
1: [0, 0, 0],
2: [0, 0, 0],
3: [0, 0, 0]
}
const senzorCC = {
1: 64,
2: 64,
3: 64
}
let staroVrtenjeZMidi = {
1: 0,
2: 0,
3: 0
};
const muteMidi = {
1: 0,
2: 0,
3: 0
}
// Midi controller input
const mi = new midi.Input()
mi.openVirtualPort("danijela-midi")
mi.on('message', (deltaTime, msg) => {
if (msg[0] === midiKanal) {
if (Object.values(senzorCCKanal).includes(msg[1])) {
const s = Object.values(senzorCCKanal).indexOf(msg[1]) + 1
if (!muteMidi[s]) {
senzorCC[s] = msg[2]
console.log(`senzor ${s}: ${msg[2]}`)
}
} else if (Object.values(senzorCCMute).includes(msg[1])) {
const s = Object.values(senzorCCMute).indexOf(msg[1]) + 1
if (msg[2]) {
console.log(`senzor UNMUTE ${s}`)
muteMidi[s] = false;
} else {
muteMidi[s] = true;
console.log(`senzor MUTE ${s}`)
}
} else if (Object.values(senzorCCkalibracija).includes(msg[1])) {
const s = Object.values(senzorCCkalibracija).indexOf(msg[1]) + 1
izhodisceQ[s] = prejsnjiQ[s].conjugate()
console.log(`senzor KALIBRACIJA ${s}`)
}
}
//console.log(`midi in: ${msg} d: ${deltaTime}`);
/*
if (senzorGlaveCC === 0 && senzorRokeCC === 0) {
console.log('===== KALIBRACIJA! =====')
let izhodisceQGlave = prejsnjiQGlave.conjugate()
let izhodisceQRoke = prejsnjiQRoke.conjugate()
}
*/
})
// Razpon za pospeskomerje
const accMin = -8000
const accMax = 8000
// Povezava na wavey wind
const ip = process.argv[2]
const oscWS = new osc.WebSocketPort({
url: `ws://${ip}:6676`,
metadata: false
})
oscWS.on('ready', () => {
console.log(`Povezan sem na ${ip}`)
/*
PING test!
setInterval(() => {
console.log('ping')
oscWS.send({ address: '/ping', args: [true]})
}, 500)
*/
})
function posljiMidi(kanal, vrednost, jakost) {
if (DEBUG.midi) {
console.log('MIDI', kanal, vrednost, jakost)
}
oscWS.send({
address: '/midi',
args: [kanal, vrednost, jakost]
})
}
function posljiMidiCC(kanal, vrednost) {
posljiMidi(midiKanal, kanal, vrednost);
}
//const norm = (val, min, max) => Math.min(1, (val - min) / (max - min))
const norm = (val, min, max) => {
const d = 0 - min;
const r = max - min
return Math.min(1, (Math.max(min, val) + d) / r);
}
const normSin = val => {
return norm(Math.sin(val), -1, 1);
}
const normMidi = (val, min, max) => Math.round(norm(val, min, max) * 127)
const abs = Math.abs;
let cakaj = false;
oscWS.on('message', ({ address, args }) => {
DEBUG.osc && console.log('MSG OSC', address, args.map(x => x.toFixed(4)))
// Wavey Wind sporočila
const re = /\/ww\/0\/ww\/(\d+)\/([a-zA-Z]+)/
const m = address.match(re)
if (m) {
const index = parseInt(m[1])
const addr = m[2]
if (addr == 'euler') {
}
if (addr == 'accel') {
const acX = args[0]
const acY = args[1]
const acZ = args[2]
//console.log(acX, acY, acZ);
// CC sporocila!
/*
posljiMidiCC(20, normMidi(acX, accMin, accMax));
posljiMidiCC(21, normMidi(acY, accMin, accMax));
posljiMidiCC(22, normMidi(acZ, accMin, accMax));
*/
}
if (addr == 'quaternion') {
//console.log('IDX', index)
// Izracunaj spremembo rotacije
const novQ = new Quat({w: args[0], x: args[1], y: args[2], z: args[3]})
const novQC = novQ.mul(izhodisceQ[index])
const qWd = novQC.div(prejsnjiQ[index])
prejsnjiQ[index] = novQC;
const eulerD = qWd.toEuler()
//console.log(index, eulerD)
eulerRotacija[index][0] += eulerD.roll * (senzorCC[index] / 64);
eulerRotacija[index][1] += eulerD.pitch * (senzorCC[index] / 64);
eulerRotacija[index][2] += eulerD.yaw * (senzorCC[index] / 64);
const vrtenjeX = Math.abs(Math.sin(eulerRotacija[index][0]));
/*
posljiMidi(180, 20, Math.round(vrtenjeX * 127));
*/
// Roka dol/gor
const vrtenjeY = Math.abs(Math.sin(eulerRotacija[index][1]));
//posljiMidi(180, 20, Math.round(vrtenjeY * 127));
//posljiMidi(181, 20, Math.round(vrtenjeY * 127));
// Vrtenje levo/desno (stegnjena roka)
//console.log(eulerRotacijaGlave)
const vrtenjeZ = normSin(eulerRotacija[index][2])
//console.log(vrtenjeZ)
const vrtenjeZmidi = Math.round(vrtenjeZ * 127)
//console.log('vrtenjeZ', vrtenjeZmidi)
//console.log('cmp', vrtenjeZmidi, staroVrtenjeZmidi);
//console.log(vrtenjeZmidi);
if (vrtenjeZmidi !== staroVrtenjeZMidi[index]
&& !muteMidi[index]) {
posljiMidi(182, midiKanalSenzor[index], vrtenjeZmidi)
staroVrtenjeZMidi[index] = vrtenjeZmidi
}
}
}
})
oscWS.open()