2017-05-01 12 views
0

3Dエンジンを作成してOBJ LoaderClassがより複雑なモデルで問題を抱えているようです。OBJ Loader IndexOutOfBounds

私はIndexOutOfBoundsExceptionを取得していますが、その理由を理解できません。 インデックス3522上のArrayListテクスチャの値がこの例外を引き起こすようですが、なぜですか?私は例外の前に取得し、最後のベクトルである

System.out.println(textures.get(Integer.parseInt(vertexData[1])-1)); 

私は介して、毎回テクスチャ値を読み出すときはここ

は私のOBJローダークラス

 package graphics.renderEngine; 

    import java.io.BufferedReader; 
    import java.io.File; 
    import java.io.FileNotFoundException; 
    import java.io.FileReader; 
    import java.util.ArrayList; 
    import java.util.List; 

    import org.joml.Vector2f; 
    import org.joml.Vector3f; 

    import graphics.models.RawModel; 

    public class OBJLoader 
    { 

     public static RawModel loadObjModel(String fileName, Loader loader) 
     { 
      FileReader fr = null; 
      try 
      { 
       fr = new FileReader(new File("Ressources/Models/"+fileName+".obj")); 
      } 
      catch (FileNotFoundException e) 
      { 
       System.err.println("Could not load File!"); 
       e.printStackTrace(); 
      } 
      BufferedReader reader = new BufferedReader(fr); 
      String line; 
      List<Vector3f> vertices = new ArrayList<Vector3f>(); 
      List<Vector2f> textures = new ArrayList<Vector2f>(); 
      List<Vector3f> normals = new ArrayList<Vector3f>(); 
      List<Integer> indices = new ArrayList<Integer>(); 
      float[] verticesArray = null; 
      float[] normalsArray = null; 
      float[] texturesArray = null; 
      int[] indicesArray = null; 

      try 
      { 
       while(true) 
       { 
        line = reader.readLine(); 
        String[] currentLine = line.split(" "); 
        if(line.startsWith("v ")) 
        { 
         Vector3f vertex = new Vector3f(Float.parseFloat(currentLine[1]),Float.parseFloat(currentLine[2]), Float.parseFloat(currentLine[3])); 
         vertices.add(vertex); 
        } 
        else if(line.startsWith("vt ")) 
        { 
         Vector2f texture = new Vector2f(Float.parseFloat(currentLine[1]), Float.parseFloat(currentLine[2])); 
         textures.add(texture); 
        } 
        else if(line.startsWith("vn ")) 
        { 
         Vector3f normal = new Vector3f(Float.parseFloat(currentLine[1]),Float.parseFloat(currentLine[2]), Float.parseFloat(currentLine[3])); 
         normals.add(normal); 
        } 
        else if(line.startsWith("f ")) 
        { 
         texturesArray = new float[vertices.size()*2]; 
         normalsArray = new float[vertices.size()*3]; 
         break; 
        } 
       } 

       while(line != null) 
       { 
        if(!line.startsWith("f ")) 
        { 
         line = reader.readLine(); 
         continue; 
        } 
        String[] currentLine = line.split(" "); 
        String[] vertex1 = currentLine[1].split("/"); 
        String[] vertex2 = currentLine[2].split("/"); 
        String[] vertex3 = currentLine[3].split("/"); 

        processVertex(vertex1, indices, textures, normals, texturesArray, normalsArray); 
        processVertex(vertex2, indices, textures, normals, texturesArray, normalsArray); 
        processVertex(vertex3, indices, textures, normals, texturesArray, normalsArray); 
        line = reader.readLine(); 
       } 
       reader.close(); 

      } 
      catch(Exception e) 
      { 
       e.printStackTrace(); 
      } 

      verticesArray = new float[vertices.size()*3]; 
      indicesArray = new int[indices.size()]; 

      int vertexPointer = 0; 
      for (Vector3f vertex:vertices) 
      { 
       verticesArray[vertexPointer++] = vertex.x; 
       verticesArray[vertexPointer++] = vertex.y; 
       verticesArray[vertexPointer++] = vertex.z; 
      } 

      for(int i=0;i<indices.size();i++) 
      { 
       indicesArray[i] = indices.get(i); 

      } 
      return 
        loader.loadToVAO 
        (verticesArray, 
          texturesArray, 
          normalsArray, 
          indicesArray); 

     } 

     private static void processVertex(String[] vertexData, List<Integer> indices, List<Vector2f> textures, List<Vector3f> normals, float[] textureArray, float[] normalsArray) 
     { 
      System.out.println(textures.get(3522)); 
      int currentvertexPointer = Integer.parseInt(vertexData[0]) -1; 
      indices.add(currentvertexPointer); 
      Vector2f currentTex = textures.get(Integer.parseInt(vertexData[1])-1); 
      textureArray[currentvertexPointer*2] = currentTex.x; 
      textureArray[currentvertexPointer*2+1] = 1 - currentTex.y; 
      Vector3f currentNorm = normals.get(Integer.parseInt(vertexData[2])-1); 
      normalsArray[currentvertexPointer*3] = currentNorm.x; 
      normalsArray[currentvertexPointer*3+1] = currentNorm.y; 
      normalsArray[currentvertexPointer*3+2] = currentNorm.z; 
     } 
} 

