android opengl 从 .obj 文件绘制 3d 模型

标签 android opengl-es .obj

这是我从这个链接获得的模型类 OpenGL ES Tools for Android我对它做了一些修改。这个类成功地从 .obj 文件中加载了 obj 数据,如顶点、法线、textcoords 和索引。

类模型

public class Model {

    // Constants
    private static final int FLOAT_SIZE_BYTES = 4;
    private static final int SHORT_SIZE_BYTES = 2;

    private FloatBuffer _vb;
    private FloatBuffer _nb;
    private ShortBuffer _ib;
    private FloatBuffer _tcb;

    private short[] indices;

    private float[] tempV;
    private float[] tempVt;
    private float[] tempVn;

    private ArrayList<Vector3D> vertices;
    private ArrayList<Vector3D> vertexTexture;
    private ArrayList<Vector3D> vertexNormal;
    private ArrayList<Face> faces;
    private int vertexCount;

    private ArrayList<GroupObject> groupObjects;

    class Vector3D {

        float x, y, z;

        public Vector3D(float parseFloat, float parseFloat2, float parseFloat3) {
            x = parseFloat;
            y = parseFloat2;
            z = parseFloat3;
        }

        public float getX() {

            return x;
        }

        public float getY() {

            return y;
        }

        public float getZ() {

            return z;
        }



}

类人脸

class Face {

            public ArrayList<Vector3D> getVertices() {

                return vertices;
            }

            public ArrayList<Vector3D> getUvws() {

                return vertexTexture;
            }

            public ArrayList<Vector3D> getNormals() {

                return vertexNormal;
            }

        }

GroupObject 类

class GroupObject {

        String objectName;

        public void setObjectName(String string) {
            this.objectName = string;
        }

        public String getObjectName() {
            return objectName;
        }

    }

    // Android Stuff!
    private Context context;
    private int modelID;

    public Model(int modelID, Context activity) {
        this.vertices = new ArrayList<Vector3D>();
        this.vertexTexture = new ArrayList<Vector3D>();
        this.vertexNormal = new ArrayList<Vector3D>();
        this.faces = new ArrayList<Face>();

        this.groupObjects = new ArrayList<GroupObject>();

        this.modelID = modelID;
        this.context = activity;

        loadFile();
    }

