Getting started with Android-Processing VR
(EN google-translate)
(PL google-translate)
The strategy here is: Keeping the code short by making an intensive use of the available libraries.
vr002_richtungen
vr002_richtungen.zipimport processing.vr.*; PShape spheres; //Resultat zu Koordinatenrichtungen: // x-Achse zeigt nach rechts // y-Achse zeigt nach oben // z-Achse zeigt nach hinten // eigene Position: z>0, also leicht nach hinten versetzt //Auslesen der Objektmatrix: //Spalten 1..3: Einheitsvektoren des Blick-Koordinatensystems, 4. Spalte Position des Viewers. PMatrix3D eyeMat = new PMatrix3D(); void setup() { fullScreen(STEREO); spheres = createShape(GROUP); float[][] orte = { {1000,0,0}, //rot links von mir {-1000,0,0}, //grün rechts von mir {0,1000,0}, //gelb unter mir {0,-1000,0}, //blau über mir {0,0,1000}, //türkis hinter mir {0,0,-1000} //violett weit vor mir durch weiss verdeckt! }; int[][] farben = { {255,0,0},//rot {0,255,0},//gruen {255,255,0},//gelb {0,0,255}, //blau {0,255,255},//türkis {255,0,255} //violett }; for(int i=0;i<orte.length;i++) { PShape sphere = createShape(SPHERE, 50); sphere.setStroke(false); sphere.setFill(color(farben[i][0],farben[i][1],farben[i][2])); sphere.translate(orte[i][0],orte[i][1],orte[i][2]); spheres.addChild(sphere); } textAlign(CENTER, CENTER); textSize(displayDensity * 36); frameRate(30); } int zzz=0; void draw() { background(0); getEyeMatrix(eyeMat); //Kameramatrix auslesen translate(eyeMat.m03, eyeMat.m13, eyeMat.m23); //Welt in Koordinatenursprung von Kamera setzen. lights(); shape(spheres); eye(); //Transformation realtiv zur Kamera translate(0, 0, 500); //Zielkreis relativ zur Kamera zeichnen noFill(); stroke(255,0,0); ellipse(0, 0, 50, 50); if(zzz%90==0) { println(zzz); //Einheitsvektoren des Kamerasystems in Koordinaten des Inertialsystems ex, ey , ez println("ex=["+nfp(eyeMat.m00,1,3)+","+nfp(eyeMat.m10,1,3)+","+nfp(eyeMat.m20,1,3)+"]"); println("ey=["+nfp(eyeMat.m01,1,3)+","+nfp(eyeMat.m11,1,3)+","+nfp(eyeMat.m21,1,3)+"]"); //ez zeigt in die Blickrichtung! //In Startrichtung nach vorne blicken: ez=[0,0,-1] //nach links blicken: ez=[-1,0,0] //nach rechts blicken: ez=[ 1,0,0] //nach hinten blicken: ez=[ 0,0,1] //nach oben blicken: ez=[ 0,-1,0] //nach unten blicken: ez=[ 0, 1,0] println("ez=["+nfp(eyeMat.m02,1,3)+","+nfp(eyeMat.m12,1,3)+","+nfp(eyeMat.m22,1,3)+"]"); println("pos=["+nfp(eyeMat.m03,1,3)+","+nfp(eyeMat.m13,1,3)+","+nfp(eyeMat.m23,1,3)+"]"); println("ez so anpassen, dass dessn Norm mit den Koordinaten der Spheren übereinstimmt:"); println("ez=["+nfp(eyeMat.m02,1,3)+","+nfp(-eyeMat.m12,1,3)+","+nfp(eyeMat.m22,1,3)+"]"); } zzz++; }
Code 0-1: vr002_richtungen - Positionierung farbiger Bälle auf den Koordinatenachsen zur Orientierung und Ausgabe der Blickrichtung
Bild 0-1: Orientierung des VR-Koordinatensystems.
Die eye-Matrix liefert in den ersten drei Spalten die Einheitsvektoren des "Blickrichtungs-Koordinatensystems".
vr002_puls
vr002_puls.zip
|
import processing.vr.*; import android.media.AudioTrack; import android.media.AudioFormat; import android.media.AudioManager; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; Piano piano; //Idee: //Die Sphären geben pulsierende Töne von sich. //Je besser man eine Sphäre fokussiert hat, desto höher die Pulsfrequenz. PShape spheres; PMatrix3D eyeMat = new PMatrix3D(); //Übereinstimmungsgrad zwischen der Blickrichtung und den 6 Sphären: // VORN HINTEN LINKS RECHTS OBEN UNTEN // 00- 00+ -00 +00 0+0 0-0 double[] uebereinstimmung = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; double ez_x = 0.0; double ez_y = 0.0; double ez_z = 0.0; public void aktualisiereUebereinstimmung() { uebereinstimmung[0] = ez_x*0.0 + ez_y*0.0 + ez_z*(-1.0); uebereinstimmung[1] = ez_x*0.0 + ez_y*0.0 + ez_z*(1.0); uebereinstimmung[2] = ez_x*(-1.0) + ez_y*0.0 + ez_z*0.0; uebereinstimmung[3] = ez_x*1.0 + ez_y*0.0 + ez_z*0.0; uebereinstimmung[4] = ez_x*0.0 + ez_y*1.0 + ez_z*0.0; uebereinstimmung[5] = ez_x*0.0 + ez_y*(-1.0) + ez_z*0.0; for(int i=0;i<uebereinstimmung.length;i++) if(uebereinstimmung[i]<0.0) uebereinstimmung[i]=0.0; } void setup() { piano = new Piano(); fullScreen(STEREO); spheres = createShape(GROUP); float[][] orte = { {1000,0,0}, //rot links von mir {-1000,0,0}, //grün rechts von mir {0,1000,0}, //gelb unter mir {0,-1000,0}, //blau über mir {0,0,1000}, //türkis hinter mir {0,0,-1000} //violett weit vor mir durch weiss verdeckt! }; int[][] farben = { {255,0,0},//rot {0,255,0},//gruen {255,255,0},//gelb {0,0,255}, //blau {0,255,255},//türkis {255,0,255} //violett }; for(int i=0;i<orte.length;i++) { PShape sphere = createShape(SPHERE, 50); sphere.setStroke(false); sphere.setFill(color(farben[i][0],farben[i][1],farben[i][2])); sphere.translate(orte[i][0],orte[i][1],orte[i][2]); spheres.addChild(sphere); } textAlign(CENTER, CENTER); textSize(displayDensity * 36); frameRate(30); } int zzz=0; void draw() { background(0); getEyeMatrix(eyeMat); //Kameramatrix auslesen translate(eyeMat.m03, eyeMat.m13, eyeMat.m23); //Welt in Koordinatenursprung von Kamera setzen. lights(); shape(spheres); eye(); //Transformation realtiv zur Kamera translate(0, 0, 500); //Zielkreis relativ zur Kamera zeichnen noFill(); stroke(255,0,0); ellipse(0, 0, 50, 50); ez_x = eyeMat.m02; ez_y = -eyeMat.m12; ez_z = eyeMat.m22; aktualisiereUebereinstimmung(); if(zzz%90==0) { println("ez=["+nfp(eyeMat.m02,1,3)+","+nfp(-eyeMat.m12,1,3)+","+nfp(eyeMat.m22,1,3)+"]"); } zzz++; }
Code 0-2: vr002_puls (Haupttab)
double dreieck(double a, double freq, double t) { double tt = t*freq - Math.floor(t*freq); //weitere Verbesserung: Lookup-Table im Bereich 0..1 sehr sehr fein (10000 Werte z.B.) if(t>=0.0) { if(tt<0.25) return 4.0*a*tt; else if(tt<0.75) return 4.0*a*(0.25 - (tt-0.25)); else return 4.0*a*(-0.25+(tt-0.75)); } else { tt=-tt; if(tt<0.25) return -4.0*a*tt; else if(tt<0.75) return -4.0*a*(0.25 - (tt-0.25)); else return -4.0*a*(-0.25+(tt-0.75)); } } public class Piano implements Runnable { AudioTrack audioTrack; int sr = 44100; int buffsize = 8820; double t=0.0; double dt = 1.0/(double)sr; protected ScheduledExecutorService schedExecService; short[] puffer = new short[buffsize*2]; //4 Byte pro Sample == 16Bit Stereo //2 * bei short public Piano() { try { audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sr, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, buffsize*4, AudioTrack.MODE_STREAM); audioTrack.setStereoVolume(1.0f, 1.0f); audioTrack.play(); schedExecService = Executors.newSingleThreadScheduledExecutor(); long period = (buffsize*1000)/sr; //Seconds per Beat==60/BPM, die Hälfte weil 8tel, mal 1000 weil Millisekunden. schedExecService.scheduleAtFixedRate(this, 0, period, TimeUnit.MILLISECONDS); } catch(Exception ee) { System.out.println("FEHLER: "+ee); } } public void run() { for(int i=0;i<buffsize;i++) { puffer[i*2+0] = (short)dreieck(uebereinstimmung[0]*15000.0,440.0,t); //VORN puffer[i*2+1] = (short)dreieck(uebereinstimmung[2]*15000.0,770.0,t); //LINKS //UNTEN puffer[i*2+0] += (short)dreieck(uebereinstimmung[5]*15000.0,330.0,t); puffer[i*2+1] += (short)dreieck(uebereinstimmung[5]*15000.0,330.0,t); t+=dt; } audioTrack.write(puffer, 0,buffsize*2); } }
Code 0-3: vr002_puls (toene-Tab)
Dreht man den Kopf nach rechts und fokussiert die rechte Sphäre verstummen alle Töne.