xxxxxxxxxx
// Spiral Galaxy Simulation
// author : Philippe Guglielmetti (Dr. Goulu www.goulu.net)
// 2008.04.03 PhG : my first processing program !
// converted from my LUA/Demoniak 3D demo V 1.0
// see http://3dmon.wordpress.com/2007/08/26/simulation-de-galaxie-spirale/
// 2008.04.04 PhG : much faster in P3D mode : now ok with 10'000 stars !
// keyboard interaction : use arrow keys to alter the galaxy
window.tr = window.console && console.log.bind( console ) || function(){};
function gauss( x ){ return Math.exp( - x * x / 2 ) / sqrt( 2 * Math.PI ); }
function gaussI( z ){ // integrated gauss [0..1]
if( z < -8.0 ) return 0.0;
if( z > 8.0 ) return 1.0;
var sum = 0, term = z;
for( var i = 3; sum + term !== sum; i+= 2 ){
sum += term;
term *= z * z / i;
}
return 0.5 + sum * gauss(z);
}
function gaussE( z ){ return gaussI( z ) * 2 - 1; } // gauss error func==> [-1..0..1]
function randomGauss(){
var x = 0, y = 0, r, c;
do{
x = Math.random() * 2 - 1;
y = Math.random() * 2 - 1;
r = x * x + y * y;
}while( r === 0 || r > 1 );
c = Math.sqrt( - 2 * Math.log(r) / r );
return x * c; //return [x*c, y*c];
}
function randomGaussIn( L, H, mul ){ return constrain( randomGauss() * (H-L) * mul + (L+H) / 2, L, H ); }
function randomGaussAt( L, H, mul ){ return randomGauss() * (H-L) * mul + (L+H) / 2; }
var stars = 10000; // only ...
var Rmax = 200; // galaxy radius
var speed = 0.02; // rotation speed
// stars follow elliptic orbits around the center
// var eratio = .85; // ellipse ratio
// var etwist = 8.0 / Rmax; // twisting factor (orbit axes depend on radius)
var eratio = 0.8;
var etwist = 0.07; //rmax=200
var angle = [];
var radius = [];
var z = [];
var WW, HH;
var cx, cy; //center
var frameTime = 1000 / 60; // millisec
var pts = Date.now() - frameTime;
function windowResized(){
initCanvas( false );
}
function initCanvas( first ){
WW = Math.min( 900, windowWidth );
HH = Math.min( 500, windowHeight );
( first ? createCanvas : resizeCanvas )( WW, HH );
background('#000000'); // back to black
// begin in the center
cx = WW / 2;
cy = HH / 2;
}
function setup(){
initCanvas( true );
// init stars
for( var i = 0; i < stars; i++ ){
angle[i] = Math.random() * 2 * Math.PI;
radius[i] = Math.abs( randomGauss()) * Rmax * 0.6 + 0.0; // radius[i] = random( 1, Rmax );
z[i] = randomGauss() * gauss( radius[i] / Rmax * 5.0 ) * Rmax * 0.04;
z[i] = Math.abs( z[i]);
//z[i] = 0;
}
}
function draw(){
/** /
background( 0, 0, 0, 128 );
/**/
var img = get();
img.resize( Math.round( WW * 0.25 ), Math.round( HH * 0.25 ));
img.resize( WW - 2, HH - 2 );
tint( 245, 250, 255 );
image( img, 1, 1 );
/**/
var ts = Date.now();
var dt = ts - pts;
pts = ts;
var fps = 1000 / dt;
//var speedMul = speed / getTargetFrameRate();
var speedMul = speed / fps;
//fill(0,8); rect( 0, 0, WW, HH );
noStroke();
var r, a, x, y, b, s, c, xx, yy, dd;
for( var i = 0; i < stars; i++ ){
r = radius[i];
a = angle[i] + speedMul * ( Rmax / r ) * 3; // increment angle
angle[i] = a;
x = r * Math.sin( a );
y = r * eratio * Math.cos( a );
b = r * etwist;
s = Math.sin( b );
c = Math.cos( b );
xx = cx + s*x + c*y; // a bit of trigo
yy = cy + ( c*x - s*y ) / 3 - z[i] * 20 + cy * 0.2;
//dd = ( r - 50.0 ) * 7.0;
dd = 40000.0 / r;
fill( dd, dd, dd * 0.9, 32 );
/**/
if( z[i] > 0.2 ){
if( z[i] > 9.0 ){
fill( 255, 255, 255, 255 );
ellipse( xx, yy, 7, 7 );
fill( 255, 255, 255, 32 );
}else if( z[i] > 4.5 ){
fill( 255, 32, 32, 64 );
ellipse(xx,yy,7.0,7.0);
fill( 255, 255, 255, 32 );
}else if( z[i] > 4.1 ){
fill( 255, 255, 255, 255 );
ellipse( xx, yy, 7, 7 );
fill( 255, 255, 255, 32 );
}else{
fill( 80, 128, 40, 64 );
if(( i % 50 ) === 0 ){
fill( 255, 255, 255, 255 );
ellipse( xx, yy, 7, 7 );
fill( 255, 255, 255, 32 );
}
}
}/**/
rect( xx - 1.5, yy - 1.5, 3, 3 );
} // for i stars
if( keyIsPressed ) handleKey();
}
function handleKey(){
if( keyCode === UP_ARROW ) eratio *= 1.02;
if( keyCode === DOWN_ARROW ) eratio /= 1.02;
if( keyCode === LEFT_ARROW ) etwist += 0.001;
if( keyCode === RIGHT_ARROW ) etwist -= 0.001;
}
function keyPressed(){
handleKey();
}