Files
processing4/android/examples/OpenGL/Planets/Planets.pde
2011-02-12 15:57:36 +00:00

129 lines
3.7 KiB
Plaintext

// Planets, by Andres Colubri
// This example uses the beginRecord/endRecord method to save
// an entire shape geometry into a PShape3D object for faster
// drawing. It also demonstrates mulitexturing and displacement
// of texture coordinates
// Sun and mercury textures from http://planetpixelemporium.com
// Star field picture from http://www.galacticimages.com/
PImage starfield;
PShape sun;
PImage suntex;
PShape planet1;
PImage surftex1;
PImage cloudtex;
PShape planet2;
PImage surftex2;
void setup() {
size(480, 800, A3D);
orientation(PORTRAIT);
starfield = loadImage("starfield.jpg");
suntex = loadImage("sun.jpg");
surftex1 = loadImage("planet.jpg");
// We need trilinear sampling for this texture so it looks good
// even when rendered very small.
PTexture.Parameters params1 = PTexture.newParameters(ARGB, TRILINEAR);
surftex2 = loadImage("mercury.jpg", params1);
// The clouds texture will "move" having the values of its u
// texture coordinates displaced by adding a constant increment
// in each frame. This requires REPEAT wrapping mode so texture
// coordinates can be larger than 1.
PTexture.Parameters params2 = PTexture.newParameters();
params2.wrapU = REPEAT;
cloudtex = createImage(512, 256, ARGB, params2);
// Using 3D Perlin noise to generate a clouds texture that is seamless on
// its edges so it can be applied on a sphere.
println("Generating clouds texture. It takes some time, please wait...");
cloudtex.loadPixels();
Perlin perlin = new Perlin();
for (int j = 0; j < cloudtex.height; j++) {
for (int i = 0; i < cloudtex.width; i++) {
// The angle values corresponding to each u,v pair:
float u = float(i) / cloudtex.width;
float v = float(j) / cloudtex.height;
float phi = map(u, 0, 1, TWO_PI, 0);
float theta = map(v, 0, 1, -HALF_PI, HALF_PI);
// The x, y, z point corresponding to these angles:
float x = cos(phi) * cos(theta);
float y = sin(theta);
float z = sin(phi) * cos(theta);
float n = perlin.noise3D(x, y, z, 1.2, 2, 8);
cloudtex.pixels[j * cloudtex.width + i] = color(255, 255, 255, 255 * n * n);
}
}
cloudtex.updatePixels();
println("Done.");
textureMode(NORMAL);
noStroke();
fill(255);
sun = beginRecord();
drawSphere(150, 20, suntex, null);
endRecord();
planet1 = beginRecord();
drawSphere(150, 20, surftex1, cloudtex);
endRecord();
planet2 = beginRecord();
drawSphere(50, 15, surftex2, null);
endRecord();
}
void draw() {
// Even we draw a full screen image after this, it is recommended to use
// background to clear the screen anyways, otherwise A3D will think
// you want to keep each drawn frame in the framebuffer, which results in
// slower rendering.
background(0);
// Disabling writing to the depth mask so the
// background image doesn't occludes any 3D object.
hint(DISABLE_DEPTH_MASK);
image(starfield, 0, 0, width, height);
hint(ENABLE_DEPTH_MASK);
// Displacing the u texture coordinate of layer 1 in planet
// so it creates the effect of moving clouds.
PShape3D p = (PShape3D)planet1;
p.loadTexcoords(1);
for (int i = 0; i < p.getVertexCount(); i++) {
float u = p.texcoords[2 * i + 0];
u += 0.002;
p.texcoords[2 * i + 0] = u;
}
p.updateTexcoords();
pushMatrix();
translate(width/2, height/2, -100);
pushMatrix();
rotateY(PI * frameCount / 500);
shape(sun);
popMatrix();
pointLight(255, 255, 255, 0, 0, 0);
rotateY(PI * frameCount / 300);
translate(0, 0, 300);
shape(planet2);
popMatrix();
noLights();
pointLight(255, 255, 255, 0, 0, 100);
translate(0.75 * width, 0.6 * height, 350);
shape(planet1);
}