xof 0302txt 0064 Header { 1; 0; 1; } Material Matred { 1.000000;1.000000;1.000000;1.000000;; 21.333333; 0.000000;0.000000;0.000000;; 0.000000;0.000000;0.000000;; TextureFilename { "test.jpg"; } } Material Matgr { 1.000000;1.000000;1.000000;1.000000;; 21.333333; 0.000000;0.000000;0.000000;; 0.000000;0.000000;0.000000;; TextureFilename { "kishi.gif"; } } Material Matwh { 1.000000;1.000000;1.000000;1.000000;; 21.333333; 0.000000;0.000000;0.000000;; 0.000000;0.000000;0.000000;; } Material Matye { 1.000000;1.000000;0.000000;1.000000;; 21.333333; 0.000000;0.000000;0.000000;; 0.000000;0.000000;0.000000;; } Material Matpi { 1.000000;0.501961;1.000000;1.000000;; 21.333333; 0.000000;0.000000;0.000000;; 0.000000;0.000000;0.000000;; } Material Matbr { 0.000000;0.000000;1.000000;1.000000;; 21.333333; 0.000000;0.000000;0.000000;; 0.000000;0.000000;0.000000;; } Mesh { 8; 1.0;-1.0;-1.0;, -1.0;-1.0;-1.0;, -1.0;1.0;-1.0;, 1.0;1.0;-1.0;, -1.0;-1.0;1.0;, 1.0;-1.0;1.0;, 1.0;1.0;1.0;, -1.0;1.0;1.0;; 6; 4;0,1,2,3;, 4;4,5,6,7;, 4;5,0,3,6;, 4;1,4,7,2;, 4;1,0,5,4;, 4;2,7,6,3;; MeshMaterialList { 6; 6; 0, 1, 2, 3, 4, 5;; {Matred} {Matred} {Matgr} {Matgr} {Matbr} {Matbr} } MeshNormals { 6; 0.000000;0.000000;-1.000000;, 0.000000;0.000000;1.000000;, 1.000000;0.000000;0.000000;, -1.000000;0.000000;0.000000;, 0.000000;-1.000000;0.000000;, 0.000000;1.000000;0.000000;; 6; 4;0,0,0,0;, 4;1,1,1,1;, 4;2,2,2,2;, 4;3,3,3,3;, 4;4,4,4,4;, 4;5,5,5,5;; } MeshTextureCoords { 8; 0.0;0.0; 1.0;0.0; 1.0;1.0; 0.0;1.0; 0.0;0.0; 1.0;0.0; 1.0;1.0; 0.0;1.0;; } } |
//★ x_loader object class 前田 稔 // Texture を設定 import java.awt.*; import javax.swing.*; import javax.media.j3d.*; import javax.vecmath.*; import com.sun.j3d.utils.universe.*; import com.sun.j3d.utils.geometry.*; import java.io.*; import java.net.URL; import com.sun.j3d.loaders.*; import com.sun.j3d.utils.behaviors.mouse.*; import java.util.*; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import com.sun.j3d.utils.image.TextureLoader; //★ X-File Loader Object Class public class x_loader extends LoaderBase { //public static final int RESIZE = 1; SceneBase Base; // SceneBase BufferedReader BR; // 入力 Reader String BUF; // 1行分の入力バッファ StringTokenizer token; // トークン Object URL PATH= null;// ファイルの PATH TransformGroup Rot; // 回転 // 頂点座標領域 ArrayList<Point3f> vp = new ArrayList<Point3f>(); // 頂点座標 ArrayList<Vector3f> vn = new ArrayList<Vector3f>(); // 法線ベクトル ArrayList<TexCoord2f> vt = new ArrayList<TexCoord2f>(); // テクスチャ座標 ArrayList<Integer> idx = new ArrayList<Integer>(); // Index(ポリゴン)の区切り ArrayList<Integer> xvp = new ArrayList<Integer>(); // 頂点 Index の並び ArrayList<Integer> xvn = new ArrayList<Integer>(); // 法線 Index の並び // Material 領域 ArrayList<String> mid = new ArrayList<String>(); // mtbl の ID ArrayList<Mat> mtbl = new ArrayList<Mat>(); // Material Table // MaterialList 領域 ArrayList<Integer> fidx = new ArrayList<Integer>(); // face Index ArrayList<Mat> fmat = new ArrayList<Mat>(); // face Material // 構造体 class mats { Color4f faceColor; float power; Color3f specularColor; Color3f emissiveColor; BufferedImage image; } @Override public Scene load(String fname) { Base = new SceneBase(); try { File file = new File(fname); java.net.URI uri = file.toURI(); PATH = uri.toURL(); BR = new BufferedReader(new FileReader(file)); } catch(IOException e) { System.out.println("File Open Error=" + fname); return Base; } Create(); return Base; } @Override public Scene load(URL aURL) { Base = new SceneBase(); return Base; } @Override public Scene load(Reader reader) { Base = new SceneBase(); return Base; } // Scene を生成 public void Create() { Base.setSceneGroup(new BranchGroup()); // 回転の初期化 Rot = new TransformGroup(); Transform3D rotate = new Transform3D(); rotate.rotY(Math.PI); // Y 軸について180度回転 Rot.setTransform(rotate); Base.getSceneGroup().addChild(Rot); set_data(); creatscene(); } // X-File を入力して ArrayList に格納 public void set_data() { int i,j,num,pn; String str; // Header Check NextRead(); str = token.nextToken(); if ("xof".equals(str)==false) { System.out.println("X-File error?" + str); return; } str = token.nextToken(); if ("txt".equals(str.substring(4,7))==false) { System.out.println("X-File error?" + str); return; } while(NextRead()) { str = token.nextToken(); if ("Mesh".equals(str)) // 頂点座標 { Skip("{"); num= Val(); // 頂点の数 for(i=0; i<num; i++) vp.add(new Point3f(FVal(), FVal(), FVal())); num= Val(); // ポリゴンの数 for(i=0; i<num; i++) { pn= Val(); // ポリゴンの頂点数 idx.add(pn); for(j=0; j<pn; j++) xvp.add(Val()); } } if ("MeshNormals".equals(str)) // 法線ベクトル { Skip("{"); num= Val(); // 法線の数 for(i=0; i<num; i++) vn.add(new Vector3f(FVal(), FVal(), FVal())); num= Val(); // 面の数 for(i=0; i<num; i++) { pn= Val(); // ポリゴンの頂点数 for(j=0; j<pn; j++) xvn.add(Val()); } } if ("MeshTextureCoords".equals(str)) // テクスチャ座標 { Skip("{"); num= Val(); // 座標の数 for(i=0; i<num; i++) vt.add(new TexCoord2f(FVal(), FVal())); } if ("Material".equals(str)) // マテリアル { str = token.nextToken(); if ("{".equals(str)) // ID が無い(普通は起こらない) { mtbl.add(matset()); } else { mid.add(str); // mtbl の ID Skip("{"); mtbl.add(matset()); // mtbl に登録 } } if ("MeshMaterialList".equals(str)) // マテリアルリスト { Skip("{"); num= Val(); // マテリアルの数 pn= Val(); // フェース(ポリゴン)の数 for(i=0; i<pn; i++) fidx.add(Val()); for(i=0; i<num; i++) { NextRead(); str = token.nextToken(); if ("Material".equals(str)) { Skip("{"); // MeshMaterialList で直接定義 fmat.add(matset()); } if (str.charAt(0)=='{') // {Matgr} { Matgr } { String wk; if ("{".equals(str)) wk= token.nextToken(); else wk= str.substring(1,str.length()-1); for(j=0; j<mid.size() && wk.equals(mid.get(j))==false; j++); if (j<mid.size()) fmat.add(mtbl.get(j)); else { System.out.println("not found MaterialID=" + wk); fmat.add(mtbl.get(0)); // 仮に設定 } if ("{".equals(str)) Skip("}"); } } } } Close(); } // Material のセット public mats matset() { String wstr; mats mat = new mats(); mat.faceColor = new Color4f(FVal(), FVal(), FVal(), FVal()); mat.power = FVal(); mat.specularColor = new Color3f(FVal(), FVal(), FVal()); mat.emissiveColor = new Color3f(FVal(), FVal(), FVal()); NextRead(); wstr = token.nextToken(); if ("TextureFilename".equals(wstr)) { // Texture の設定 NextRead(); wstr = token.nextToken(); mat.image = loadImage(wstr); Skip("}"); // TextureFilename の終わり Skip("}"); // Material の終わり } return mat; } // Scene を生成 public void creatscene() { int i,j,cnt,pt,n; Point3f[] vw; // 頂点座標 TexCoord2f[] tex; // テクスチャ Vector3f[] nw = new Vector3f[0]; // 法線ベクトル pt= 0; // 多角形の先頭Index for(i=0; i<idx.size(); i++) // i=Frame(ポリゴン)の番号 { cnt= idx.get(i); // 多角形の角数 vw = new Point3f[cnt]; // Frame の頂点座標 tex = new TexCoord2f[cnt]; // Frame のテクスチャ座標 for(j=0; j<cnt; j++) { n= xvp.get(pt+j); // 頂点Index if (n<vp.size()) vw[j]= vp.get(n); else System.out.print("頂点Index Error=" + n); if (n<vt.size()) { tex[j]= new TexCoord2f(); tex[j].x= vt.get(n).x; tex[j].y= 1.0f-vt.get(n).y; } else System.out.print("Texture Index Error=" + n); } if (0<xvn.size()) { nw = new Vector3f[cnt]; for(j=0; j<cnt; j++) { n= xvn.get(pt+j); // 法線Index if (n<vn.size()) nw[j]= vn.get(n); } } if (vn.size()<1) nw= null; if (vt.size()<1) tex= null; n= fidx.get(i); // マテリアルの Index if (n>=fmat.size()) n= 0; face(Rot,vw,nw,fmat.get(n),tex); pt+= cnt; } } // Face(Polygon) を生成 public void face(TransformGroup trans, Point3f[] vertices, Vector3f[] normal, mats mat, TexCoord2f[] texture) { int[] stripCount = new int[1]; Color4f[] colors = new Color4f[vertices.length]; stripCount[0] = vertices.length; for(int i=0; i<vertices.length; i++) colors[i]= mat.faceColor; // Face を作成 GeometryInfo ginfo = new GeometryInfo(GeometryInfo.POLYGON_ARRAY); ginfo.setCoordinates(vertices); ginfo.setStripCounts(stripCount); ginfo.setColors(colors); // Texture の設定 if (mat.image!=null && texture!=null) { ginfo.setTextureCoordinateParams(1,2); // 二次元のテクスチャ座標を一枚使う ginfo.setTextureCoordinates(0,texture); // 参照する次元(二次元のテクスチャ=0) } // 法線ベクトルの設定 if (normal!=null) ginfo.setNormals(normal); else { NormalGenerator gen = new NormalGenerator(); gen.generateNormals(ginfo); } // Material を設定して SceneBase に追加 Shape3D shape = new Shape3D(ginfo.getGeometryArray()); shape.setAppearance(createAppearance(mat)); trans.addChild(shape); } // Material の設定 private Appearance createAppearance(mats para) { Appearance ap = new Appearance(); Material mat = new Material(); Color3f cw= new Color3f(para.faceColor.x,para.faceColor.y,para.faceColor.z); mat.setDiffuseColor(cw); // 拡散反射による色 Color3f acw = new Color3f(cw.x*0.2f,cw.y*0.2f,cw.z*0.2f); mat.setAmbientColor(acw); // 環境光 mat.setShininess(para.power); // 輝度 mat.setSpecularColor(para.specularColor); // 鏡面反射 mat.setEmissiveColor(para.emissiveColor); // 発光 if (para.image!=null) // Texture の設定 { TextureLoader texload = new TextureLoader(para.image); Texture2D texture2d = (Texture2D)texload.getTexture(); ap.setTexture(texture2d); TextureAttributes txattr = new TextureAttributes(); txattr.setTextureMode(TextureAttributes.MODULATE); txattr.setTextureBlendColor(para.faceColor); ap.setTextureAttributes(txattr); } ap.setMaterial(mat); //※ 透明度の設定 //ap.setTransparencyAttributes(new TransparencyAttributes(TransparencyAttributes.BLENDED, 0.0f)); return ap; } // Line Read(BUF に入力) private boolean LineRead() { try { BUF = BR.readLine(); } catch(IOException e) { System.out.println(e); } if (BUF == null) { System.out.println("End of file"); return false; } return true; } // Next Read Line(/をスキップ, Token を設定) private boolean NextRead() { while(LineRead()) { if (BUF.length()>0 && BUF.charAt(0)!='/') { token = new StringTokenizer(BUF, " ,;\t", false); if (token.hasMoreTokens()) return true; } } return false; } // Next Float(BUF から次の値を取得) private float FVal() { if (token.hasMoreTokens()==false) if (NextRead()==false) return -1.0f; return Float.parseFloat(token.nextToken()); } // Next int(BUF から次の値を取得) private int Val() { if (token.hasMoreTokens()==false) if (NextRead()==false) return -1; return Integer.parseInt(token.nextToken()); } // key まで読み飛ばす private void Skip(String key) { String str; while(true) { if (token.hasMoreTokens()==false) if (NextRead()==false) return; str = token.nextToken(); if (str.equals(key)) return; } } // BUFferedReader Close public void Close() { try { BR.close(); } catch(IOException e) { System.out.println("File Close Error"); } } // BufferedImage の入力 public BufferedImage loadImage(String fileName) { BufferedImage img= null; String wk = fileName; if (wk.charAt(0)=='"') wk= fileName.substring(1,fileName.length()-1); try { URL u = new URL(PATH, wk); img = ImageIO.read(u); } catch (IOException e) { System.out.println("Image Open Error=" + fileName); } return img; } } |
TransformGroup Rot; // 回転 ・・・ // 回転の初期化 Rot = new TransformGroup(); Transform3D rotate = new Transform3D(); rotate.rotY(Math.PI); // Y 軸について180度回転 Rot.setTransform(rotate); Base.getSceneGroup().addChild(Rot); |
// 構造体 class mats { Color4f faceColor; float power; Color3f specularColor; Color3f emissiveColor; BufferedImage image; } |
// 頂点座標領域 ArrayList<TexCoord2f> vt = new ArrayList<TexCoord2f>(); // テクスチャ座標 // Material 領域 ArrayList<String> mid = new ArrayList<String>(); // mtbl の ID ArrayList<Mat> mtbl = new ArrayList<Mat>(); // Material Table // MaterialList 領域 ArrayList<Integer> fidx = new ArrayList<Integer>(); // face Index ArrayList<Mat> fmat = new ArrayList<Mat>(); // face Material |
if ("MeshTextureCoords".equals(str)) // テクスチャ座標 { ・・・ } if ("Material".equals(str)) // マテリアル { ・・・ } if ("MeshMaterialList".equals(str)) // マテリアルリスト { ・・・ } |
face(Rot,vw,nw,fmat.get(n),tex); |
tex[j]= new TexCoord2f(); tex[j].x= vt.get(n).x; tex[j].y= 1.0f-vt.get(n).y; |
// Face(Polygon) を生成 public void face(TransformGroup trans, Point3f[] vertices, Vector3f[] normal, mats mat, TexCoord2f[] texture) { ・・・ } |
// Material の設定 private Appearance createAppearance(mats para) { ・・・ } |