    private int loadFile() {
        InputStream inputStream = context.getResources().openRawResource(
                modelID);

        BufferedReader in = new BufferedReader(new InputStreamReader(
                inputStream));

        try {
            loadOBJ(in);
            Log.d("LOADING FILE", "FILE LOADED SUCESSFULLY====================");
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return 1;
    }

    private void loadOBJ(BufferedReader in) throws IOException {
        Log.d("LOADING FILE", "STARTING!====================");
        GroupObject defaultObject = new GroupObject();
        GroupObject currentObject = defaultObject;

        this.groupObjects.add(defaultObject);

        String Line; // Stores ever line we read!
        String[] Blocks; // Stores string fragments after the split!!
        String CommandBlock; // Stores Command Blocks such as: v, vt, vn, g,
                                // etc...

        while ((Line = in.readLine()) != null) {
            Blocks = Line.split(" ");
            CommandBlock = Blocks[0];

            // Log.d("COMMAND BLOCK" , "---------- " + CommandBlock +
            // " ----------");

            if (CommandBlock.equals("g")) {
                if (Blocks[1] == "default")
                    currentObject = defaultObject;
                else {
                    GroupObject groupObject = new GroupObject();
                    groupObject.setObjectName(Blocks[1]);
                    currentObject = groupObject;
                    groupObjects.add(groupObject);
                }
            }

            if (CommandBlock.equals("v")) {
                Vector3D vertex = new Vector3D(Float.parseFloat(Blocks[1]),
                        Float.parseFloat(Blocks[2]),
                        Float.parseFloat(Blocks[3]));
                this.vertices.add(vertex);
                // Log.d("VERTEX DATA", " " + vertex.getX() + ", " +
                // vertex.getY() + ", " + vertex.getZ());
            }

            if (CommandBlock.equals("vt")) {
                Vector3D vertexTex = new Vector3D(Float.parseFloat(Blocks[1]),
                        Float.parseFloat(Blocks[2]), 0.0f);
                this.vertexTexture.add(vertexTex);
                // Log.d("TEXTURE DATA", " " + vertexTex.getX() + ", " +
                // vertexTex.getY() + ", " + vertexTex.getZ());
            }

            if (CommandBlock.equals("vn")) {
                Vector3D vertexNorm = new Vector3D(Float.parseFloat(Blocks[1]),
                        Float.parseFloat(Blocks[2]),
                        Float.parseFloat(Blocks[3]));
                this.vertexNormal.add(vertexNorm);
                // Log.d("NORMAL DATA", " " + vertexNorm.getX() + ", " +
                // vertexNorm.getY() + ", " + vertexNorm.getZ());
            }

            if (CommandBlock.equals("f")) {
                Face face = new Face();
                faces.add(face);

                String[] faceParams;

                for (int i = 1; i < Blocks.length; i++) {
                    faceParams = Blocks[i].split("/");

                    face.getVertices()
                            .add(this.vertices.get(Integer
                                    .parseInt(faceParams[0]) - 1));

                    if (faceParams[1] == "") {
                    } else {
                        face.getUvws().add(
                                this.vertexTexture.get(Integer
                                        .parseInt(faceParams[1]) - 1));
                        face.getNormals().add(
                                this.vertexNormal.get(Integer
                                        .parseInt(faceParams[2]) - 1));
                    }
                }
            }
        }

        // fillInBuffers();
        fillInBuffersWithNormals();

        Log.d("OBJ OBJECT DATA", "V = " + vertices.size() + " VN = "
                + vertexTexture.size() + " VT = " + vertexNormal.size());

    }

    private void fillInBuffers() {

        int facesSize = faces.size();

        vertexCount = facesSize * 3;

        tempV = new float[facesSize * 3 * 3];
        tempVt = new float[facesSize * 2 * 3];
        indices = new short[facesSize * 3];

        for (int i = 0; i < facesSize; i++) {
            Face face = faces.get(i);
            tempV[i * 9] = face.getVertices().get(0).getX();
            tempV[i * 9 + 1] = face.getVertices().get(0).getY();
            tempV[i * 9 + 2] = face.getVertices().get(0).getZ();
            tempV[i * 9 + 3] = face.getVertices().get(1).getX();
            tempV[i * 9 + 4] = face.getVertices().get(1).getY();
            tempV[i * 9 + 5] = face.getVertices().get(1).getZ();
            tempV[i * 9 + 6] = face.getVertices().get(2).getX();
            tempV[i * 9 + 7] = face.getVertices().get(2).getY();
            tempV[i * 9 + 8] = face.getVertices().get(2).getZ();
            tempVt[i * 6] = face.getUvws().get(0).getX();
            tempVt[i * 6 + 1] = face.getUvws().get(0).getY();
            tempVt[i * 6 + 2] = face.getUvws().get(1).getX();
            tempVt[i * 6 + 3] = face.getUvws().get(1).getY();
            tempVt[i * 6 + 4] = face.getUvws().get(2).getX();
            tempVt[i * 6 + 5] = face.getUvws().get(2).getY();
            indices[i * 3] = (short) (i * 3);
            indices[i * 3 + 1] = (short) (i * 3 + 1);
            indices[i * 3 + 2] = (short) (i * 3 + 2);
        }

        _vb = ByteBuffer.allocateDirect(tempV.length * FLOAT_SIZE_BYTES)
                .order(ByteOrder.nativeOrder()).asFloatBuffer();
        _vb.put(tempV);
        _vb.position(0);

        _tcb = ByteBuffer.allocateDirect(tempVt.length * FLOAT_SIZE_BYTES)
                .order(ByteOrder.nativeOrder()).asFloatBuffer();
        _tcb.put(tempVt);
        _tcb.position(0);

        _ib = ByteBuffer.allocateDirect(indices.length * SHORT_SIZE_BYTES)
                .order(ByteOrder.nativeOrder()).asShortBuffer();
        _ib.put(indices);
        _ib.position(0);
    }

    private void fillInBuffersWithNormals() {

        int facesSize = faces.size();

        vertexCount = facesSize * 3;

        tempV = new float[facesSize * 3 * 3];
        tempVt = new float[facesSize * 2 * 3];
        tempVn = new float[facesSize * 3 * 3];
        indices = new short[facesSize * 3];

        for (int i = 0; i < facesSize; i++) {
            Face face = faces.get(i);
            tempV[i * 9] = face.getVertices().get(0).getX();
            tempV[i * 9 + 1] = face.getVertices().get(0).getY();
            tempV[i * 9 + 2] = face.getVertices().get(0).getZ();
            tempV[i * 9 + 3] = face.getVertices().get(1).getX();
            tempV[i * 9 + 4] = face.getVertices().get(1).getY();
            tempV[i * 9 + 5] = face.getVertices().get(1).getZ();
            tempV[i * 9 + 6] = face.getVertices().get(2).getX();
            tempV[i * 9 + 7] = face.getVertices().get(2).getY();
            tempV[i * 9 + 8] = face.getVertices().get(2).getZ();

            tempVn[i * 9] = face.getNormals().get(0).getX();
            tempVn[i * 9 + 1] = face.getNormals().get(0).getY();
            tempVn[i * 9 + 2] = face.getNormals().get(0).getZ();
            tempVn[i * 9 + 3] = face.getNormals().get(1).getX();
            tempVn[i * 9 + 4] = face.getNormals().get(1).getY();
            tempVn[i * 9 + 5] = face.getNormals().get(1).getZ();
            tempVn[i * 9 + 6] = face.getNormals().get(2).getX();
            tempVn[i * 9 + 7] = face.getNormals().get(2).getY();
            tempVn[i * 9 + 8] = face.getNormals().get(2).getZ();

            tempVt[i * 6] = face.getUvws().get(0).getX();
            tempVt[i * 6 + 1] = face.getUvws().get(0).getY();
            tempVt[i * 6 + 2] = face.getUvws().get(1).getX();
            tempVt[i * 6 + 3] = face.getUvws().get(1).getY();
            tempVt[i * 6 + 4] = face.getUvws().get(2).getX();
            tempVt[i * 6 + 5] = face.getUvws().get(2).getY();

            indices[i * 3] = (short) (i * 3);
            indices[i * 3 + 1] = (short) (i * 3 + 1);
            indices[i * 3 + 2] = (short) (i * 3 + 2);
        }

        _vb = ByteBuffer.allocateDirect(tempV.length * FLOAT_SIZE_BYTES)
                .order(ByteOrder.nativeOrder()).asFloatBuffer();
        _vb.put(tempV);
        _vb.position(0);

        _tcb = ByteBuffer.allocateDirect(tempVt.length * FLOAT_SIZE_BYTES)
                .order(ByteOrder.nativeOrder()).asFloatBuffer();
        _tcb.put(tempVt);
        _tcb.position(0);

        _nb = ByteBuffer.allocateDirect(tempVn.length * FLOAT_SIZE_BYTES)
                .order(ByteOrder.nativeOrder()).asFloatBuffer();
        _nb.put(tempVn);
        _nb.position(0);

        _ib = ByteBuffer.allocateDirect(indices.length * SHORT_SIZE_BYTES)
                .order(ByteOrder.nativeOrder()).asShortBuffer();
        _ib.put(indices);
        _ib.position(0);
    }

    public FloatBuffer getVertices() {
        return _vb;
    }

    public FloatBuffer getTexCoords() {
        return _tcb;
    }

    public ShortBuffer getIndices() {
        return _ib;
    }

    public FloatBuffer getNormals() {
        return _nb;
    }
}

我的问题是,在 opengl 中的何处以及如何传递或使用我从模型类获得的数据(顶点、法线、文本坐标和索引..)。这是我在绘制函数中所做的。它是现在正确绘制对象。我是 opengl 的新手,我认为这里做错了什么(在绘制函数中)任何帮助将不胜感激。提前致谢。

MyObjModel 类

Class MyObjModel
{

  // global buffers

    FloatBuffer mVertexBuffer;
    FloatBuffer mTextureBuffer;
    FloatBuffer mNormalBuffer;
    ShortBuffer mIndices;

public MyObjModel()

{

//penguin_obj is .obj file which is exported from blender

  Model model = new Model(R.raw.penguin_obj,
                activity);

        mVertexBuffer = model.getVertices();
        mTextureBuffer = model.getTexCoords();
        mNormalBuffer = model.getNormals();
        mIndices = model.getIndices();
}

public void draw(GL10 gl) {

        gl.glVertexPointer(3, GL10.GL_FIXED, 0, mVertexBuffer);

        gl.glEnable(GL10.GL_TEXTURE_2D); // workaround bug 3623
        gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, mTextureBuffer);
        gl.glNormalPointer(1, GL10.GL_FIXED, mNormalBuffer);
        // gl.glColor4f(1, 1, 1, 1);
        // gl.glNormal3f(0, 0, 1);
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, mVertexBuffer.limit());
}

}

最佳答案

您没有在绘制方法中启用顶点数组。添加这个:

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

关于android opengl 从 .obj 文件绘制 3d 模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21879563/

相关文章:

javascript - 使用 JavaScript 解析 .obj 3D 图形文件

java - 管理 RecyclerView 中 View 的回收方式

java - 错误 : picked up java_options: -Djava.net.preferIPv4Stack=true

android - react-native在Android上运行教程 'AwesomeProject'结果 'Unable to download JS Bundle'红屏

链接期间 Android NDK undefined reference

iphone - Opengl 着色器问题 - 奇怪的光反射伪影

android - 使用 GLSurfaceView 捏合缩放

iphone - 将 GLKView 与 UIViewController 一起使用

java - OpenGL:模型显示不正确。 (需要固定绘制距离吗?)

python - 如何在 python 中从 .obj 文件获取坐标?