This is the OBJFile of the Model im trying to load

です

(4.260E-1 1.275E-1) 
(4.650E-1 1.664E-1) 
(4.706E-1 1.621E-1) 
(4.650E-1 1.664E-1) 
(4.925E-1 2.140E-1) 
(1.340E-1 8.170E-2) 
(1.947E-1 4.650E-2) 
(1.902E-1 3.560E-2) 

OBJファイルを見た後、最後の2つを除いて、私は順番に見つけることができません。ここで

java.lang.IndexOutOfBoundsException: Index: 3522, Size: 3522 
    at java.util.ArrayList.rangeCheck(Unknown Source) 
    at java.util.ArrayList.get(Unknown Source) 
    at graphics.renderEngine.OBJLoader.processVertex(OBJLoader.java:122) 
    at graphics.renderEngine.OBJLoader.loadObjModel(OBJLoader.java:82) 
    at main.Main.init(Main.java:150) 
    at main.Main.<init>(Main.java:82) 
    at main.Main.main(Main.java:75) 

イムだけ困惑を取得例外イムで、私はこの例外を取得する理由は、リストのいずれかの手がかりのための事前のおかげ

+0

となりますための最も簡単なパスを持っていないことを推測しています](https://github.com/java-graphics/assimp)私たちはassimpのjvmポートを持っており、objは既にサポートされています – elect

答えて

1

サイズは3522とされている見当がつかない0から3521までの範囲のインデックス値を持ちますが、リスト内の要素にアクセスするために存在しないインデックス(3522)を使用しようとしています。リスト要素にアクセスする前に、インデックスがサイズより小さいかどうかをチェックする条件が必要です。

+0

\t \t if(textures.size()> Integer.parseInt(vertexData [1] ]) - 1) \t \t { \t \t \t currentTex = textures.get(Integer.parseInt(vertexData [1]) - 1); \t \t}? – Spytrycer

+0

はいそうです。 – OTM

+0

私はこれを試した後、次のすべての配列から複数のOutOfBounds例外を取得しました。私はこれらの例外のすべてにそれをしなければならないと仮定して、私はやったが、半分もロードされていないと終わった。 – Spytrycer

1

実際の問題は、最初に 'f'(面)宣言が表示されたら、 'v'、 'vt'および 'vn'宣言の読み込みを中止することです。 Wavefront OBJ仕様では、 'v *'宣言が 'f'宣言の前に来る必要があると述べていないため、これを行うことはできません。実際、あなたのサンプルファイルでは、それらは混在しています。 つまり、最初のループで 'v *'宣言の読み込みを停止すると、読んでいない他の 'v *'宣言を参照する 'f'宣言が見つかるため、IndexOutOfBounds例外が発生します。 いつでも「v *」と「f」の宣言を読むことができるように、ループを再構成する必要があります。あなたはhttps://www.youtube.com/user/ThinMatrix

のチュートリアルチュートリアルは結構ですが、次のされているように見えます

0

。それは完全に動作します。 (私は前にそれを使用している)

問題

は、問題は彼のOBJLoaderは、彼が選んだのOBJファイルの形式に特有のものであり、「万能」OBJ-ローダーではないということです。

彼の書式は以下の通りです: V/VT/VN/F/EOF

あなたがより多くのようであるのに対し: V/VT/VN/F/V/VT/VN/F/.../EOF

あなたが投稿したコードでは、 'f'の最初の行が見つかると、それ以上の頂点データはなく、後で顔データのみが存在すると仮定しています。

したがって、コードはすべての頂点データを受け取っていないので、そのデータにインデックスを作成しようとするとそこにはありません。

修正

これには2つの可能な解決策があります。

  1. が、それはファイルからのデータのすべてを受け入れることを可能にすることにより、より一般的な意味で動作するようにあなたのコードを再構成し、バッファーにロードしてください。
  2. ThinMatrixで概説された形式の中にOBJファイルが正しく配置されるように、OBJファイルを再構成します。最も簡単な方法はおそらくコピー/ペーストすることですが、あなたのためにこれを行うプログラムを作成することができます。

私はあなたがトピックに関連するチュートリアルを次されているので、あなたはここで、[、それで多くの経験や興味を持った場合は、ソリューション番号2