// uncomment to run in fullscreen GG.fullscreen(); // Scene setup =================== GG.scene().backgroundColor(@(0,0,0)); GG.camera().position(@(0.0551,-1.9374,3.0522) ); GG.camera().rotation((Math.pi/180)*@(10.7622,31.8428,-84.8183) ); // window size 1024 => int WINDOW_SIZE; 0.25 => float sun_r; 0.5 => float earth_r; 0.15 => float moon_r; // width of waveform and spectrum display 1 => float DISPLAY_WIDTH; // need to fix GGen system --> GG.scene(); GSphere earth --> system; GSphere sun --> system; // GCircle sun_halo --> sun; GSphere moon --> system; GPoints points --> GG.scene(); // GDirLight sun_glow --> sun; GPointLight sun_glow --> sun; // DataTexture tex; // // 1 pixel white texture with transparency = 100/255 // // tex.data([255, 255, 255, 100], 1, 1); // FlatMaterial mat; // mat.diffuseMap(tex); // PhongMaterial PhongMaterial; earth.mat(); sun.mat().color(@(.992,.816,.09)); earth.mat().color(@(0,51.0,102.0)/256.0); earth.mat().specular(@(0,191.0,256.0)/256.0); moon.mat().color(@(.425,.433,.441)); earth.position(@(0,0,0)); sun.position(@(1.5,1,0)); moon.position(@(.7,-.7,0)); earth.scale(2*@(earth_r,earth_r,earth_r)); sun.scale(2*@(sun_r,sun_r,sun_r)); moon.scale(2*@(moon_r,moon_r,moon_r)); sun_glow.diffuse(@(.992,.816,.09)); sun_glow.position(@(1.5,1,0)); sun_glow.rotation(@(1,Math.pi,Math.pi)); sun_glow.specular(@(.999,.916,.19)); // sun_halo.position(@(-.2,0,-1)); // sun_halo.mat().color(@(0,0,0)); // sun_halo.rotation((Math.pi/180)*@(10.7622,31.8428,-84.8183)); // prepare vertex data for 1,000,000 points! 500 => int numPoints; float pointPos[numPoints * 3]; float pointColor[numPoints * 4]; float brightDir[numPoints]; 0 => int index; // populate within a 10x10x10 cube for (int i; i < numPoints; i++) { 5 => float posScale; // set position of this vertex Math.random2f(-posScale,posScale) => pointPos[3*index + 0]; Math.random2f(-posScale,posScale) => pointPos[3*index + 1]; Math.random2f(-posScale,posScale) => pointPos[3*index + 2]; // set color of this vertex 1 => pointColor[4*index + 0]; 1 => pointColor[4*index + 1]; 1 => pointColor[4*index + 2]; Math.random2f(.3,1.0) => pointColor[4*index + 3]; // alpha always 1 // twinkling Math.random2f(-5,5)=> brightDir[index]; index+1 => index; } points.geo().positions(pointPos); // set vertex position data points.geo().colors(pointColor); // set vertex color data // waveform renderer GLines waveform --> earth; waveform.mat().lineWidth(1.0); // translate // waveform.posZ(earth_r); // color0 waveform.mat().color( @(.4, .4, 1) ); // spectrum renderer GLines spectrum --> sun; spectrum.mat().lineWidth(1.0); // translate // spectrum.posZ(sun_r); // color0 spectrum.mat().color( @(.4, 1, .4) ); // accumulate samples from mic adc => Flip accum => blackhole; // take the FFT adc => PoleZero dcbloke => FFT fft => blackhole; // set DC blocker .95 => dcbloke.blockZero; // set size of flip WINDOW_SIZE => accum.size; // set window type and size Windowing.hann(WINDOW_SIZE) => fft.window; // set FFT size (will automatically zero pad) WINDOW_SIZE*2 => fft.size; // get a reference for our window for visual tapering of the waveform Windowing.hann(WINDOW_SIZE) @=> float window[]; // sample array float samples[0]; // FFT response complex response[0]; complex response_log[11]; vec3 vertices[WINDOW_SIZE]; float positions[WINDOW_SIZE*3]; float power; // map audio buffer to 3D positions fun void map2waveform( float in[], float out[] ) { if( in.size()*3 != out.size() ) { <<< "size mismatch in flatten()", "" >>>; return; } // mapping to xyz coordinate int i; float ang; // (-pi/2 -> pi/2) DISPLAY_WIDTH => float width; for( auto s : in ) { // map // -width/2 + width/WINDOW_SIZE*i => out[i*3+1]; // y // s*6 * window[i] => out[i*3]; // x // 0 => out[i*3+2]; // z -Math.pi/2 + (width/WINDOW_SIZE*i)/earth_r=> ang; width/2 * Math.sin(ang) => out[i*3]; // x s*1 * window[i] => out[i*3+1]; // y earth_r * Math.cos(ang) => out[i*3+2]; // z // increment i++; } } // map FFT output to 3D positions fun void map2spectrum( complex in[], float out[] ) { if( in.size()*3 != out.size() ) { <<< "size mismatch in flatten()", "" >>>; return; } // mapping to xyz coordinate int i; float ang; // (-pi/2 -> pi/2) DISPLAY_WIDTH => float width; for( auto s : in ) { // map // -width/2 + width/WINDOW_SIZE*i => out[i*3+1]; // y // 25 * Math.sqrt( (s$polar).mag ) => out[i*3]; // x // 0 => out[i*3+2]; // z -Math.pi/2 + (width/WINDOW_SIZE*i)/sun_r => ang; width/2 * Math.sin(ang) => out[i*3]; // x sun_r * Math.sqrt( (s$polar).mag * 25 ) => out[i*3+1]; // y earth_r * Math.cos(ang) => out[i*3+2]; // z // increment i++; } } fun void move_stars() { 0 => int index; for (int i; i < numPoints; i++) { 5 => float posScale; // set position of this vertex // Math.random2f(-posScale,posScale) => pointPos[3*index + 0]; // Math.random2f(-posScale,posScale) => pointPos[3*index + 1]; // Math.random2f(-posScale,posScale) => pointPos[3*index + 2]; // set brightness of this vertex pointColor[4*index + 3] + brightDir[index] * GG.dt() => pointColor[4*index + 3]; if (pointColor[4*index + 3]>0.9 && brightDir[index] > 0) { Math.random2f(-5,5)=> brightDir[index]; } if (pointColor[4*index + 3] < -0.9 && brightDir[index] < 0) { Math.random2f(-5,5)=> brightDir[index]; } // alpha index+1 => index; } points.geo().colors(pointColor); } // do audio stuff fun void doAudio() { while( true ) { // upchuck to process accum accum.upchuck(); // get the last window size samples (waveform) accum.output( samples ); // upchuck to take FFT, get magnitude reposne fft.upchuck(); // get spectrum (as complex values) fft.spectrum( response ); // convert response values to logarithmic frequency // FIX!!! 0 => int j; for (1 => int i; i i) { response[i] => response_log[j]; j++; } //get power 0 => float temp; for(int i; i float sqr; sqr +=> temp; } temp/WINDOW_SIZE => power; // jump by samples WINDOW_SIZE::samp/2 => now; } } spork ~ doAudio(); fun void move_camera() { // 3d moving camera to figure out camera position if( KB.isKeyDown(KB.KEY_D) ) { // positive x axis GG.camera().translate(GG.dt()*GG.camera().right()); } if( KB.isKeyDown(KB.KEY_A) ) { // negative x axis GG.camera().translate(-GG.dt()*GG.camera().right()); } if( KB.isKeyDown(KB.KEY_E) ) { // positive y axis GG.camera().translate(GG.dt()*GG.camera().forward()); } if( KB.isKeyDown(KB.KEY_Z) ) { // negative y axis GG.camera().translate(-GG.dt()*GG.camera().forward()); } if( KB.isKeyDown(KB.KEY_W) ) { // positive z axis GG.camera().translate(GG.dt()*GG.camera().up()); } if( KB.isKeyDown(KB.KEY_X) ) { // negative z axis GG.camera().translate(-GG.dt()*GG.camera().up()); } if( KB.isKeyDown(KB.KEY_U) ) { // rotate + x axis GG.camera().rotateOnWorldAxis(GG.camera().right(), GG.dt()); } if( KB.isKeyDown(KB.KEY_M) ) { // rotate - x axis GG.camera().rotateOnWorldAxis(GG.camera().right(), -GG.dt()); } if( KB.isKeyDown(KB.KEY_I) ) { // rotate + y axis GG.camera().rotateOnWorldAxis(GG.camera().forward(), GG.dt()); } if( KB.isKeyDown(KB.KEY_N) ) { // rotate - y axis GG.camera().rotateOnWorldAxis(GG.camera().forward(), -GG.dt()); } if( KB.isKeyDown(KB.KEY_H) ) { // rotate + z axis GG.camera().rotateOnWorldAxis(GG.camera().up(), GG.dt()); } if( KB.isKeyDown(KB.KEY_K) ) { // rotate - z axis GG.camera().rotateOnWorldAxis(GG.camera().up(), -GG.dt()); } if( KB.isKeyDown(KB.KEY_P) ) { // print camera pos and angle <<< "Position: ", GG.camera().pos() >>>; <<< "Rotation: ", GG.camera().rot() >>>; } } // infinite time loopp while( true ) { move_camera(); // setting xyz coord GG.camera().rot() => vec3 view; // map to interleaved format map2waveform( samples, positions ); // set the mesh position waveform.geo().positions( positions ); waveform.rotation((Math.pi/180)*view); // map to spectrum display map2spectrum( response, positions ); // set the mesh position spectrum.geo().positions( positions ); spectrum.rotation((Math.pi/180)*view); // glow sun depending on power sun_glow.intensity(power*100); // move stars move_stars(); // earth.rotY(GG.dt()); // sun.rotY(GG.dt()); // moon.rotY(GG.dt()); // IMPORTANT: synchronization point with next frame to render GG.nextFrame() => now; }