0

ボトムラインアップフロント

私の 3D オブジェクト (立方体の例) を立方体の両側に配置すると、1 つの三角形が正しくレンダリングされますが、反対側はそうではありません。

概要

Blender で作成した 3D オブジェクトを Android OpenGL ワールドにインポートしようとしています。

頂点、インデックス、そしてテクスチャ座標を読み取る独自のカスタム パーサーを作成しました。すべてのデータを問題なく読み取ることができ、テクスチャがなくても形状は完璧です。問題は、テクスチャ座標を読み込もうとすると、三角形の 1 つが正しくレンダリングされている間に、すべての面で三角形の 1 つが非常に台無しになることです。

これは、テクスチャ座標がブレンダーで生成される方法と関係があると思いますf 1/1 2/2 3/3 4/4.「テクスチャのインデックス」をリストするファイルの部分で、テクスチャがリストされている順序で並んでいないことに気付きました. それが問題でしょうか?テクスチャ インデックスがリストされている順序でテクスチャ バッファを構築すると、それは役に立ちますか?

私の .obj ファイル

# Blender v2.63 (sub 0) OBJ File: ''
# www.blender.org
mtllib untitled.mtl
o Cube
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -0.999999
v 0.999999 1.000000 1.000001
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
vt 0.000000 0.334353
vt 0.332314 0.333333
vt 0.333333 0.665647
vt 0.001020 0.666667
vt 1.000000 0.001019
vt 0.998981 0.333333
vt 0.666667 0.332314
vt 0.667686 0.000000
vt 1.000000 0.665647
vt 0.667686 0.666667
vt 0.666667 0.334353
vt 0.334353 0.666667
vt 0.333333 0.334353
vt 0.665647 0.333333
vt 0.666667 0.665647
vt 0.333333 0.332314
vt 0.001020 0.333333
vt 0.000000 0.001020
vt 0.332314 0.000000
vt 0.333333 0.001019
vt 0.665647 0.000000
vt 0.334353 0.333333
usemtl Material_golden_fur_by_Dwaoviel.jpg
s off
f 1/1 2/2 3/3 4/4
f 5/5 8/6 7/7 6/8
f 1/6 5/9 6/10 2/11
f 2/12 6/13 7/14 3/15
f 3/16 7/17 8/18 4/19
f 5/20 1/21 4/7 8/22

私のパーサーメソッド

public static Mesh createMesh(int resourceID)
{
    Mesh m = new Mesh();
    Scanner s;
    BufferedReader inputStream = null;
    
    ArrayList<Float> floats = new ArrayList<Float>();
    ArrayList<Short> indicies = new ArrayList<Short>();
    ArrayList<Float> textures = new ArrayList<Float>();
    ArrayList<Short> texturesindex = new ArrayList<Short>();
    try
    {
        inputStream = new BufferedReader(new InputStreamReader(context.getResources().openRawResource(resourceID)));
        s = new Scanner(inputStream);
        String line = inputStream.readLine();
        line = inputStream.readLine();
        line = inputStream.readLine();
        line = inputStream.readLine();
        line = inputStream.readLine();
        while(line.charAt(0) == 'v'&&line.charAt(1)!='t')
        {
            s = new Scanner(line);
            s.next();
            floats.add(s.nextFloat());
            floats.add(s.nextFloat());
            floats.add(s.nextFloat());
            line = inputStream.readLine();
        }
        while(line.charAt(0)=='v' && line.charAt(1)=='t')
        {
            s = new Scanner(line);
            s.next(); //read in "vt"
            textures.add(s.nextFloat());
            textures.add(s.nextFloat());
            line = inputStream.readLine();
        }
        line = inputStream.readLine();
        line = inputStream.readLine();
        while(line != null && line.charAt(0) == 'f')
        {
            s = new Scanner(line);
            s.useDelimiter("[ /\n]");
            String xx = s.next();
            int a,b,c,d;
            int e,f,g,h;
            
            a = s.nextShort();
        
            e = s.nextShort();
            
            b = s.nextShort();
            
            f = s.nextShort();
            
            c = s.nextShort();
            
            g = s.nextShort();
            
            d = s.nextShort();
            
            h = s.nextShort();
            
            indicies.add((short)a);
            indicies.add((short)b);
            indicies.add((short)c);
            indicies.add((short)a);
            indicies.add((short)c);
            indicies.add((short)d);
            line = inputStream.readLine();
        }       
        float[] vertex = new float[floats.size()];
        for(int i=0;i<vertex.length;i++)
        {
            vertex[i] = floats.get(i).floatValue();
        }
        short[] ind = new short[indicies.size()];
        for(int i=0;i<ind.length;i++)
        {
            ind[i] = (short) (indicies.get(i).shortValue()-1); //minus one because its 1 based in that program
        }
        float[] texture = new float[floats.size()];
        for(int i=0;i<texture.length;i++)
        {
            texture[i] = textures.get(i).floatValue();
        }
        m.constructVertexBuffer(vertex);
        m.constructIndexBuffer(ind);
        m.constructTextureBuffer(texture);
        
    } 
    catch (FileNotFoundException e)
    {
        e.printStackTrace();
    } 
    catch (IOException e)
    {
        e.printStackTrace();
    }

    return m;
}

このメソッドは基本的に、配列リストに存在するのと同じ数のテクスチャ UV 座標を読み込み、次に float 配列にデータを入力してから、OpenGL に必要なすべての ByteBuffer/FloatBuffer 処理を行うコンストラクト Texture Buffer メソッドを呼び出します。

私の施工方法

public void constructTextureBuffer(float[] texture)
{
    ByteBuffer vbb = ByteBuffer.allocateDirect(texture.length*4);
    vbb.order(ByteOrder.nativeOrder());
    textureBuffer = vbb.asFloatBuffer();
    textureBuffer.put(texture);
    textureBuffer.position(0);
}

これを解決するために私ができることについて何か考えがある人はいますか?

4

2 に答える 2

1

コードを正しく読み取れるかどうかはわかりませんが、問題は顔コマンド ('f'文字) の解析にあると思います。OBJ 仕様の内部またはwikiのobj 形式に関する記事を見ると、face コマンドは (あなたの場合) 形式でf v1/vt1 v2/vt2 v3/vt3 ...あり、最初に頂点座標インデックス (以前に読み込まれた頂点座標のリストに) '/'、次にテクスチャ座標インデックス (以前にロードしたテクスチャ座標のリストに追加します)。'f'コマンドが 1 つの面 (三角形、四角形など) を作成 した後、これらすべての頂点が 1 行に表示されます。

また、テクスチャ配列 (リスト) へのインデックスが以前に宣言されたのと同じ順序であるかどうかも問題ではありません。それは単なるインデックス (0 <= インデックス < リストのサイズ) です。

于 2012-12-14T15:08:59.080 に答える
0

世の中には、Android 用の優れた FOSS OpenGL エンジンがいくつかあります。あなたのコードが機能していない正確な理由を説明することはできませんが、Rajawali の OBJ パーサーが特に Blender からエクスポートされたモデルで非常にうまく機能することはわかっています。おそらく、彼らのコードでいくつかの手がかりを見つけることができます:

https://github.com/MasDennis/Rajawali/blob/master/src/rajawali/parser/ObjParser.java

編集: Rajawali でも、通常、次のような OBJ から 2 行を削除する必要があることも追加する必要があります usemtl Material_golden_fur_by_Dwaoviel.jpgs off

おそらくあなたのパーサーもそれらをうまく処理していませんか?

于 2013-01-29T19:49:13.793 に答える