// Schwarzschild. // Okay, this will let us drive a spaceship inside a black hole horizon // first create an abstract object, since I guess we will in principle simulate more things. class thing { float r, phi, rdot, phidot, v, vdot; float display_r; float s; int x,y; // also keep track of x and y coords. thing (float r_in, float phi_in, float rdot_in, float phidot_in) { // just initializes it. r = r_in; phi = phi_in; rdot = rdot_in; phidot = phidot_in; display_r = r; normalize(); s = 0; v = 0; // println(r, rdot, phi, phidot, vdot); x = (int)(r*cos(phi)); y = (int)(r*sin(phi)); } void normalize() { // this is done differently depending on which side of the horizon we are on if (r > rh) { // figure out vdot by normalizing the whole thing to have length -1. vdot = (r*rdot + sqrt(r*(-rh+r*(1.0+pow(rdot,2)+(r*(r-rh)*pow(phidot,2))))))/(r-rh); } else { // now figure out rdot (as this is the timelike direction now) rdot = (-r + (r - rh)*pow(vdot,2)-pow(r,3)*pow(phidot,2))/(2*r*vdot); //rdot = 0; } float norm = 2*rdot*vdot + (-1 + rh/r)*pow(vdot,2) + pow(r*phidot,2); //println("norm ", norm, "normalizing: ", (-rh+r*(1.0+pow(rdot,2)+(r*(r-rh)*pow(phidot,2))))); } void update() { // update the accel values, etc. // doing the eddington evolver: vdot += (-(rh/(2*pow(r,2)))*pow(vdot,2) + r*(pow(phidot,2)))*deltaT; rdot += (((rh/pow(r,2))*rdot*vdot) - (((r-rh)*rh*pow(vdot,2))/(2*pow(r,3))) + ((r-rh)*pow(phidot,2)))*deltaT; phidot += (-(2*phidot*rdot)/r)*deltaT; // update the (r, phi, v) r += (rdot*deltaT); phi += (phidot*deltaT); // only update the v if we have crossed the horizon (that way v = 0 is the horizon crossing time) if (r < rh) { v += (vdot * deltaT); } // finally, update the proper time. s += deltaT; //float norm = 2*rdot*vdot + (-1 + rh/r)*pow(vdot,2) + pow(r*phidot,2); // next, figure out the display position. this is where we do an interesting nonlinear map. // okay, here is the display position; use v as the coordinate after crossing horizon if (r > rh) { display_r = r; } else { display_r = rh/(1+v/v_scaling); } //float display_r = (exp(-v)*rh)*theta(rh-r) + theta(r-rh)*r; x = (int)(display_r*cos(phi)); y = (int)(display_r*sin(phi)); //println("v ", v, "display r", display_r, "r ", r); } } // schwarzschild radius. float rh = 300; float UVcutoff = 5; float v_scaling = 200; float init_r = 1.6*rh; float init_phidot = sqrt(rh)/(init_r*sqrt(2*init_r - 3*rh)); //float init_phidot = 0; // create the ship. thing ship = new thing(init_r,0,0,init_phidot); // create the coin thing coin = new thing(init_r,1.5,0,init_phidot); int ship_width = 30; int jet_width = 10; int coin_width = 20; color jet_color = color(252,96,5); //color bh_color = color(137,203,242); color bh_color = color(0,0,0,200); color ship_color = color(181,195,203); color coin_color = color(255,255,0); color heart_color = color(255,255,255); color star_color = color(40,40,80); color horizon_color = color(255,0,0,100); //color star_color = color(20,20,80); color bg_color = color(0,0,60); float rocketAcc = 0.5; // overall thing for dimensional reasons. float deltaT = 0.05; float beep_rate = 20; //float beep_rate = 100; float wobble_amp = 400; float min_scale = 0.75; float T = 0; //float s = 0; // proper time. // this is the number of timesteps that we go through before it displays it. // (40 is like arcade game. 20 is introspective enough that you can see things.) int display_rate = 30; int score = 0; PFont f; // the star locations int num_stars = 1000; //int num_stars = 0; int[] starsX = new int[num_stars]; int[] starsY = new int[num_stars]; int[] starSize = new int[num_stars]; int starMaxSize = 7; // whether or not to show the horizon boolean showHorizon = false; float tanh(float x) { return (exp(x) - exp(-x))/(exp(x) + exp(-x)); } float theta(float x) { // this is a regulated step function for x > 0. return (tanh(x/UVcutoff) + 1)/2; } void setup() { size(800,800); background(0,0,60); frameRate(30); for (int i =0; i