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.zip
import 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.