5

私はあなたたちがそれを試してみないとうまく説明できないいくつかの問題に遭遇しました。

キューブを正しくロードできません。ただし、すべての軸でうまく回転させることができました。(複数の「軸」は「軸」ですか?)

照明や質感に挑戦したことはないので、まだモデルがわからないようでしたらごめんなさい。

これは現在のように見えます(自由に回転するモデルのスナップショット):

キューブのスナップショット。 深さはまだ表示されていません。

これは期待される結果です。

Blenderモデル。 期待が高すぎます、サー。

これは私のコードですGLSurfaceView.Renderer

package dd.ww;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.Matrix;

public class Render implements Renderer {

    private Context context;
    private Cube cube;

    private float[] modelViewProjectionMatrix = new float[16];
    private float[] projectionMatrix = new float[16];
    private float[] viewMatrix = new float[16];
    private float[] rotationMatrix = new float[16];
    private float angle = 0f;

    public Render(Context context) {
        this.context = context;
    }

    @Override
    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        GLES20.glClearColor(1f, 1f, 1f, 1f);
        cube = new Cube(context);
    }

    @Override
    public void onSurfaceChanged(GL10 unused, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
        float ratio = (float) width / (float) height;
        Matrix.frustumM(projectionMatrix, 0, -3f, 3f, -3f, 3f, 1f, 10f);
    }

    @Override
    public void onDrawFrame(GL10 unused) {
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        //Camera position
        Matrix.setLookAtM(viewMatrix, 0, 0f, 0f, -4f, 0f, 0f, 0f, 0f, 1f, 0f);
        // projection x view = modelView
        Matrix.multiplyMM(modelViewProjectionMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
        //Creating rotation matrix
        Matrix.setRotateM(rotationMatrix, 0, angle, 0f, 0f, -1f);
        //rotation x camera = modelView
        Matrix.multiplyMM(modelViewProjectionMatrix, 0, rotationMatrix, 0, modelViewProjectionMatrix, 0);
        Matrix.setRotateM(rotationMatrix, 0, angle, 0f, -1f, 0f);
        Matrix.multiplyMM(modelViewProjectionMatrix, 0, rotationMatrix, 0, modelViewProjectionMatrix, 0);
        Matrix.setRotateM(rotationMatrix, 0, angle, -1f, 0f, 0f);
        Matrix.multiplyMM(modelViewProjectionMatrix, 0, rotationMatrix, 0, modelViewProjectionMatrix, 0);

        cube.draw(modelViewProjectionMatrix);

        angle += 0.7f;
        if (angle > 360f)
            angle = 0f;
    }

}

これは、CubeクラスとそのOBJローダーのコードです。OBJローダーは、BlenderからエクスポートされたOBJモデルをロードするために使用されます(これは、Blenderに表示されるCubeの期待される結果です)。

package dd.ww;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import android.content.Context;
import android.content.res.AssetManager;
import android.opengl.GLES20;
import android.util.Log;

public class Cube {
    private Context context;
    private FloatBuffer vertexBuffer;
    private ShortBuffer indexBuffer;

    private int shaderProgram;

    //TODO: Go to Google Code, find OpenGL ES 2.0 Programming Guide source code, Android,
    //check in the ESShapes.java, and study the FloatBuffers...

    public Cube(Context c) {
        context = c;
        loadCube("cube/cube.obj");
    }

