Compare commits

..

3 Commits

Author SHA1 Message Date
rc 579506e4c5 Fix port 2022-03-05 15:31:22 +01:00
rc f0d95ecb9d disable console log of osc messages and debug set to false 2022-03-05 13:32:05 +01:00
rc 198bbf69cc Calibrate global reference with btn1 2022-03-05 13:23:30 +01:00
12 changed files with 90 additions and 4698 deletions

4
.gitignore vendored
View File

@ -1,5 +1 @@
node_modules
.~*~
.*~undo-tree~
.~lock*#
.*.swp

View File

@ -4,22 +4,6 @@ OSC controlled visual (used with motion controller)
Also see https://git.kompot.si/g1smo/pifcamp-2021
* Running
0. Install dependencies
`npm i`
1. Serial port
`node server.js /dev/ttyUSB0 115200`
2. Bluetooth
`node server.js /dev/rfcomm0 115200`
3. WiFi
`node server.js`
(wait for it)
* older prototypes
- https://kreten.si/spin/
- https://kreten.si/spin-color/

90
anim.js
View File

@ -38,13 +38,8 @@ var rotacijaX = 0;
var rotacijaY = 0;
var rotacijaZ = 0;
var crotacijaX = 0.000;
var crotacijaY = 0.000;
var crotacijaZ = 0.000;
// Premik obstojecih barv
var zamikBarve = 0.01;
var barvapuls = 10;
// Zamik pri novem objektu
var barva_mod = 0.003;
@ -52,14 +47,16 @@ var saturacija = 1;
var svetlost = 0.4;
// Rotiranje kamere
var qKamera = new THREE.Quaternion();
var kameraX = 0;
var kameraY = 0;
var kameraZ = 0;
// Quaternioni za rotacijo in kalibracijo
var qWW = new THREE.Quaternion();
var qWWo = new THREE.Quaternion();
var qWWd = new THREE.Quaternion();
var qObj = new THREE.Quaternion();
var qStart = new THREE.Quaternion();
var qWW = new THREE.Quaternion(-1, 0, 0, 0);
var qWWo = new THREE.Quaternion(-1, 0, 0, 0);
var qWWd = new THREE.Quaternion(-1, 0, 0, 0);
var qObj = new THREE.Quaternion(-1, 0, 0, 0);
var qStart = new THREE.Quaternion(-1, 0, 0, 0);
var calibrate = true;
var reset = false;
@ -88,8 +85,6 @@ renderer.setSize(window.innerWidth, window.innerHeight);
// Črno ozadje
renderer.setClearColor(0x000000, 1);
//var pivot = new THREE.Group();
//scene.add( pivot );
@ -112,13 +107,8 @@ function render () {
function modulirajParametre() {
// Vsi gumbi? => RESET
if ((keysPressed[0] + keysPressed[1] + keysPressed[2] + keysPressed[3]) === 4 && !reset) {
setTimeout(() => {
if ((keysPressed[0] + keysPressed[1] + keysPressed[2] + keysPressed[3]) === 4) {
setTimeout(() => {
window.location.reload()
}, 1000);
}
}, 1000)
reset = true;
window.location.reload()
}
// Posodobi kvaternion polozaja kontrolerja
@ -131,32 +121,20 @@ function modulirajParametre() {
}
// Rotiranje manualno (z rocnimi gibi "iz sredine")
if (keysPressed[0]) {
if (keysPressed[3]) {
var k = objekti.slice(-1)[0];
qObj.multiply(qWWd);
k.quaternion.multiply(qWWd);
}
if (keysPressed[1]) {
if (keysPressed[2]) {
drotacijaX += qWWd.x / 10;
drotacijaY += qWWd.y / 10;
drotacijaZ += qWWd.z / 10;
}
if (keysPressed[2]) {
crotacijaX += qWWd.x / 30;
//crotacijaY += qWWd.y / 30;
crotacijaZ += qWWd.z / 30;
barvapuls += qWWd.y;
}
if (keysPressed[3]) {
width *= 1 + (dqX / 3);
barva_mod += (dqZ / 1000);
obj_limit *= 1 - dqY;
}
if (kbdPressed['c']) {
crotacijaX *= 0.9;
crotacijaY *= 0.9;
crotacijaZ *= 0.9;
if (keysPressed[0]) {
width *= 1 + dqX;
barva_mod += (dqZ / 100);
obj_limit *= 1 + (dqY);
}
}
@ -178,8 +156,7 @@ function objAnim() {
// Funkcija za dodajanje novih objektov
function addObj(w, h) {
var col = new THREE.Color();
//col.setHSL(stevec * barva_mod, saturacija, svetlost);
col.setHSL(stevec * barva_mod, saturacija, (Math.sin(stevec/barvapuls) / 6) + 0.3);
col.setHSL(stevec * barva_mod, saturacija, svetlost);
var mat = new THREE.LineBasicMaterial({
color: col
@ -203,7 +180,6 @@ function addObj(w, h) {
var obj = new THREE.Line(geo, mat, THREE.LineSegments);
scene.add(obj);
//pivot.add(obj);
obj.setRotationFromQuaternion(qObj);
// Pocisti za seboj
@ -215,14 +191,27 @@ function addObj(w, h) {
}
};
qK = new THREE.Quaternion()
var xAksa = new THREE.Vector3(0, 1, 0);
function camRotate () {
//scene.setRotationFromQuaternion(qKamera)
scene.rotation.x += crotacijaX
scene.rotation.y += crotacijaY
scene.rotation.z += crotacijaZ
}
// rotiraj po z osi
camera.translateX(kameraX);
camera.translateZ(odmik_kamere - Math.sqrt(Math.pow(odmik_kamere, 2) + Math.pow(kameraX, 2)));
/*
camera.translateY(kameraY);
camera.translateX(odmik_kamere - Math.sqrt(Math.pow(odmik_kamere, 2) + Math.pow(kameraY, 2)));
camera.translateZ(kameraZ);
camera.translateX(odmik_kamere - Math.sqrt(Math.pow(odmik_kamere, 2) + Math.pow(kameraZ, 2)));
*/
/*
camera.position.x = Math.sin((stevec % 10) / 10) * cam_rot_offset;
camera.position.y = Math.cos((stevec % 10) / 10) * cam_rot_offset;
*/
camera.lookAt(scene.position);
};
// Inicializiraj
document.onreadystatechange = function () {
@ -246,12 +235,11 @@ function getVal(msg) {
return msg.value;
}
const kbdPressed = {
kbdPressed = {
a: false,
s: false,
d: false,
f: false,
c: false
f: false
};
window.addEventListener('keydown', (e) => {

4282
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,6 @@
"description": "epilepsija",
"dependencies": {
"express": "^4.17.1",
"midi": "^2.0.0",
"nodemon": "^2.0.12",
"nouislider": "14.6.2",
"osc": "^2.4.2",

View File

@ -1,134 +0,0 @@
// Zacetek / konec
Server.local.boot;
Server.local.quit;
s.boot;
s.stop;
// Server -> Boot /// Ctrl+B
{SinOsc.ar}.play; // Shift+Enter evalvira
// Ctrl + . ustavi zvok!
// Start/stop prek spremenljivke
x = {SinOsc.ar}.play;
x.free;
// HELP: shift+ctrl+D
// recimo ugen
{SinOsc.ar(SinOsc.kr(1, 0, 1, 1), 0, 1, 0)}.play
{SinOsc.ar(520, 0, SinOsc.ar(3, 0.75, add: 1, phase: 0))}.play;
{VarSaw.ar(42, 0, SinOsc.ar(2, 0.75, add: 1, phase: 0))}.play;
{SinOsc.ar(32, 0, VarSaw.kr(3, 0.75, add: 1, phase: 0))}.play;
{SinOsc.ar(100, )}.play
// Kurzor na keyword in Ctrl+d odpre help zanj
(
{SinOsc.ar(100,)}.play;
{SinOsc.ar(100, 3.14)}.play;
)
()
(
SynthDef.new(\kFaza, {
var a = SinOsc.ar(100);
var b = SinOsc.ar(100, 3.14);
Out.ar(0, a);
Out.ar(1, b);
}).add;
)
(
SynthDef.new(\faza, {
var a = SinOsc.ar(100);
var b = SinOsc.ar(100);
Out.ar(0, a);
Out.ar(1, b);
}).add;
)
s = Synth.new(\kFaza);
v = Synth.new(\faza);
z.set(\f, 80);
z.set(\f, 200, \amp, 0.5);
NetAddr.langPort;
a= 0;
b= 0;
c= 0;
d= 0;
// WW
// Receiver function
(
SynthDef.new(\slOSC, {
// Najprej argumenti, potem variable
arg f=0, ampOsc=0, ch=0, off=0;
var so;
so = SinOsc.ar(f, off, SinOsc.kr(ampOsc));
Out.ar(ch, so);
}).add;
a = Synth.new(\slOSC);
b = Synth.new(\slOSC);
c = Synth.new(\slOSC);
d = Synth.new(\slOSC);
s = [a, b, c, d];
OSCFunc({
arg msg, time, addr, recvPort;
//[msg, time, addr, recvPort].postln;
~gX = msg[1] * 100;
~gY = msg[2] / 3;
}, '/euler', n);
OSCFunc({
arg msg, time, addr, recvPort;
//[msg, time, addr, recvPort].postln;
4.do({
arg i;
if (msg[i + 1] == 1.0) {
s[i].set(\f, ~gX);
s[i].set(\ampOsc, ~gY);
s[i].set(\off, ~gZ);
}
});
}, '/keys', n);
)
// ENDWW
(
w = {
arg noiseHz = 2.5;
var f, sig, amp;
// Med 200 in 1000 Hz
//f = LFNoise0.kr(8, 400, 600);
// f = LFNoise0.kr(8).range(200, 1000)
f = LFNoise0.kr(noiseHz).exprange(300, 600);
amp = LFNoise1.kr(9).exprange(0.2, 1);
sig = SinOsc.ar(f) * amp;
}.play;
)
w.set(\noiseHz, 48);
w.set(\noiseHz, exprand(260, 400));
w.free;

View File

@ -1,57 +0,0 @@
// Zacetek / konec
s.boot;
s.stop;
// Server -> Boot /// Ctrl+B
// HELP: shift+ctrl+D
// recimo ugen
NetAddr.langPort;
(
SynthDef.new(\slOSC, {
// Najprej argumenti, potem variable
arg f=440, ampOsc=0, ch=0, off=0;
var so;
so = SinOsc.ar(f, off, SinOsc.kr(ampOsc));
Out.ar(ch, so);
}).add;
s = [
Synth.new(\slOSC),
Synth.new(\slOSC),
Synth.new(\slOSC),
Synth.new(\slOSC)
];
OSCFunc({
arg msg, time, addr, recvPort;
//[msg, time, addr, recvPort].postln;
~gX = msg[1] * 100;
~gY = msg[2] / 3;
~gZ = msg[3] / 5;
}, '/eulerDiff', n);
OSCFunc({
arg msg, time, addr, recvPort;
msg.postln;
}, '/euler', n);
OSCFunc({
arg msg, time, addr, recvPort;
//[msg, time, addr, recvPort].postln;
4.do({
arg i;
if (msg[i + 1] == 1.0) {
s[i].get(\f, {arg f; s[i].set(\f, f + ~gX)});
s[i].get(\ampOsc, {arg ao; s[i].set(\ampOsc, ao + ~gY)});
s[i].get(\off, {arg o; s[i].set(\off, o + ~gZ)});
}
});
}, '/keys', n);
)

View File

@ -1,70 +0,0 @@
// Zacetek / konec
s.boot;
s.stop;
// Server -> Boot /// Ctrl+B
// HELP: shift+ctrl+D
// recimo ugen
NetAddr.langPort;
(
(
SynthDef.new(\slOSC, {
// Najprej argumenti, potem variable
arg f=120, ampOsc=1, ch=0, off=1;
var so;
so = SinOsc.ar(f, off, SinOsc.kr(ampOsc));
Out.ar(ch, so);
}).add);
s = [
Synth.new(\slOSC),
Synth.new(\slOSC, [\ampOsc, 1.5]),
Synth.new(\slOSC, [\ampOsc, 3]),
Synth.new(\slOSC, [\ampOsc, 4])
];
OSCFunc({
arg msg, time, addr, recvPort;
//[msg, time, addr, recvPort].postln;
~gX = msg[1];
~gY = msg[2];
~gZ = msg[3];
}, '/eulerDiff', n);
OSCFunc({
arg msg, time, addr, recvPort;
msg.postln;
}, '/euler', n);
OSCFunc({
arg msg, time, addr, recvPort;
//[msg, time, addr, recvPort].postln;
/*
if (msg[0]+msg[1]+msg[2]+msg[3] == 4.0) {
4.do({
arg i;
if (msg[i + 1] == 1.0) {
s[i].set(\f, 100);
s[i].set(\ampOsc, 1);
s[i].set(\off, 1);
}
});
} else {*/
4.do({
arg i;
if (msg[i + 1] == 1.0) {
s[i].get(\f, {arg f; s[i].set(\f, f * (1 + ~gX))});
s[i].get(\ampOsc, {arg ao; s[i].set(\ampOsc, ao * (1 + ~gY))});
s[i].get(\off, {arg o; s[i].set(\off, o * (1 + ~gZ))});
}
});
//}
}, '/keys', n);
)

View File

@ -64,7 +64,7 @@ o = OSCFunc({
~oX = ~gX;
~oY = ~gY;
~oZ = ~gZ;
msg.postln;
//[msg, time, addr, recvPort].postln;
~gW = msg[1];
~gZ = msg[2];
@ -92,11 +92,11 @@ o = OSCFunc({
~euler = ~quaternionToEuler.([~dgW, ~dgX, ~dgY, ~dgZ]);
~euler.postln;
}, '/quaternion', n);
}, '/quaternion/', n);
)
// ENDWW
OSCFunc.trace(false);
OSCFunc.trace(true);

123
server.js
View File

@ -1,36 +1,11 @@
// Which port do I send OSC messages to? (SupperCollider, ...)
const OSCPORT = 57120;
// Which port do I listen to (for visuals, calibration)
const PORT = 6676
// Do we have a problem, shall we debug?
const DEBUG = {
osc: true,
udp: false,
midi: true
}
// MIDI out
const MIDI = true
const express = require('express')
const http = require('http')
const WebSocket = require('ws')
const osc = require('osc')
const readline = require('readline')
const fs = require('fs')
const midi = require('midi')
const port = 6676
// Vzemi iz argumenta
const tty = process.argv[2]
@ -55,19 +30,11 @@ const include_files = [
const app = express();
const server = http.Server(app);
const DEBUG = true
// Odprti serijski OSC link
let scon = null
let mo = null
if (MIDI) {
// Midi port
mo = new midi.Output()
//mo.getPortCount()
//mo.getPortName(0)
//mo.openPort(0)
mo.openVirtualPort("kegel")
}
function openSerial() {
console.log('opening ', tty, baudrate)
@ -77,6 +44,7 @@ function openSerial() {
autoOpen: true,
useSLIP: true
})
scon.open()
scon.on('open', e => {
console.log('serial connection opened')
@ -88,21 +56,18 @@ function openSerial() {
})
scon.on('close', e => {
console.warn('serial connection closed, restarting in 1 second')
setTimeout(openSerial, 1000)
})
// Arduino OSC gre v web
scon.on('message', msg => {
// Debug incoming osc
if (DEBUG.osc) {
if (DEBUG) {
console.log('osc msg', msg)
}
sendAll(msg, null, null, osclients)
})
scon.open()
if (scon._closeCode) {
scon = null
console.log('restarting serial connection')
@ -126,14 +91,6 @@ app.get('/test', (req, res) => {
res.sendFile(__dirname + '/test.html');
});
// Hydra inclusion
app.get('/hydra', function(req, res) {
res.sendFile(__dirname + '/hydra-osc-main/index.html');
});
app.get('/lib/osc.min.js', function(req, res) {
res.sendFile(__dirname + '/hydra-osc-main/lib/osc.min.js');
});
let settings = {};
app.get('/settings', function(req, res) {
res.send(settings);
@ -145,7 +102,7 @@ include_files.map(function(file) {
});
});
server.listen(PORT, () => console.log('listening on *:' + PORT))
server.listen(port, () => console.log('listening on *:' + port))
// Websocket init
const wss = new WebSocket.Server({ server })
@ -153,18 +110,17 @@ const wss = new WebSocket.Server({ server })
// Relay multicast to websockets
// @TODO still sends to supercollider? Do we need two sockets?
/*
var dgram = require('dgram');
var sss = dgram.createSocket('udp4');
sss.on('listening', () => {
sss.addMembership('224.0.1.9');
})
sss.bind(6696, '224.0.1.9');
*/
//var dgram = require('dgram');
//var sss = dgram.createSocket('udp4');
//sss.on('listening', () => {
// sss.addMembership('224.0.1.9');
//})
//sss.bind(57120);
const scudp = new osc.UDPPort({
remotePort: OSCPORT
//socket: sss
remotePort: 57121,
localPort: 57100
})
scudp.on('open', () => {
@ -172,10 +128,7 @@ scudp.on('open', () => {
})
scudp.on('message', (msg) => {
if (DEBUG.udp) {
console.log('got UDP msg', msg);
}
console.log('got UDP msg', msg);
osclients.forEach( client => {
if (client) {
//console.log("sending", msg, info)
@ -222,10 +175,10 @@ function eulerFromQuaternion(quaternion) {
}
const sendAll = (msg, info, oscWS, osclients) => {
// Reset euler rotation to 0
if (msg.address == '/keys') {
if (msg.args[0] && msg.args[1] && msg.args[2] && msg.args[3]) {
eulerRotation = [0, 0, 0]
if (msg.args[0] == 1) {
eulerRotation = [0, 0, 0];
console.log("EULER ROTATION RESET");
}
}
@ -255,53 +208,31 @@ const sendAll = (msg, info, oscWS, osclients) => {
})
if (scudp) {
if (DEBUG.udp) {
console.log("UDP SEND", msg)
}
console.log("SENDING UDP", msg)
scudp.send(msg)
}
}
let osclients = []
const osclients = []
wss.on('connection', function (ws) {
console.log('new client connection', ws._socket.remoteAddress)
let oscWS = new osc.WebSocketPort({
socket: ws
console.log('new client connection')
const oscWS = new osc.WebSocketPort({
socket: ws,
metadata: false
});
// Vsi OSC sem grejo naprej na kliente OSC
oscWS.on('message', ({ address, args}, info) => {
console.log('fasal sem', address, args)
if (MIDI) {
if (address == '/midi') {
if (DEBUG.midi) {
console.log('midi SEND', args)
}
mo.send(args)
}
}
oscWS.on('packet', (packet, info) => {
// Broadcast adjust msg
const [address, args] = packet
sendAll({ address, args}, info, oscWS, osclients)
})
oscWS.on('error', error => {
console.warn('Ignoring invalid OSC')
console.warn(error)
oscWS.close()
osclients = osclients.filter(ws => ws !== oscWS)
})
osclients.push(oscWS)
oscWS.on('close', () => {
console.log('closing socket', oscWS.socket.remoteAddress)
osclients = osclients.filter(ws => ws !== oscWS)
})
})
// Zapri midi
/*
if (MIDI && mo) {
mo.closePort()
}
*/

View File

@ -65,8 +65,9 @@ scene.add(skupina);
// Quaternioni za rotacijo in kalibracijo
var qWW = new THREE.Quaternion();
var qObj = new THREE.Quaternion();
var qStart = new THREE.Quaternion();
var qObj = new THREE.Quaternion(-1, 0, 0, 0);
var qStart = new THREE.Quaternion(-1, 0, 0, 0);
var qCalibrate = new THREE.Quaternion();
var reset = false;