Sphere3D s; BImage earthimg; float tpx, tpy = 0; float crtpx, crtpy = 0; float eyex, eyey = 0; void mousePressed(){ tpx = (float)mouseX / width; tpy = (float)mouseY / height; } void setup(){ background( 0 ); size( 500, 500 ); framerate( 30 ); s = new Sphere3D( 180, 20, 15 ); earthimg = loadImage( "earth_lights.jpg" ); //東京 tpx = 0.89f; tpy = 0.29f; } void loop(){ background( 0 ); crtpx += ( tpx - crtpx ) * 0.2; crtpy += ( tpy - crtpy ) * 0.2; eyex += ( crtpx - eyex ) * 0.1; eyey += ( crtpy - eyey ) * 0.1; Vertex tvtx = s.getSphereCoord( s.r, crtpx, crtpy ); Vertex eyevtx = s.getSphereCoord( s.r*2, eyex, eyey ); beginCamera(); float fov = 60; float eyeZ = (height/2) / ((float) tan(PI * fov / 360f)); float nearDist = eyeZ / 10.0f; float farDist = eyeZ * 10.0f; float aspect = (float)width / (float)height; perspective(fov, aspect, nearDist, farDist); lookat( eyevtx.x, eyevtx.y, eyevtx.z, tvtx.x, tvtx.y, tvtx.z, 0, 1, 0); endCamera(); push(); translate( tvtx.x, tvtx.y, tvtx.z ); noStroke(); fill( 255 ); sphere( 3 ); pop(); push(); stroke( 100 ); fill( 255 ); s.drawSelf(); pop(); } class Sphere3D{ float r; int lx, ly; Sphere3D( float r, int lx, int ly ){ this.r = r; this.lx = lx; this.ly = ly; } void drawSelf(){ float du = 1.0; float dv = 1.0; float ustep = du / lx; float vstep = dv / ly; //頂点の算出 int numVertex = lx * ( ly -1 ) + 2; Vertex[] vtx = new Vertex[numVertex]; int count = 0; vtx[count++] = getSphereCoord( r, 0, 0 ); int i, j; float v, u; for( j = 0, v = vstep; j < ly-1; j++, v += vstep ){ for( i = 0, u = 0.0; i < lx; i++, u += ustep ){ vtx[count++] = getSphereCoord( r, u, v ); } } vtx[count++] = getSphereCoord( r, 0, 1 ); int dtx = earthimg.width / lx; int dty = earthimg.height / ly; int tx = 0, ty = 0; beginShape( QUADS ); //南極 for( i = 0, tx = 0; i < lx; i++, tx += dtx ){ int m = i+1; int n = ( i == lx-1 ) ? 1: m+1; texture( earthimg ); vertex( vtx[0].x, vtx[0].y, vtx[0].z, tx, ty ); vertex( vtx[0].x, vtx[0].y, vtx[0].z, tx+dtx, ty ); vertex( vtx[m].x, vtx[m].y, vtx[m].z, tx+dtx, ty+dty ); vertex( vtx[n].x, vtx[n].y, vtx[n].z, tx, ty+dty ); } //中央 for( j = 0, ty = dty; j < ly-2; j++, ty += dty ){ for( i = 0, tx = 0; i < lx; i++, tx += dtx ){ int m = j*lx+i+1; int n = ( i == lx-1 ) ? m-i : m+1; int r = (j+1)*lx+i+1; int q = ( i == lx -1 ) ? r-i : r+1; texture( earthimg ); //normal( vtx[m].x, vtx[m].y, vtx[m].z ); vertex( vtx[m].x, vtx[m].y, vtx[m].z, tx, ty ); //normal( vtx[n].x, vtx[n].y, vtx[n].z ); vertex( vtx[n].x, vtx[n].y, vtx[n].z, tx+dtx, ty ); //normal( vtx[q].x, vtx[q].y, vtx[q].z ); vertex( vtx[q].x, vtx[q].y, vtx[q].z, tx+dtx, ty+dty ); //normal( vtx[r].x, vtx[r].y, vtx[r].z ); vertex( vtx[r].x, vtx[r].y, vtx[r].z, tx, ty+dty ); } } //北極 int o = lx*(ly-1)+1; for( i = 0, tx = 0, ty = dty*(ly-1); i < lx; i++, tx += dtx ){ int m = lx*(ly-2)+1+i; int n = ( i == lx-1 ) ? m-i : m+1; texture( earthimg ); vertex( vtx[m].x, vtx[m].y, vtx[m].z, tx, ty ); vertex( vtx[n].x, vtx[n].y, vtx[n].z, tx+dtx, ty ); vertex( vtx[o].x, vtx[o].y, vtx[o].z, tx+dtx, ty+dty ); vertex( vtx[o].x, vtx[o].y, vtx[o].z, tx, ty+dty ); } endShape(); } //球の頂点位置の計算 Vertex getSphereCoord( float r, float up, float vp ){ float u = 2*PI*up; float v = PI*vp; float s = -sin(v); float px = s * sin(u); float py = -cos(v); float pz = s * cos(u); return new Vertex( r*px, r*py, r*pz ); } } //頂点座標クラス class Vertex{ float x, y, z; Vertex( float x, float y, float z ){ this.x = x; this.y = y; this.z = z; } }