//****************************************************************************** // // Hello3D_05.java: JAVAで3D表示にチャレンジ // // All rights reserved. Copyright (C) (Jun Mitani), 1998- // //****************************************************************************** import java.applet.Applet; import java.awt.*; import java.lang.Math; import java.io.*; import java.net.URL; import java.util.*; //============================================================================== // アプレット Hello3D のメインクラス // //============================================================================== public class Hello3D_05 extends Applet { final static int AppX=300; final static int AppY=300; final static int Canvas_x = 0; final static int Canvas_y = 0; final static int Canvas_w = 300; final static int Canvas_h = 300; final static int Center_x =(int)(Canvas_w/2); final static int Center_y =(int)(Canvas_h/2); double m_Scale; Graphics gg,offg; Image offImage; Color m_CanvasColor = Color.white; int vt_num,fc_num; public Vertex vt[]; public Face fc[]; int pre_x = Center_x, pre_y = Center_y; double phi = 0, theta = 0; double sense = 0.01; String m_FileName = "model.obj"; boolean nomal_inverse = false; public void init() { resize(AppX,AppY); offImage = createImage(Canvas_w,Canvas_h); offg = offImage.getGraphics(); gg = getGraphics(); ImageClear(); setModelData(); DrawModel(); } public void setModelData() { InputStream is; int l = 0,vn = 0,fn = 0; double max_xyz=0.001; Vector v_vec = new Vector(); Vector f_vec = new Vector(); try { is = new URL( getDocumentBase(), m_FileName ).openStream(); StreamTokenizer st = new StreamTokenizer(is); int token; while((token = st.nextToken())!=StreamTokenizer.TT_EOF) { if(token == StreamTokenizer.TT_WORD) { if(st.sval.equals("v")) { double v[] = new double[3]; st.nextToken(); v[0] = (double)st.nval; st.nextToken(); v[1] = (double)st.nval; st.nextToken(); v[2] = (double)st.nval; if(Math.abs(v[0]) > max_xyz)max_xyz = Math.abs(v[0]); if(Math.abs(v[1]) > max_xyz)max_xyz = Math.abs(v[1]); if(Math.abs(v[2]) > max_xyz)max_xyz = Math.abs(v[2]); v_vec.addElement(v); } else if(st.sval.equals("f")) { int f[] = new int[3]; st.nextToken(); f[0] = (int)st.nval; st.nextToken(); f[1] = (int)st.nval; st.nextToken(); f[2] = (int)st.nval; f_vec.addElement(f); } } } } catch(Exception e) { getAppletContext().showStatus("Data Read Error!"); } vt_num = v_vec.size(); fc_num = f_vec.size(); vt = new Vertex[vt_num]; fc = new Face[fc_num]; for(int i = 0; i < vt_num; i++) { double v[] = (double[])v_vec.elementAt(i); vt[i] = new Vertex(v[0],v[1],v[2]); } for(int i = 0; i < fc_num; i++) { int f[] = (int[])f_vec.elementAt(i); fc[i] = new Face(vt[f[0]-1], vt[f[1]-1], vt[f[2]-1]); } m_Scale = 130/max_xyz; } // ダブルバッファへの描画 //-------------------------------------------------------------------------- public void DrawOffg() { // DrawModel(offg,m_Model); } public void update(Graphics g) { paint(g); } // 描画ハンドラ //-------------------------------------------------------------------------- public void paint(Graphics g) { g.drawImage(offImage,0,0,this); } // ダブルバッファのクリア //---------------------------------------------------------------- public void ImageClear() { offg.setColor(m_CanvasColor); offg.fillRect(0,0,Canvas_w,Canvas_h); } // Model の描画 //---------------------------------------------------------------- public void DrawModel() { int px[] = new int[3]; int py[] = new int[3]; int count = 0; int tmp[] = new int[fc_num]; double tmp_depth[]= new double[fc_num]; double a1,a2,a3,b1,b2,b3,nx,ny,nz; ImageClear(); offg.setColor(Color.black); for(int i = 0; i < fc_num; i++) { a1 = fc[i].vt[1].x - fc[i].vt[0].x; a2 = fc[i].vt[1].y - fc[i].vt[0].y; a3 = fc[i].vt[1].z - fc[i].vt[0].z; b1 = fc[i].vt[2].x - fc[i].vt[1].x; b2 = fc[i].vt[2].y - fc[i].vt[1].y; b3 = fc[i].vt[2].z - fc[i].vt[1].z; fc[i].nx = a2 * b3 - a3 * b2; fc[i].ny = a3 * b1 - a1 * b3; fc[i].nz = a1 * b2 - a2 * b1; if(nomal_inverse) { fc[i].nx = -fc[i].nx; fc[i].ny = -fc[i].ny; fc[i].nz = -fc[i].nz; } if( fc[i].nz < 0) { tmp[count] = i; tmp_depth[count] = fc[i].getDepth(); count++; } } double t; int ti; int lim = count-1; do{ int m = 0; for(int n = 0;n <= lim-1; n++) { if(tmp_depth[n] < tmp_depth[n+1]) { t = tmp_depth[n]; tmp_depth[n] = tmp_depth[n+1]; tmp_depth[n+1] = t; ti = tmp[n]; tmp[n] = tmp[n+1]; tmp[n+1] = ti; m = n; } } lim = m; }while(lim != 0); int B; double l; for(int m=0;m 255)B = 255; Color cc; cc = Color.getHSBColor((float)0.2,(float)0.5,(float)B / 255); offg.setColor(cc); for(int j=0; j < 3; j++) { px[j]=(int)( fc[i].vt[j].x * m_Scale + Center_x); py[j]=(int)(-fc[i].vt[j].y * m_Scale + Center_y); } offg.fillPolygon(px,py,3); } gg.drawImage(offImage,0,0,this); } // マウスイベントの処理 //---------------------------------------------------------------- public boolean mouseDown(Event evt, int x, int y) { pre_x = x; pre_y = y; return true; } public boolean mouseUp(Event evt, int x, int y) { return true; } public boolean mouseDrag(Event evt, int x, int y) { int dx = x - pre_x; int dy = y - pre_y; phi = dx * sense; theta = dy * sense; rotate(phi,theta); DrawModel(); pre_x = x; pre_y = y; return true; } // 法線のひっくり返し処理の有無 //---------------------------------------------------------------- public boolean keyDown(Event evt,int key) { if( key == 'z' || key == 'Z') { if(nomal_inverse) { nomal_inverse = false; } else { nomal_inverse = true; } } return true; } // モデルの回転処理 //---------------------------------------------------------------- public void rotate(double phi,double theta) { double tx,ty,tz; double tmpSin = Math.sin(theta); double tmpCos = Math.cos(theta); for(int i=0;i