2016-10-19 4 views
0

バッファ付きリーダーを使用して1行ずつ読み込むObjファイルリーダーを作成します。各行を頂点にする必要があります。頂点に追加します。ArrayList面IはFaceオブジェクトを作成し、get(i)頂点ArrayListを作成し、別の2は "normal and UVs"をリストしてfacesリストに追加します。 これはコードAndroidのスピードBufferedReaderのreadラインとArrayListの追加と取得

public final void ctreateObject() { 
    float now = System.nanoTime(); 
    BufferedReader bufferReader = new BufferedReader(inputStreamReader); 
    String line; 
    try { 
     while ((line = bufferReader.readLine()) != null) {    
      if (line.startsWith("f")) { 
       processFLine(line); 
      } else if (line.startsWith("vn")) { 
       processVNLine(line); 
      } else if (line.startsWith("vt")) { 
       processVTLine(line); 
      } else if (line.startsWith("v")) { 
       processVLine(line); 
      } else if (line.startsWith("usemtl")) { 
       mtlName = line.split("[ ]+", 2)[1]; 
      } else if (line.startsWith("mtllib")) { 
       mtllib = line.split("[ ]+")[1]; 
      } else if (line.startsWith("g") || line.startsWith("o")) { 
       if (faces.size() > 0) { 
        List<Face> theFaces = new ArrayList<Face>(); 
        theFaces.addAll(faces); 
        Model model = new Model(id, theFaces, mtlName); 
        SharedData.models.add(model); 
        faces.clear(); 
       } 
      } 
      Log.i("line", line); 
      ln++; 
     } 
     if (faces.size() > 0) { 
      List<Face> theFaces = new ArrayList<Face>(); 
      theFaces.addAll(faces); 
      Model model = new Model(id, theFaces, mtlName); 
      SharedData.models.add(model); 
      faces.clear(); 
      vertices.clear(); 
      normals.clear(); 
      uvs.clear(); 
     } 
     inputStreamReader.close(); 
     bufferReader.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    Log.i("Line", String.valueOf(ln)); 
    Log.i("time", String.valueOf((System.nanoTime() - now)/1000000000)); 
} 

private void processVLine(String line) { 
    String[] tokens = line.split("[ ]+"); 
    vertices.add(new float[] { Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2]), Float.parseFloat(tokens[3]) }); 
} 

private void processVNLine(String line) { 
    String[] tokens = line.split("[ ]+"); 
    normals.add(new float[] { Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2]), Float.parseFloat(tokens[3]) }); 
} 

private void processVTLine(String line) { 
    String[] tokens = line.split("[ ]+"); 
    uvs.add(new float[] { Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2]) }); 
} 

private void processFLine(String line) { 
    String[] tokens = line.split("[ ]+"); 
    if (tokens.length == 4) { 
     makeFace3(tokens); 
    } 
} 