    private void loadCube(String filename) {

        ArrayList<Float> tempVertices = new ArrayList<Float>();
        //ArrayList<Float> tempNormals = new ArrayList<Float>();
        ArrayList<Short> vertexIndices = new ArrayList<Short>();
        //ArrayList<Short> normalIndices = new ArrayList<Short>();

        try {
            AssetManager manager = context.getAssets();
            BufferedReader reader = new BufferedReader(new InputStreamReader(manager.open(filename)));
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.startsWith("v")) {
                    tempVertices.add(Float.valueOf(line.split(" ")[1])); //vx
                    tempVertices.add(Float.valueOf(line.split(" ")[2])); //vy
                    tempVertices.add(Float.valueOf(line.split(" ")[3])); //vz
                }
                //              else if (line.startsWith("vn")) {
                //                  tempNormals.add(Float.valueOf(line.split(" ")[1])); //nx
                //                  tempNormals.add(Float.valueOf(line.split(" ")[2])); //ny
                //                  tempNormals.add(Float.valueOf(line.split(" ")[3])); //nz
                //              }
                else if (line.startsWith("f")) {

                    /*
                    vertexIndices.add(Short.valueOf(tokens[1].split("/")[0])); //first point of a face
                    vertexIndices.add(Short.valueOf(tokens[2].split("/")[0])); //second point
                    vertexIndices.add(Short.valueOf(tokens[3].split("/")[0])); //third point
                    normalIndices.add(Short.valueOf(tokens[1].split("/")[2])); //first normal
                    normalIndices.add(Short.valueOf(tokens[2].split("/")[2])); //second normal
                    normalIndices.add(Short.valueOf(tokens[3].split("/")[2])); //third
                     */
                    //                  for (int i = 1; i <= 3; i++) {
                    //                      //String[] s = tokens[i].split("/");
                    //                      vertexIndices.add(Short.valueOf());
                    //                      //normalIndices.add(Short.valueOf(s[2]));
                    //                  }

                    vertexIndices.add(Short.valueOf(line.split(" ")[1]));
                    vertexIndices.add(Short.valueOf(line.split(" ")[2]));
                    vertexIndices.add(Short.valueOf(line.split(" ")[3]));
                }
            }

            float[] vertices = new float[tempVertices.size()];
            for (int i = 0; i < tempVertices.size(); i++) {
                Float f = tempVertices.get(i);
                vertices[i] = (f != null ? f : Float.NaN);
            }

            short[] indices = new short[vertexIndices.size()];
            for (int i = 0; i < vertexIndices.size(); i++) {
                Short s = vertexIndices.get(i);
                indices[i] = (s != null ? s : 1);
            }

            vertexBuffer = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
            vertexBuffer.put(vertices).position(0);

            indexBuffer = ByteBuffer.allocateDirect(indices.length * 2).order(ByteOrder.nativeOrder()).asShortBuffer();
            indexBuffer.put(indices).position(0);


            int vertexShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
            GLES20.glShaderSource(vertexShader, vertexCode);
            GLES20.glCompileShader(vertexShader);
            int fragmentShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
            GLES20.glShaderSource(fragmentShader, fragmentCode);
            GLES20.glCompileShader(fragmentShader);

            shaderProgram = GLES20.glCreateProgram();
            GLES20.glAttachShader(shaderProgram, vertexShader);
            GLES20.glAttachShader(shaderProgram, fragmentShader);
            GLES20.glLinkProgram(shaderProgram);

            int[] linked = new int[1];
            GLES20.glGetProgramiv(shaderProgram, GLES20.GL_LINK_STATUS, linked, 0);
            if (linked[0] == 0){
                Log.d("DEBUG", "Shader code error.");
                Log.d("DEBUG", GLES20.glGetProgramInfoLog(shaderProgram));
                GLES20.glDeleteProgram(shaderProgram);
                return;
            }

            GLES20.glDeleteShader(vertexShader);
            GLES20.glDeleteShader(fragmentShader);




        }
        catch (Exception e) {
            Log.d("DEBUG", "Error.", e);
        }
    }

    private String vertexCode = "" +
            "attribute vec4 a_position;  \n" +
            "uniform mat4 mvpMatrix;     \n" +
            "void main() {               \n" +
            "   gl_Position = a_position * mvpMatrix;\n" +
            "}                           \n";

    private String fragmentCode = "" +
            "precision mediump float;                   \n" +
            "void main() {                              \n" +
            "   gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" +
            "}                                          \n";

    private int attribute_Position;
    private int uniform_mvpMatrix;

    public void draw(float[] mvpMatrix){
        GLES20.glUseProgram(shaderProgram);
        attribute_Position = GLES20.glGetAttribLocation(shaderProgram, "a_position");
        GLES20.glVertexAttribPointer(attribute_Position, 3, GLES20.GL_FLOAT, false, 3 * 4, vertexBuffer);
        GLES20.glEnableVertexAttribArray(attribute_Position);
        uniform_mvpMatrix = GLES20.glGetUniformLocation(shaderProgram, "mvpMatrix");
        GLES20.glUniformMatrix4fv(uniform_mvpMatrix, 1, false, mvpMatrix, 0);
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, indexBuffer.capacity(), GLES20.GL_UNSIGNED_SHORT, indexBuffer);
        GLES20.glDisableVertexAttribArray(attribute_Position);
    }
}

