mirror of
https://github.com/processing/processing4.git
synced 2026-02-04 06:09:17 +01:00
198 lines
5.0 KiB
Plaintext
198 lines
5.0 KiB
Plaintext
// Earth
|
|
// by Mike 'Flux' Chang (cleaned up by Aaron Koblin).
|
|
// Based on code by Toxi.
|
|
// Android port by Andres Colubri
|
|
//
|
|
// This example shows the shape recording functionality in A3D,
|
|
// where an entire geometry drawn with the regular API can be
|
|
// stored in a PShape3D object for later use. This greatly
|
|
// improves the performance of the application.
|
|
// Tap on the screen to enable/disable drawing with the recorded
|
|
// shape.
|
|
|
|
PShape globe;
|
|
PImage texmap;
|
|
|
|
int sDetail = 32; // Sphere detail setting
|
|
float rotationY = 0;
|
|
float globeRadius = 450;
|
|
float pushBack = 0;
|
|
|
|
float[] cx, cz, sphereX, sphereY, sphereZ;
|
|
float sinLUT[];
|
|
float cosLUT[];
|
|
float SINCOS_PRECISION = 0.5f;
|
|
int SINCOS_LENGTH = (int)(360.0f / SINCOS_PRECISION);
|
|
|
|
boolean usingPShape = false;
|
|
|
|
public void setup() {
|
|
size(480, 800, P3D);
|
|
orientation(PORTRAIT);
|
|
|
|
PFont font = createFont(PFont.list()[0], 24);
|
|
textFont(font, 24);
|
|
|
|
texmap = loadImage("world32k.jpg");
|
|
initializeSphere(sDetail);
|
|
|
|
autoNormal(false);
|
|
noStroke();
|
|
|
|
// Everything that is drawn between beginRecord/endRecord
|
|
// is saved into the PShape3D returned by beginRecord.
|
|
// Drawing the PShape3D object is much faster than redrawing
|
|
// all the geometry again in the draw() function.
|
|
globe = beginRecord();
|
|
texturedSphere(globeRadius, texmap);
|
|
endRecord();
|
|
}
|
|
|
|
public void draw() {
|
|
background(0);
|
|
renderGlobe();
|
|
|
|
fill(255);
|
|
if (usingPShape) {
|
|
text("With PShape3D. FPS: " + frameRate, 10, height - 30);
|
|
} else {
|
|
text("Without PShape3D. FPS: " + frameRate, 10, height - 30);
|
|
}
|
|
}
|
|
|
|
void mousePressed() {
|
|
usingPShape = !usingPShape;
|
|
}
|
|
|
|
public void renderGlobe() {
|
|
pushMatrix();
|
|
translate(width/2.0f, height/2.0f, pushBack);
|
|
lights();
|
|
|
|
pushMatrix();
|
|
|
|
rotateY(rotationY);
|
|
|
|
if (usingPShape) {
|
|
shape(globe);
|
|
} else {
|
|
texturedSphere(globeRadius, texmap);
|
|
}
|
|
|
|
popMatrix();
|
|
popMatrix();
|
|
|
|
rotationY += 0.01;
|
|
}
|
|
|
|
public void initializeSphere(int res) {
|
|
sinLUT = new float[SINCOS_LENGTH];
|
|
cosLUT = new float[SINCOS_LENGTH];
|
|
|
|
for (int i = 0; i < SINCOS_LENGTH; i++) {
|
|
sinLUT[i] = (float) Math.sin(i * DEG_TO_RAD * SINCOS_PRECISION);
|
|
cosLUT[i] = (float) Math.cos(i * DEG_TO_RAD * SINCOS_PRECISION);
|
|
}
|
|
|
|
float delta = (float)SINCOS_LENGTH/res;
|
|
float[] cx = new float[res];
|
|
float[] cz = new float[res];
|
|
|
|
// Calc unit circle in XZ plane
|
|
for (int i = 0; i < res; i++) {
|
|
cx[i] = -cosLUT[(int) (i*delta) % SINCOS_LENGTH];
|
|
cz[i] = sinLUT[(int) (i*delta) % SINCOS_LENGTH];
|
|
}
|
|
|
|
// Computing vertexlist vertexlist starts at south pole
|
|
int vertCount = res * (res-1) + 2;
|
|
int currVert = 0;
|
|
|
|
// Re-init arrays to store vertices
|
|
sphereX = new float[vertCount];
|
|
sphereY = new float[vertCount];
|
|
sphereZ = new float[vertCount];
|
|
float angle_step = (SINCOS_LENGTH*0.5f)/res;
|
|
float angle = angle_step;
|
|
|
|
// Step along Y axis
|
|
for (int i = 1; i < res; i++) {
|
|
float curradius = sinLUT[(int) angle % SINCOS_LENGTH];
|
|
float currY = -cosLUT[(int) angle % SINCOS_LENGTH];
|
|
for (int j = 0; j < res; j++) {
|
|
sphereX[currVert] = cx[j] * curradius;
|
|
sphereY[currVert] = currY;
|
|
sphereZ[currVert++] = cz[j] * curradius;
|
|
}
|
|
angle += angle_step;
|
|
}
|
|
sDetail = res;
|
|
}
|
|
|
|
// Generic routine to draw textured sphere
|
|
void texturedSphere(float r, PImage t) {
|
|
int v1,v11,v2;
|
|
r = (r + 240 ) * 0.33;
|
|
beginShape(TRIANGLE_STRIP);
|
|
texture(t);
|
|
float iu=(float)(t.width-1)/(sDetail);
|
|
float iv=(float)(t.height-1)/(sDetail);
|
|
float u=0,v=iv;
|
|
for (int i = 0; i < sDetail; i++) {
|
|
normal(0, -1, 0);
|
|
vertex(0, -r, 0,u,0);
|
|
normal(sphereX[i], sphereY[i], sphereZ[i]);
|
|
vertex(sphereX[i]*r, sphereY[i]*r, sphereZ[i]*r, u, v);
|
|
u+=iu;
|
|
}
|
|
vertex(0, -r, 0,u,0);
|
|
normal(sphereX[0], sphereY[0], sphereZ[0]);
|
|
vertex(sphereX[0]*r, sphereY[0]*r, sphereZ[0]*r, u, v);
|
|
endShape();
|
|
|
|
// Middle rings
|
|
int voff = 0;
|
|
for(int i = 2; i < sDetail; i++) {
|
|
v1=v11=voff;
|
|
voff += sDetail;
|
|
v2=voff;
|
|
u=0;
|
|
beginShape(TRIANGLE_STRIP);
|
|
texture(t);
|
|
for (int j = 0; j < sDetail; j++) {
|
|
normal(sphereX[v1], sphereY[v1], sphereZ[v1]);
|
|
vertex(sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1++]*r, u, v);
|
|
normal(sphereX[v2], sphereY[v2], sphereZ[v2]);
|
|
vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2++]*r, u, v+iv);
|
|
u+=iu;
|
|
}
|
|
|
|
// Close each ring
|
|
v1=v11;
|
|
v2=voff;
|
|
normal(sphereX[v1], sphereY[v1], sphereZ[v1]);
|
|
vertex(sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1]*r, u, v);
|
|
normal(sphereX[v2], sphereY[v2], sphereZ[v2]);
|
|
vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r, u, v+iv);
|
|
endShape();
|
|
v+=iv;
|
|
}
|
|
u=0;
|
|
|
|
// Add the northern cap
|
|
beginShape(TRIANGLE_STRIP);
|
|
texture(t);
|
|
for (int i = 0; i < sDetail; i++) {
|
|
v2 = voff + i;
|
|
normal(sphereX[v2], sphereY[v2], sphereZ[v2]);
|
|
vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r, u, v);
|
|
normal(0, 1, 0);
|
|
vertex(0, r, 0, u, v+iv);
|
|
u+=iu;
|
|
}
|
|
normal(sphereX[voff], sphereY[voff], sphereZ[voff]);
|
|
vertex(sphereX[voff]*r, sphereY[voff]*r, sphereZ[voff]*r, u, v);
|
|
|
|
endShape();
|
|
}
|