private void makeFace3(String[] tokens) { 
    if (tokens[1].matches("[0-9]+")) {// f: v 
     Face face = new Face(vertices.get(Integer.parseInt(tokens[1]) - 1), vertices.get(Integer.parseInt(tokens[2]) - 1), vertices.get(Integer.parseInt(tokens[1]) - 1)); 
     if (normals.size() > 0) { 
      face.setAn(normals.get(Integer.parseInt(tokens[1]) - 1)); 
      face.setBn(normals.get(Integer.parseInt(tokens[2]) - 1)); 
      face.setCn(normals.get(Integer.parseInt(tokens[3]) - 1)); 
     } 
     if (uvs.size() > 0) { 
      face.setAuv(uvs.get(Integer.parseInt(tokens[1]) - 1)); 
      face.setBuv(uvs.get(Integer.parseInt(tokens[2]) - 1)); 
      face.setCuv(uvs.get(Integer.parseInt(tokens[3]) - 1)); 
     } 
     faces.add(face); 
    } 
    if (tokens[1].matches("[0-9]+/[0-9]+")) { 
     Face face = new Face(vertices.get(Integer.parseInt(tokens[1].split("/")[0]) - 1), vertices.get(Integer.parseInt(tokens[2].split("/")[0]) - 1), vertices.get(Integer.parseInt(tokens[3].split("/")[0]) - 1)); 
     if (normals.size() > 0) { 
      face.setAn(normals.get(Integer.parseInt(tokens[1].split("/")[0]) - 1)); 
      face.setBn(normals.get(Integer.parseInt(tokens[2].split("/")[0]) - 1)); 
      face.setCn(normals.get(Integer.parseInt(tokens[3].split("/")[0]) - 1)); 
     } 
     if (uvs.size() > 0) { 
      face.setAuv(uvs.get(Integer.parseInt(tokens[1].split("/")[1]) - 1)); 
      face.setBuv(uvs.get(Integer.parseInt(tokens[2].split("/")[1]) - 1)); 
      face.setCuv(uvs.get(Integer.parseInt(tokens[3].split("/")[1]) - 1)); 
     } 
     faces.add(face); 
    } 
    if (tokens[1].matches("[0-9]+//[0-9]+")) {// f: v//vn 
     Face face = new Face(vertices.get(Integer.parseInt(tokens[1].split("/")[0]) - 1), vertices.get(Integer.parseInt(tokens[2].split("/")[0]) - 1), vertices.get(Integer.parseInt(tokens[3].split("/")[0]) - 1)); 
     if (uvs.size() > 0) { 
      face.setAuv(uvs.get(Integer.parseInt(tokens[1].split("/")[0]) - 1)); 
      face.setBuv(uvs.get(Integer.parseInt(tokens[2].split("/")[0]) - 1)); 
      face.setCuv(uvs.get(Integer.parseInt(tokens[3].split("/")[0]) - 1)); 
     } 
     if (normals.size() > 0) { 
      face.setAn(normals.get(Integer.parseInt(tokens[1].split("/")[2]) - 1)); 
      face.setBn(normals.get(Integer.parseInt(tokens[2].split("/")[2]) - 1)); 
      face.setCn(normals.get(Integer.parseInt(tokens[3].split("/")[2]) - 1)); 
     } 
     faces.add(face); 
    } 
    if (tokens[1].matches("[0-9]+/[0-9]+/[0-9]+")) { 
     Face face = new Face(vertices.get(Integer.parseInt(tokens[1].split("/")[0]) - 1), vertices.get(Integer.parseInt(tokens[2].split("/")[0]) - 1), vertices.get(Integer.parseInt(tokens[3].split("/")[0]) - 1)); 
     if (uvs.size() > 0) { 
      face.setAuv(uvs.get(Integer.parseInt(tokens[1].split("/")[1]) - 1)); 
      face.setBuv(uvs.get(Integer.parseInt(tokens[2].split("/")[1]) - 1)); 
      face.setCuv(uvs.get(Integer.parseInt(tokens[3].split("/")[1]) - 1)); 
     } 
     if (normals.size() > 0) { 
      face.setAn(normals.get(Integer.parseInt(tokens[1].split("/")[2]) - 1)); 
      face.setBn(normals.get(Integer.parseInt(tokens[2].split("/")[2]) - 1)); 
      face.setCn(normals.get(Integer.parseInt(tokens[3].split("/")[2]) - 1)); 
     } 
     faces.add(face); 
    } 
} 

問題はパフォーマンスであり、それはファイルが約120,000行を含むファイルが複雑であれば、このプロセスは、私はそのような多くのモデルをロードしたいので、長すぎる約90秒かかりますです850,000行の処理には約280秒がかかりますが、BufferReaderは非常に高速にスキャンすることができますが、ArrayList処理では遅く処理されますが、私はLinkedListをテストしましたが、結果は恐ろしい "5倍遅く"でしたこれを行うためにメソッドや別の解決策を使用できますか?後で、顔を反復してArrayListにバッファを作成し、OpenGLに渡します。私は同じ12万線でVectorを使用