そして最後に、APKの添付ファイルがあります(Mediafireにアップロードされています。削除しないでください。ライセンスのないフリーウェアです)。添付されたAPKファイルは署名され、プロジェクトから直接エクスポートされ、Gingerbread以降でのみ実行できます。(これがOpenGL ES 2.0の目的です...): APKファイルへのMediafireダウンロードリンク。

誰かが私が間違っていることに気付くのを喜んで手伝ってくれるなら、私は私の人生の残りのために喜んでいるでしょう。ここでのこの質問は、私の問題が関連している可能性が40%あるSOで検索したときに見つけたものに最も近いものです。残念ながら、彼はまだモデルを歪めています。私が見つけた残りの質問はすべて、テクスチャが正しくレンダリングされない、モデルを変換するなどに関するもののようです。しかし、私と同じような問題のある質問を見つけるために最善を尽くします。

4

1 に答える 1

3

聖なる牛...

私はついにそれを機能させました。

スナップショット1

スナップショット2

問題は、OpenGLES2.0マトリックスがどのように機能するかです。

SOユーザーのTimからの引用:

mvpMatrix * mRotationMatrixである必要があると思いますが、その関数への入力および出力と同じ行列を使用することは想定されていないため、一時行列を使用する必要があります。Android.opengl.Matrix "同じfloat配列を結果、lhs、またはrhsに渡すことができます。ただし、結果要素がlhsまたはrhs要素のいずれかと重複する場合、結果要素の値は未定義です。" それでも問題が解決しない場合は、コード全体を投稿してください。

太字のテキストは、これを行うと次のことを意味します。

//Creating rotation matrix
Matrix.setRotateM(rotationMatrix, 0, angle, 0f, 0f, -1f);

//rotation x camera = modelView    
Matrix.multiplyMM(modelViewProjectionMatrix, 0, modelViewProjectionMatrix, 0, rotationMatrix, 0);

Matrix.setRotateM(rotationMatrix, 0, angle, 0f, -1f, 0f);
Matrix.multiplyMM(modelViewProjectionMatrix, 0, modelViewProjectionMatrix, 0, rotationMatrix, 0);

Matrix.setRotateM(rotationMatrix, 0, angle, -1f, 0f, 0f);
Matrix.multiplyMM(modelViewProjectionMatrix, 0, modelViewProjectionMatrix, 0, rotationMatrix, 0);

cube.draw(modelViewProjectionMatrix);

これは通常のように見えますが、立方体は歪んで見えます。理由は、lhsとrhsが結果の行列と同じであってはならないということです。

しかし、これを行う場合:

//Creating rotation matrix
Matrix.setRotateM(rotationMatrix, 0, angle, 0f, 0f, -1f);

//rotation x camera = modelView
float[] duplicateMatrix = Arrays.copyOf(modelViewProjectionMatrix, 16);

Matrix.multiplyMM(modelViewProjectionMatrix, 0, duplicateMatrix, 0, rotationMatrix, 0);

Matrix.setRotateM(rotationMatrix, 0, angle, 0f, -1f, 0f);
duplicateMatrix = Arrays.copyOf(modelViewProjectionMatrix, 16);
Matrix.multiplyMM(modelViewProjectionMatrix, 0, duplicateMatrix, 0, rotationMatrix, 0);

Matrix.setRotateM(rotationMatrix, 0, angle, -1f, 0f, 0f);
duplicateMatrix = Arrays.copyOf(modelViewProjectionMatrix, 16);
Matrix.multiplyMM(modelViewProjectionMatrix, 0, duplicateMatrix, 0, rotationMatrix, 0);

cube.draw(modelViewProjectionMatrix);

正しく表示されます。

から役立つヒントを見つけた場所。

そして、これが私が3人がこの質問を締めくくることに投票した理由に気づいたところです。彼らはそもそもこの質問に対する答えを知っていたに違いなく、私に自分で解決策を見つけてほしいと思っていました。彼らに帽子をかぶって...

私は神に誓います、これは私がついに克服した難しい問題です。2年間の無駄な人生が流れています...

于 2013-03-29T08:42:53.960 に答える