import java.io.File; import java.io.IOException; import java.nio.FloatBuffer; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.media.opengl.GL; import javax.media.opengl.GL2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import javax.media.opengl.awt.GLCanvas; import javax.media.opengl.glu.GLU; import javax.swing.JFrame; import tangram.GeomElem; import tangram.GeomPoint; import tangram.Tangram; import tangram.svcs.Listios; import com.sun.opengl.util.Animator; import com.sun.opengl.util.BufferUtil; import com.sun.opengl.util.texture.Texture; import com.sun.opengl.util.texture.TextureIO; public class importjte extends JFrame implements GLEventListener { private GLCanvas canvas; private Animator animator; private GLU glu; private Texture[] texture; static FloatBuffer verticesBuf; static FloatBuffer normalsBuf; static FloatBuffer texcoordBuf; static List bufindexes; static List bufelemofst; static Tangram tan; static float t = 0.0f; static float T = 0.0f; static float zoom = 1/160.f; static float hzw = 15f; public importjte() { glu = new GLU(); canvas = new GLCanvas(new GLCapabilities(GLProfile.getDefault())); canvas.addGLEventListener(this); getContentPane().add(canvas); } public void run() { setSize(320+10, 460+30); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); canvas.requestFocusInWindow(); animator = new Animator(canvas); animator.setRunAsFastAsPossible(false); animator.start(); } public static void main(String[] args) { new importjte().run(); } public void init(GLAutoDrawable drawable) { texture = new Texture[6]; try { texture[0] = TextureIO.newTexture(new File("res/wood1.png"), true); texture[1] = TextureIO.newTexture(new File("res/wood2.png"), true); texture[2] = TextureIO.newTexture(new File("res/wood3.png"), true); texture[3] = TextureIO.newTexture(new File("res/wood4.png"), true); texture[4] = TextureIO.newTexture(new File("res/wood5.png"), true); texture[5] = TextureIO.newTexture(new File("res/wood6.png"), true); } catch (IOException ex) { ex.printStackTrace(); } GL2 gl = drawable.getGL().getGL2(); setupPointers(gl); gl.glEnableClientState(GL2.GL_VERTEX_ARRAY); gl.glEnableClientState(GL2.GL_NORMAL_ARRAY); gl.glEnableClientState(GL2.GL_TEXTURE_COORD_ARRAY); gl.glVertexPointer(3, GL2.GL_FLOAT, 0, verticesBuf); gl.glNormalPointer(GL2.GL_FLOAT, 0, normalsBuf); gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, texcoordBuf); } public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { GL2 gl = drawable.getGL().getGL2(); gl.glMatrixMode(GL2.GL_PROJECTION); gl.glLoadIdentity(); glu.gluPerspective(60, (float)width/(float)height, 0.5, 50.0) ; // 視野角[deg] アスペクト比 最近点 最遠い点 gl.glViewport( 0, 0, width , height ); // 左下pxl座標X Y ウィンドウ幅 高さ gl.glMatrixMode(GL2.GL_MODELVIEW); gl.glLoadIdentity(); } public void display(GLAutoDrawable drawable) { GL2 gl = drawable.getGL().getGL2(); float[] lightpos = new float[]{ 10, 8, 0, 1 }; float[] fogcolor = new float[]{ 1, 1, 1, 1 }; gl.glDisable(GL2.GL_FOG); gl.glFogi(GL2.GL_FOG_MODE, GL2.GL_EXP); gl.glFogf(GL2.GL_FOG_DENSITY, 0.05f); gl.glFogfv(GL2.GL_FOG_COLOR, fogcolor, 0); gl.glClearColor(.5f, .5f, .5f, 1.0f); gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); //オブジェクト描画モードにする。 gl.glMatrixMode(GL2.GL_MODELVIEW); gl.glLoadIdentity(); gl.glEnable(GL.GL_TEXTURE_2D); gl.glEnable(GL.GL_DEPTH_TEST); gl.glDepthFunc(GL.GL_LEQUAL); gl.glCullFace(GL2.GL_BACK); gl.glEnable(GL.GL_CULL_FACE); // 光源と材質の設定 gl.glEnable(GL2.GL_COLOR_MATERIAL); gl.glColorMaterial(GL2.GL_FRONT, GL2.GL_DIFFUSE); // カメラ if ((t += 0.025) > 360.0 ) t -= 360.0; glu.gluLookAt( (float)(2.0*Math.sin(t/180*Math.PI)), // 視点の位置x,y,z, (float)(2.0*Math.cos(t/180*Math.PI)), (float)(2.0*Math.cos(t/180*Math.PI)), 0, 0, 0, // 視界の中心位置の参照点座標x,y,z 0, 1, 0); // 視界の上方向のベクトルx,y,z // 照明 gl.glEnable(GL2.GL_LIGHTING); gl.glEnable(GL2.GL_LIGHT0); gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, lightpos, 0); // 今の座標系を保存しておく gl.glPushMatrix(); //オブジェクトの描画 if ((T += 0.017) > 360.0 ) T -= 360.0; //gl.glRotatef(T, 0.3f, -0.5f, 0.9f); gl.glRotatef(T, 1.3f, -0.5f, 1.0f); drawObj(gl); // 座標系を戻す gl.glPopMatrix(); // コマンドのフラッシュ gl.glFlush(); } private void drawObj(GL2 gl) { int pn, ofst; float x, y, z; float xyr[]; // Tangram int tex[] = {0,4,1,2,1,3,0}; int eno[] = {0,1,1,2,3,4,4}; // Ivy //int tex[] = {0,4,1,2,1,3,0}; //int eno[] = {0,0,1,2,2,3,4}; List li = bufindexes; for (int n = 0; n < 2; n++) { x=0f; y=0f; z=-0.5f + (float)n; switch (n) { case 4: // Ivy xyr = new float[] {24.252514264248006f, -2.0632000212564456f, 5.235987755982988f, 38.19995538099002f, 49.98935886200137f, 2.0943951023931953f, 53.22623482261889f, -14.142038346142774f, 2.0943951023931953f, -45.773765177381144f, -21.299714995915696f, 0.0f, -1.7737651773811205f, -45.089479462885116f, 3.141592653589793f, -1.7737651773810974f, 68.41905014797373f, 4.1887902047863905f, -42.65902846763241f, 28.515638303630222f, 4.1887902047863905f }; break; case 5: // Cassowary xyr = new float[] {-13.973723026788404f, 71.02626661534872f, 0.5235987755982988f, 58.02627841180251f, 65.02626197150313f, 5.759586531581287f, -40.000002468417264f, -10.000012826280157f, 0.5235987755982988f, 43.36790971438627f, 22.999987173719816f, 1.5707963267948966f, -7.842325818644314f, 23.698716984497892f, 2.617993877991494f, 99.71876267547214f, -10.000012826280175f, 0.5235987755982988f, -82.65767911819025f, -61.88527611653144f, 5.759586531581287f }; break; default: // Square xyr = new float[] {-51.87572264268514f, -51.9568494554193f, 6.283185307179586f, 40.12427723036572f, -65.95684976960885f, 0.0f, -25.875724352900754f, 0.04315136921091023f, 4.71238898038469f, 0.12427754885441633f, -39.95685052453581f, 6.283185307179586f, -59.87572570350895f, 20.04315052998068f, 0.0f, 56.124276472405825f, 0.0431535191572312f, 6.283185307179586f, 0.12427156723072397f, 56.0431515636766f, 1.5707963267948966f }; break; case 2: // Confotable Clothe xyr = new float[] {72.01203388576373f, -75.36967666750425f, 3.926991f, 32.011998926016474f, 110.22827536612041f, 3.141592653589793f, -101.01601074434598f, 37.22828367997014f, 2.3561946732051036f, 1.9559518724764224f, -144.77171632002987f, 0f, 12.01199892601648f, 64.22827536612041f, 0f, 16.01202663883157f, -35.77171632002983f, 3.141593f, -31.987999504758708f, 44.22827489535299f, 0f }; break; case 1: //Penguin Tank xyr = new float[] {-85.78252982505829f, 13.378650525466263f, 2.356194490192345f, -32.04986285770957f, 47.90505637328138f, 4.71238898038469f, -6.0498628577096945f, -119.2320286165663f, 3.141592653589793f, -6.049862857709691f, 7.905056373281291f, 4.71238898038469f, -8.687461827603666f, 147.301222177526f, 1.325354514014773f, -5.647842604156299f, 81.44416161668221f, 3.92699081698724f, -6.451883111263037f, -65.63404887011964f, 0.7853981633974483f }; break; } for (int i = 0; i < 7; i++) { texture[tex[i]].enable(); texture[tex[i]].bind(); gl.glPushMatrix(); gl.glTranslatef(-xyr[i*3]*zoom+x, -xyr[i*3+1]*zoom+y, z); gl.glRotatef(xyr[i*3+2]*180/(float)Math.PI+180, 0, 0, 1); ofst = bufelemofst.get(eno[i]); gl.glDrawArrays(GL2.GL_TRIANGLE_STRIP, li.get(ofst+0), pn = li.get(ofst+1)); gl.glDrawArrays(GL2.GL_TRIANGLE_STRIP, li.get(ofst+2), pn = li.get(ofst+3)); ofst += 4; for (int j = 0; j < pn; j++, ofst += 2) { gl.glDrawArrays(GL2.GL_TRIANGLE_STRIP, li.get(ofst), li.get(ofst+1)); } gl.glPopMatrix(); texture[tex[i]].disable(); } } } private void setupPointers(GL2 gl) { tan = new Tangram(); Listios lios = new Listios(); lios.loadXML(tan, "res/tangram100.jte", true, false); int i, j, d, idx = 0, pn; boolean etgl; boolean ldsc; GeomElem ge; bufindexes = new ArrayList(100); bufelemofst = new ArrayList(10); float vertices[] = new float[3*(2*3+4*3)*20]; float normals[] = new float[3*(2*3+4*3)*20]; float texcoord[] = new float[3*(2*3+4*3)*20]; for (Iterator gei = tan.geombank.geombank.iterator(); gei.hasNext();) { double ox, oy; ge = gei.next(); pn = ge.geompoints.size(); ox = ge.local_ox; oy = ge.local_oy; bufelemofst.add(bufindexes.size()); // 始点と終点が同じなら、頂点数-1 if ((ge.geompoints.get(0).x[0] == ge.geompoints.get(pn-1).x[0]) && (ge.geompoints.get(0).y[0] == ge.geompoints.get(pn-1).y[0])) { pn--; } // 表面 bufindexes.add(idx); for (i = 0, d = 0, etgl = true; i < pn; i++, etgl = !etgl, idx++) { if (etgl) { vertices[idx*3+0] = (float)(ge.geompoints.get(d).x[0] - ox); vertices[idx*3+1] = (float)(ge.geompoints.get(d).y[0] - oy); texcoord[idx*2+0] = (float)(ge.geompoints.get(d).x[0]); texcoord[idx*2+1] = (float)(ge.geompoints.get(d).y[0]); d++; } else { vertices[idx*3+0] = (float)(ge.geompoints.get((pn - d) % pn).x[0] - ox); vertices[idx*3+1] = (float)(ge.geompoints.get((pn - d) % pn).y[0] - oy); texcoord[idx*2+0] = (float)(ge.geompoints.get((pn - d) % pn).x[0]); texcoord[idx*2+1] = (float)(ge.geompoints.get((pn - d) % pn).y[0]); } vertices[idx*3+2] = hzw; normals[idx*3+0] = 0; normals[idx*3+1] = 0; normals[idx*3+2] = 1; } bufindexes.add(i); // 裏面 bufindexes.add(idx); for (i = 0, d = 0, etgl = true; i < pn; i++, etgl = !etgl, idx++) { if (etgl) { vertices[idx*3+0] = (float)(ge.geompoints.get((pn - d) % pn).x[0] - ox); vertices[idx*3+1] = (float)(ge.geompoints.get((pn - d) % pn).y[0] - oy); texcoord[idx*2+0] = (float)(ge.geompoints.get((pn - d) % pn).x[0]); texcoord[idx*2+1] = (float)(ge.geompoints.get((pn - d) % pn).y[0]); d++; } else { vertices[idx*3+0] = (float)(ge.geompoints.get(d).x[0] - ox); vertices[idx*3+1] = (float)(ge.geompoints.get(d).y[0] - oy); texcoord[idx*2+0] = (float)(ge.geompoints.get(d).x[0]); texcoord[idx*2+1] = (float)(ge.geompoints.get(d).y[0]); } vertices[idx*3+2] = -hzw; normals[idx*3+0] = 0; normals[idx*3+1] = 0; normals[idx*3+2] = -1; } bufindexes.add(i); // 側面 for (i = 0; i < pn; i++) { bufindexes.add(idx); GeomPoint gp0, gp1; double dx, dy, l; double tdx, tdy; gp0 = ge.geompoints.get(i); gp1 = ge.geompoints.get((i + 1) % pn); dx = gp1.x[0] - gp0.x[0]; dy = gp1.y[0] - gp0.y[0]; l = Math.sqrt(dx*dx + dy*dy); tdx = Math.abs(dx); tdy = Math.abs(dy); ldsc = (tdx > tdy); if (ldsc) { tdx = l; tdy = hzw*2; } else { tdx = hzw*2; tdy = l; } normals[idx*3+1] = (float)(gp0.x[0] - gp1.x[0]); for (j = 0, etgl = true; j < 4; j++, etgl = !etgl, idx++) { if (etgl) { vertices[idx*3+0] = (float)(gp0.x[0] - ox); vertices[idx*3+1] = (float)(gp0.y[0] - oy); if (ldsc) { texcoord[idx*2+0] = 0f; texcoord[idx*2+1] = (j < 2) ? 0f : (float)tdy; } else { texcoord[idx*2+0] = (j < 2) ? 0f : (float)tdx; texcoord[idx*2+1] = 0f; } } else { vertices[idx*3+0] = (float)(gp1.x[0] - ox); vertices[idx*3+1] = (float)(gp1.y[0] - oy); if (ldsc) { texcoord[idx*2+0] = (float)tdx; texcoord[idx*2+1] = (j < 2) ? 0f : (float)tdy; } else { texcoord[idx*2+0] = (j < 2) ? 0f : (float)tdx; texcoord[idx*2+1] = (float)tdy; } } vertices[idx*3+2] = (j < 2) ? hzw : -hzw; normals[idx*3+0] = (float)(dy/l); normals[idx*3+1] = (float)(-dx/l); normals[idx*3+2] = 0; } bufindexes.add(j); } } this.verticesBuf = mkFloatBuf(vertices, zoom); this.normalsBuf = mkFloatBuf(normals, 1.0f); this.texcoordBuf = mkFloatBuf(texcoord, zoom); } private FloatBuffer mkFloatBuf(float[] vertices, float ratio) { FloatBuffer tmpVerticesBuf = BufferUtil.newFloatBuffer(vertices.length); for (int i = 0; i < vertices.length; i++) tmpVerticesBuf.put(vertices[i] * ratio); tmpVerticesBuf.rewind(); return tmpVerticesBuf; } public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} public void dispose(GLAutoDrawable drawable){} }