編集は、(20秒ArrayListより増加)

+0

'BufferedReader.readLine()'を使用すると、毎秒何百万行も読むことができます。 'ArrayList'の性能はJavadocで定義されています。あなたの問題はほぼ確実に7つの「条件」です。あなたが何を求めているのか不明です。 – EJP

+0

はい、私は問題がBufferedReaderにないことを知っています。私はファイルを読み込んでテストし、各行を実際に非常に高速で印刷しています。私はこれらの条件でarraylistやヒントよりも早くFaceのコレクションを取得できますか?私のコードを実行する、私は間違った方法で何かを使用するかもしれない – Mohamed

+0

あなたは問題がバッファリングされたリードではないが、あなたのタイトル、あなたの質問、およびあなたのタグにそれを言及することを知っている。どうして?あなたのタイトル、あなたの質問、あなたのタグを実際に何が関係があるものにすることを考えましたか? – EJP

答えて

1

BufferedReaderArrayListが問題ではない結果が109秒であるファイル。

パフォーマンスの問題は、基本的に割り当てと解析の2つの問題になります。

解析 - パートI

String[] tokens = line.split("[ ]+"); 

あなたは正規表現を使用して文字列をトークン化されています。これは、ラインをトークンに分割する最も遅い方法です。あなたは自分自身で文字列を繰り返し、トークンを構築することでこれをスピードアップすることができます。これは、「ローハンドの果物」です。これは、大きなスピードアップをもたらす小さな変化です。

if (tokens[1].matches("[0-9]+")) {// f: v 

再度、正規表現を使用します。これはあなたを遅くしています。

解析 - パートII

は、なぜあなたは既に解析されたものを再解析していますか?

Face face = new Face(vertices.get(Integer.parseInt(tokens[1]) - 1), vertices.get(Integer.parseInt(tokens[2]) - 1), vertices.get(Integer.parseInt(tokens[1]) - 1)); 
    if (normals.size() > 0) { 
     face.setAn(normals.get(Integer.parseInt(tokens[1]) - 1)); 
     face.setBn(normals.get(Integer.parseInt(tokens[2]) - 1)); 
     face.setCn(normals.get(Integer.parseInt(tokens[3]) - 1)); 
    } 

Integer.parseInt(tokens[x]) - 1に重複して電話をかけています。結果をintに入れ、それを使用するだけです。

配分

あなたがnewオペレータを呼び出している回数を見てください。すべてのオブジェクトの割り当ては、パフォーマンス面でコストがかかります。ループ内のすべてのnewオペレータを見て、次のように質問します。これを一度に行う方法はありますか?たとえば、各頂点はfloat[3]です。 new float[3]を何度も繰り返し呼び出すのではなく、試用値から始めて、new float[numVertices][3]を一度だけ呼び出すことはできますか?それはすべての状況で実行可能ではないかもしれませんが、new呼び出しを減らす機会を探してください。

ArrayListに関連しています。 ArrayListを使用してオブジェクトを蓄積するのは簡単ですが、あまり効率的ではありません。配列が最大になるたびに、新しい配列を割り当て、既存のすべてのデータを配列にコピーする必要があることを覚えておいてください。

このOBJファイル形式は、頂点、座標、ベクトルなどをダンプする点であまり面倒ではありません。ここで非常に役立つはずです。

+0

はい、これは完璧な答えです。私の時間を救ってくれてありがとう、また私はこの答えから素晴らしいアイデアを得ることができます。 – Mohamed

+1

私はあなたの偉大な答えにすべての指示に従って、私は驚くべき結果、180.000行を持っていて、90秒でロードされていた同じファイルが今7秒でロードされている、ありがとう。 – Mohamed

関連する問題