0

我一直在尝试将我之前编写的使用显示列表的 OBJ 解析器转换为使用 VBO,并试图看看我是否可以在没有任何外部帮助的情况下自己解决这个问题,但现在我想我一直在看代码太长,找不到任何错误。

这是一个 Android 应用程序,通过 OpenGLES 2.0,我最终在屏幕上出现了一些三角形,但根本不在正确的位置。我有一种感觉,我尝试根据单个索引列表获取每个面的所有元素是不正确的,我最终只是把所有东西都乱七八糟地扔掉了,但我找不到我的错误。

本质上,由于 OBJ 格式为顶点、纹理坐标和法线向量提供了单独的索引,因此我最终得到了 3 个彼此完全乱序的数据列表,但 VBO 基于单个引用每个部分索引列表。

这是我的代码,以帮助某人帮助我:

OBJ工具包:

public class OBJToolkit {
    public static Mesh loadOBJ(String modelLocation) throws FileNotFoundException, IOException
    {
        Log.d("OBJToolkit", "Location searched for model: " + modelLocation);

        ArrayList<Float> allVertices = new ArrayList<Float>();
        ArrayList<Float> allTextureCoors = new ArrayList<Float>();
        ArrayList<Float> allNormals = new ArrayList<Float>();

        ArrayList<Face> faces = new ArrayList<Face>();

        BufferedReader reader = new BufferedReader(new FileReader(new File(modelLocation)));

        Mesh mesh = new Mesh();

        Log.d("OBJToolkit", "About to read the contents of the model");
        while (reader.ready())
        {
            String line = reader.readLine();

            if (line == null)
                break;

            if (line.startsWith("v "))
            {
                allVertices.add(Float.valueOf(line.split(" ")[1]));
                allVertices.add(Float.valueOf(line.split(" ")[2]));
                allVertices.add(Float.valueOf(line.split(" ")[3]));
            }

            if (line.startsWith("vt "))
            {
                allTextureCoors.add(Float.valueOf(line.split(" ")[1]));
                allTextureCoors.add(Float.valueOf(line.split(" ")[2]));
            }

            if (line.startsWith("vn "))
            {
                allNormals.add(Float.valueOf(line.split(" ")[1]));
                allNormals.add(Float.valueOf(line.split(" ")[2]));
                allNormals.add(Float.valueOf(line.split(" ")[3]));
            }

            if (line.startsWith("f "))
            {
                Face f = new Face();
                String[] lineArray = line.split(" ");

                for (int index = 1; index < lineArray.length; index++)
                {
                    String[] valueArray = lineArray[index].split("/");
                    f.addVertexIndex(Integer.valueOf(valueArray[0]));
                    if (valueArray.length > 1)
                        f.addTextureIndex(Integer.valueOf(valueArray[1]));
                    if (valueArray.length > 2)
                        f.addNormalIndex(Integer.valueOf(valueArray[2]));
                }
                faces.add(f);
            }
        }
        reader.close();

        ArrayList<Float> verticesInOrder = new ArrayList<Float>();
        ArrayList<Integer> indicesInOrder = new ArrayList<Integer>();
        ArrayList<Float> textureCoorsInOrder = new ArrayList<Float>();
        ArrayList<Float> normalsInOrder = new ArrayList<Float>();

        int counter = 0;
        Log.d("OBJToolkit", "About to reorganize each point of data");
        for (Face f : faces)
        {
            for (int value : f.vertexIndices)
            {
                verticesInOrder.add(allVertices.get(value));
            }

            for (int value : f.textureIndices)
            {
                textureCoorsInOrder.add(allTextureCoors.get(value));
            }

            for (int value : f.normalIndices)
            {
                normalsInOrder.add(allNormals.get(value));
            }
            indicesInOrder.add(counter);
            counter++;
        }

        Log.d("OBJToolkit", "Vertices");
        printFloatArrayList(verticesInOrder);
        Log.d("OBJToolkit", "Indices");
        printIntegerArrayList(indicesInOrder);
        Log.d("OBJToolkit", "Texture Coordinates");
        printFloatArrayList(textureCoorsInOrder);
        Log.d("OBJToolkit", "Normals");
        printFloatArrayList(normalsInOrder);

        Log.d("OBJToolkit", "About to create the VBOs");
        mesh.createBuffers(floatListToFloatArray(verticesInOrder), integerListToShortArray(indicesInOrder), null, floatListToFloatArray(textureCoorsInOrder));
        return mesh;
    }

    public static void printFloatArrayList(ArrayList<Float> list)
    {
        String strToPrint = "";
        for (float value : list)
        {
            strToPrint += value + ", ";
        }
        Log.d("OBJToolkit", strToPrint);
    }

    public static void printIntegerArrayList(ArrayList<Integer> list)
    {
        String strToPrint = "";
        for (float value : list)
        {
            strToPrint += value + ", ";
        }
        Log.d("OBJToolkit", strToPrint);
    }

    public static float[] floatListToFloatArray(ArrayList<Float> list)
    {
        Log.d("OBJToolkit", "Converting ArrayList Float");
        float[] returnArray = new float[list.size()];
        int counter = 0;
        for (float i : list)
        {
            returnArray[counter] = i;
            counter++;
        }
        return returnArray;
    }

    public static short[] integerListToShortArray(ArrayList<Integer> list)
    {
        Log.d("OBJToolkit", "Converting ArrayList Integer");
        short[] returnArray = new short[list.size()];
        int counter = 0;
        for (int i : list)
        {
            returnArray[counter] = (short)i;
            counter++;
        }
        return returnArray;
    }
}

网格类:

public class Mesh { 
    Bitmap bitmap = null;

    private FloatBuffer verticesBuffer;
    private ShortBuffer indicesBuffer;
    private int numOfIndices = -1;
    private float[] rgba = new float[] {1.0f, 1.0f, 1.0f, 1.0f};
    private FloatBuffer colorBuffer;
    private FloatBuffer mTextureBuffer;
    private int mTextureId = -1;
    private Bitmap mBitmap;
    private boolean mShouldLoadTexture = false;

    public float x = 0, y = 0, z = 0, rx = 0, ry = 0, rz = 0;

    public Mesh() {

    }

    public void draw(GL10 gl)
    {
        //Log.d("Mesh", "About to render mesh");
        gl.glFrontFace(GL10.GL_CCW);
        gl.glEnable(GL10.GL_CULL_FACE);
        gl.glCullFace(GL10.GL_BACK);
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, verticesBuffer);
        gl.glColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);
        if (colorBuffer != null)
        {
            gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
            gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
        }

        if (mShouldLoadTexture)
        {
            loadGLTexture(gl);
            mShouldLoadTexture = false;
        }

        if (mTextureId != -1 && mTextureBuffer != null)
        {
            gl.glEnable(GL10.GL_TEXTURE_2D);
            gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer);
            gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);
        }

        gl.glTranslatef(x, y, z);
        gl.glRotatef(rx, 1, 0, 0);
        gl.glRotatef(ry, 0, 1, 0);
        gl.glRotatef(rz, 0, 0, 1);
        gl.glDrawElements(GL10.GL_TRIANGLES, numOfIndices, GL10.GL_UNSIGNED_SHORT, indicesBuffer);
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        if (mTextureId != -1 && mTextureBuffer != null)
        {
            gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
        }
        gl.glDisable(GL10.GL_CULL_FACE);
    }

    public void setTexture(Bitmap bitmap) {
        this.bitmap = bitmap;
    }

    public void createBuffers(float[] vertices, short[] indices, float[] colors, float[] textureCoords)
    {
        Log.d("MeshCreateBuffers", "Vertices: " + floatArrayToString(vertices));
        setVertices(vertices);
        Log.d("MeshCreateBuffers", "Indices: " + shortArrayToString(indices));
        setIndices(indices);
        if (colors != null)
            setColors(colors);
        setTextureCoordinates(textureCoords);
        Log.d("MeshCreateBuffers", "Texture Coors: " + floatArrayToString(textureCoords));
    }

    public String floatArrayToString(float[] array)
    {
        String returnString = "";
        for (int i = 0; i < array.length; i++)
        {
            returnString += array[i];
        }
        return returnString;
    }

    public String shortArrayToString(short[] array)
    {
        String returnString = "";
        for (int i = 0; i < array.length; i++)
        {
            returnString += array[i];
        }
        return returnString;
    }

    protected void setVertices(float[] vertices)
    {
        ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
        vbb.order(ByteOrder.nativeOrder());
        verticesBuffer = vbb.asFloatBuffer();
        verticesBuffer.put(vertices);
        verticesBuffer.position(0);
    }

    protected void setIndices(short[] indices)
    {
        ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
        ibb.order(ByteOrder.nativeOrder());
        indicesBuffer = ibb.asShortBuffer();
        indicesBuffer.put(indices);
        indicesBuffer.position(0);
        numOfIndices = indices.length;
    }

    protected void setColor(float red, float green, float blue, float alpha)
    {
        rgba[0] = red;
        rgba[1] = green;
        rgba[2] = blue;
        rgba[3] = alpha;
    }

    protected void setColors(float[] colors)
    {
        ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);
        cbb.order(ByteOrder.nativeOrder());
        colorBuffer = cbb.asFloatBuffer();
        colorBuffer.put(colors);
        colorBuffer.position(0);
    }

    protected void setTextureCoordinates(float[] textureCoords)
    {
        ByteBuffer byteBuf = ByteBuffer.allocateDirect(textureCoords.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        mTextureBuffer = byteBuf.asFloatBuffer();
        mTextureBuffer.put(textureCoords);
        mTextureBuffer.position(0);
    }

    public void loadBitmap(Bitmap bitmap)
    {
        this.mBitmap = bitmap;
        mShouldLoadTexture = true;
    }

    private void loadGLTexture(GL10 gl)
    {
        int[] textures = new int[1];
        gl.glGenTextures(1, textures, 0);
        mTextureId = textures[0];
        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mBitmap, 0);
    }
}

我是否在做一些我无法发现的明显错误或过于复杂的事情?

我感谢任何愿意提供意见的人。

4

1 回答 1

1

在大多数情况下,我终于让它工作了。我没有将每个顶点的相关数据保存得足够好,所以在需要渲染的时候,一切都乱了套。到目前为止,解析器支持顶点、法线和纹理坐标,尽管网格的细节较为精细,但它会达到最大堆大小并陷入非常长的垃圾收集循环中。我在 Blender 中创建了 suzanne 猴头,用平滑对其进行了细分,然后将其导出为 OBJ。它确实加载了,但花了大约 20 分钟。

这是源代码,我相信它会对某人有所帮助,因为我无法找到读取 OBJ 文件并以 VBO 的形式将其发送到显卡的代码,法线和纹理坐标正常工作:

public class OBJToolkit {
    private static ArrayList<String> parseOBJ(String modelLocation) throws IOException
    {
        BufferedReader reader = new BufferedReader(new FileReader(new File(modelLocation)));
        ArrayList<String> lines = new ArrayList<String>();
        while(reader.ready())
        {
            lines.add(reader.readLine());
        }
        reader.close();
        reader = null;
        return lines;
    }

    public static Mesh loadOBJ(String modelLocation) throws FileNotFoundException, IOException
    {
        Log.d("OBJToolkit", "Location searched for model: " + modelLocation);

        ArrayList<Vector3f> allVertices = new ArrayList<Vector3f>();
        ArrayList<Vector2f> allTextureCoords = new ArrayList<Vector2f>();
        ArrayList<Vector3f> allNormals = new ArrayList<Vector3f>();

        ArrayList<Face> faces = new ArrayList<Face>();

        Mesh mesh = new Mesh();

        ArrayList<String> lines = parseOBJ(modelLocation);

        Log.d("OBJToolkit", "About to read the contents of the model");
        for (String line : lines)
        {
            if (line == null)
                break;

            if (line.startsWith("v "))
            {
                allVertices.add(new Vector3f(Float.valueOf(line.split(" ")[1]), Float.valueOf(line.split(" ")[2]), Float.valueOf(line.split(" ")[3])));
            }

            if (line.startsWith("vt "))
            {
                allTextureCoords.add(new Vector2f(Float.valueOf(line.split(" ")[1]),Float.valueOf(line.split(" ")[2])));
            }

            if (line.startsWith("vn "))
            {
                allNormals.add(new Vector3f(Float.valueOf(line.split(" ")[1]), Float.valueOf(line.split(" ")[2]), Float.valueOf(line.split(" ")[3])));
            }

            if (line.startsWith("f "))
            {
                //Log.d("OBJToolkit", line);
                Face f = new Face();
                String[] faceVertexArray = line.split(" ");

                for (int index = 1; index < faceVertexArray.length; index++)
                {
                    String[] valueArray = faceVertexArray[index].split("/");

                    if (allTextureCoords.size() > 0)
                        f.addVertex(new Vertex(allVertices.get(Integer.valueOf(valueArray[0]) - 1), allNormals.get(Integer.valueOf(valueArray[2]) - 1), allTextureCoords.get(Integer.valueOf(valueArray[1]) - 1)));
                    else
                        f.addVertex(new Vertex(allVertices.get(Integer.valueOf(valueArray[0]) - 1), allNormals.get(Integer.valueOf(valueArray[2]) - 1), new Vector2f(0, 0)));
                }
                faces.add(f);
            }
        }

        Log.d("OBJToolkit", "Number of vertices: " + allVertices.size());
        Log.d("OBJToolkit", "Number of normals: " + allNormals.size());
        Log.d("OBJToolkit", "Number of texture coords: " + allTextureCoords.size());

        lines = null;
        allVertices = null;
        allNormals = null;
        allTextureCoords = null;

        ArrayList<Vector3f> VBOVertices = new ArrayList<Vector3f>();
        ArrayList<Vector2f> VBOTextureCoords = new ArrayList<Vector2f>();
        ArrayList<Vector3f> VBONormals = new ArrayList<Vector3f>();
        ArrayList<Integer> VBOIndices = new ArrayList<Integer>();

        Log.d("OBJToolkit", "About to reorganize each point of data");
        int counter = 0;
        for (Face f : faces)
        {
            for (Vertex v : f.vertices)
            {
                VBOVertices.add(v.position);
                VBONormals.add(v.normal);
                VBOTextureCoords.add(v.textureCoord);
                VBOIndices.add(counter);
                counter++;
            }
        }

        faces = null;

        mesh.createBuffers(vector3fListToFloatArray(VBOVertices), integerListToShortArray(VBOIndices), null, vector2fListToFloatArray(VBOTextureCoords), vector3fListToFloatArray(VBONormals));

        VBOVertices = null;
        VBONormals = null;
        VBOTextureCoords = null;
        VBOIndices = null;
        return mesh;
    }

    public static void printFloatArrayList(ArrayList<Float> list)
    {
        String strToPrint = "";
        for (float value : list)
        {
            strToPrint += (value + ", ");
        }
        Log.d("OBJToolkit", strToPrint);
    }

    public static String floatArrayToString(ArrayList<Float> list)
    {
        String strToPrint = "";
        for (float value : list)
        {
            strToPrint += (value + ", ");
        }
        return strToPrint;
    }

    public static String vector3fArrayToString(ArrayList<Vector3f> list)
    {
        String strToPrint = "";
        for (Vector3f v : list)
        {
            strToPrint += v.x + ", ";
            strToPrint += v.y + ", ";
            strToPrint += v.z + ", ";
        }
        return strToPrint;
    }

    public static void printStringArray(String[] list)
    {
        String strToPrint = "";
        for (String s : list)
        {
            strToPrint += s + ",";
        }
        Log.d("OBJToolkit", strToPrint);
    }

    public static void printIntegerArrayList(ArrayList<Integer> list)
    {
        String strToPrint = "";
        for (float value : list)
        {
            strToPrint += (value + ", ");
        }
        Log.d("OBJToolkit", strToPrint);
    }

    public static float[] floatListToFloatArray(ArrayList<Float> list)
    {
        Log.d("OBJToolkit", "Converting ArrayList Float");
        float[] returnArray = new float[list.size()];
        int counter = 0;
        for (Float i : list)
        {
            returnArray[counter] = i.floatValue();
            counter++;
        }
        return returnArray;
    }

    public static short[] integerListToShortArray(ArrayList<Integer> list)
    {
        Log.d("OBJToolkit", "Converting ArrayList Integer");
        short[] returnArray = new short[list.size()];
        int counter = 0;
        for (int i : list)
        {
            returnArray[counter] = (short)i;
            counter++;
        }
        return returnArray;
    }

    public static float[] vector3fListToFloatArray(ArrayList<Vector3f> list)
    {
        Log.d("OBJToolkit", "Converting ArrayList Vector3f");
        float[] returnArray = new float[list.size() * 3];
        int counter = 0;
        for (Vector3f v : list)
        {
            returnArray[counter] = v.x;
            counter++;
            returnArray[counter] = v.y;
            counter++;
            returnArray[counter] = v.z;
            counter++;
        }

        return returnArray;
    }

    public static float[] vector2fListToFloatArray(ArrayList<Vector2f> list)
    {
        Log.d("OBJToolkit", "Converting ArrayList Vector2f");
        float[] returnArray = new float[list.size() * 2];
        int counter = 0;
        for (Vector2f v : list)
        {
            returnArray[counter] = v.x;
            counter++;
            returnArray[counter] = v.y;
            counter++;
        }

        return returnArray;
    }

矢量3f:

public class Vector3f {
    public float x, y, z;

    public Vector3f()
    {
        setTo(0, 0, 0);
    }

    public Vector3f(float x, float y, float z)
    {
        setTo(x, y, z);
    }

    public void setTo(float x, float y, float z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    public float lengthSquared()
    {
        return x*x + y*y + z*z;
    }

    public float length()
    {
        return (float) Math.sqrt(lengthSquared());
    }

    public Vector3f add(Vector3f v)
    {
        return new Vector3f(x + v.x, y + v.y, z + v.z);
    }

    public Vector3f addAndSet(Vector3f v)
    {
        x += v.x;
        y += v.y;
        z += v.z;
        return this;
    }

    public Vector3f crossProduct(Vector3f v)
    {
        return new Vector3f(y * v.z - z * v.y,
                z * v.x - x * z,
                x * v.y - y * v.x
                );
    }

    public Vector3f negate()
    {
        x *= -1;
        y *= -1;
        z *= -1;
        return this;
    }

    public Vector3f normalize()
    {
        float l = length();

        return new Vector3f(x / l, y / l, z / l);
    }

    public float dotProduct(Vector3f v)
    {
        return x * v.x + y * v.y + z * v.z;
    }

    public float angleBetween(Vector3f v)
    {
        float dls = dotProduct(v) / (length() * v.length());
        if (dls < -1f)
            dls = -1f;
        else if (dls > 1.0f)
            dls = 1.0f;
        return (float)Math.acos(dls);
    }

    public Vector3f scale(float scale)
    {
        return new Vector3f(x * scale, y * scale, z * scale);
    }

    public Vector3f scaleAndSet(float scale)
    {
        x *= scale;
        y *= scale;
        z *= scale;
        return this;
    }


}

矢量2f:

public class Vector2f {
    public float x, y;

    public Vector2f()
    {
        setTo(0, 0);
    }

    public Vector2f(float x, float y)
    {
        setTo(x, y);
    }

    public void setTo(float x, float y)
    {
        this.x = x;
        this.y = y;
    }

    public float lengthSquared()
    {
        return x * x + y * y;
    }

    public float length()
    {
        return (float) Math.sqrt(lengthSquared());
    }

    public Vector2f add(float x, float y)
    {
        return new Vector2f(this.x + x, this.y + y);
    }

    public Vector2f addAndSet(float x, float y)
    {
        this.x += x;
        this.y += y;
        return this;
    }

    public Vector2f negate()
    {
        x *= -1;
        y *= -1;
        return this;
    }

    public Vector2f normalize()
    {
        float l = length();
        return new Vector2f(x / l, y / l);
    }

    public float dotProduct(Vector2f v)
    {
        return x * v.x + y * v.y;
    }

    public float angleBetween(Vector2f v)
    {
        float dls = dotProduct(v) / (length() * v.length());
        if (dls < -1f)
            dls = -1f;
        else if (dls > 1.0f)
            dls = 1.0f;
        return (float)Math.acos(dls);
    }

    public Vector2f scale(float scale)
    {
        return new Vector2f(x * scale, y * scale);
    }

    public Vector2f scaleAndSet(float scale)
    {
        x *= scale;
        y *= scale;
        return this;
    }
}

网:

public class Mesh { 
    Bitmap bitmap = null;

    private FloatBuffer verticesBuffer;
    private ShortBuffer indicesBuffer;
    private FloatBuffer normalsBuffer;
    private int numOfIndices = -1;
    private float[] rgba = new float[] {1.0f, 1.0f, 1.0f, 1.0f};
    private FloatBuffer colorBuffer;
    private FloatBuffer mTextureBuffer;
    private int mTextureId = -1;
    private Bitmap mBitmap;
    private boolean mShouldLoadTexture = false;

    public float x = 0, y = 0, z = 0, rx = 0, ry = 0, rz = 0;

    public Mesh() {

    }

    public void draw(GL10 gl)
    {
        //Log.d("Mesh", "About to render mesh");
        gl.glFrontFace(GL10.GL_CCW);
        gl.glEnable(GL10.GL_CULL_FACE);
        gl.glCullFace(GL10.GL_BACK);
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, verticesBuffer);
        gl.glNormalPointer(GL10.GL_FLOAT, 0, normalsBuffer);
        gl.glColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);
        if (colorBuffer != null)
        {
            gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
            gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
        }

        if (mShouldLoadTexture)
        {
            loadGLTexture(gl);
            mShouldLoadTexture = false;
        }

        if (mTextureId != -1 && mTextureBuffer != null)
        {
            gl.glEnable(GL10.GL_TEXTURE_2D);
            gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer);
            gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);
        }

        gl.glTranslatef(x, y, z);
        gl.glRotatef(rx, 1, 0, 0);
        gl.glRotatef(ry, 0, 1, 0);
        gl.glRotatef(rz, 0, 0, 1);
        gl.glDrawElements(GL10.GL_TRIANGLES, numOfIndices, GL10.GL_UNSIGNED_SHORT, indicesBuffer);
        gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        if (mTextureId != -1 && mTextureBuffer != null)
        {
            gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
        }
        gl.glDisable(GL10.GL_CULL_FACE);
    }

    public void setTexture(Bitmap bitmap) {
        this.bitmap = bitmap;
    }

    public void createBuffers(float[] vertices, short[] indices, float[] colors, float[] textureCoords, float[] normals)
    {
        Log.d("MeshCreateBuffers", "Vertices: " + floatArrayToString(vertices));
        setVertices(vertices);
        Log.d("MeshCreateBuffers", "Indices: " + shortArrayToString(indices));
        setIndices(indices);
        if (colors != null)
            setColors(colors);
        if (textureCoords != null)
            setTextureCoordinates(textureCoords);
        if (normals != null)
            setNormals(normals);
        Log.d("MeshCreateBuffers", "Texture Coors: " + floatArrayToString(textureCoords));
    }

    public String floatArrayToString(float[] array)
    {
        String returnString = "";
        for (int i = 0; i < array.length; i++)
        {
            returnString += ", " + array[i];
        }
        if (returnString.length() > 2)
            return returnString.substring(2);
        else
            return returnString;
    }

    public String shortArrayToString(short[] array)
    {
        String returnString = "";
        for (int i = 0; i < array.length; i++)
        {
            returnString += ", " + array[i];
        }
        if (returnString.length() > 2)
            return returnString.substring(2);
        else
            return returnString;
    }

    protected void setVertices(float[] vertices)
    {
        ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
        vbb.order(ByteOrder.nativeOrder());
        verticesBuffer = vbb.asFloatBuffer();
        verticesBuffer.put(vertices);
        verticesBuffer.position(0);
    }

    protected void setIndices(short[] indices)
    {
        ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
        ibb.order(ByteOrder.nativeOrder());
        indicesBuffer = ibb.asShortBuffer();
        indicesBuffer.put(indices);
        indicesBuffer.position(0);
        numOfIndices = indices.length;
    }

    protected void setColor(float red, float green, float blue, float alpha)
    {
        rgba[0] = red;
        rgba[1] = green;
        rgba[2] = blue;
        rgba[3] = alpha;
    }

    protected void setColors(float[] colors)
    {
        ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);
        cbb.order(ByteOrder.nativeOrder());
        colorBuffer = cbb.asFloatBuffer();
        colorBuffer.put(colors);
        colorBuffer.position(0);
    }

    protected void setTextureCoordinates(float[] textureCoords)
    {
        ByteBuffer byteBuf = ByteBuffer.allocateDirect(textureCoords.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        mTextureBuffer = byteBuf.asFloatBuffer();
        mTextureBuffer.put(textureCoords);
        mTextureBuffer.position(0);
    }

    protected void setNormals(float[] normals)
    {
        ByteBuffer byteBuf = ByteBuffer.allocateDirect(normals.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        normalsBuffer = byteBuf.asFloatBuffer();
        normalsBuffer.put(normals);
        normalsBuffer.position(0);
    }

    public void loadBitmap(Bitmap bitmap)
    {
        this.mBitmap = bitmap;
        mShouldLoadTexture = true;
    }

    private void loadGLTexture(GL10 gl)
    {
        int[] textures = new int[1];
        gl.glGenTextures(1, textures, 0);
        mTextureId = textures[0];
        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mBitmap, 0);
    }
}

脸:

public class Face {
    ArrayList<Vertex> vertices = new ArrayList<Vertex>();

    public Face()
    {

    }

    public void addVertex(Vertex vertex)
    {
        vertices.add(vertex);
    }
}

顶点:

public class Vertex {
    public Vector3f position, normal;
    public Vector2f textureCoord;

    public Vertex(Vector3f pos, Vector3f norm, Vector2f textCoord)
    {
        position = pos;
        normal = norm;
        textureCoord = textCoord;
    }
}

主要活动:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        MyGLSurfaceView view = new MyGLSurfaceView(this);
        OpenGLRenderer renderer = new OpenGLRenderer();
        view.renderer = renderer;
        //renderer.plane.loadBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher));
        view.setRenderer(renderer);
        setContentView(view);
    }
}

class MyGLSurfaceView extends GLSurfaceView implements OnGestureListener, OnTouchListener
{
    OpenGLRenderer renderer;
    GestureDetector detector;

    float lastX = 0, lastY = 0;

    float onDown = 0, onUp = 0;

    public MyGLSurfaceView(Context context) {
        super(context);
        detector = new GestureDetector(this);
        setOnTouchListener(this);
    }

    @Override
    public boolean onTouchEvent(MotionEvent me)
    {
        detector.onTouchEvent(me);
        //Log.d("OBJToolkit", "X: " + me.getX());
        //Log.d("OBJToolkit", "Y: " + me.getY());
        return super.onTouchEvent(me);
    }

    @Override
    public boolean onTouch(View v, MotionEvent me)
    {
        Log.d("OBJToolkit", "Registered onTouch event");
        Log.d("OBJToolkit", "X: " + me.getX());
        Log.d("OBJToolkit", "Y: " + me.getY());
        if (me.getAction() == MotionEvent.ACTION_DOWN)
        {
            lastY = me.getY();
        }
        else if (me.getAction() == MotionEvent.ACTION_MOVE)
        {
            renderer.moveMesh(me.getY() - lastY);
        }
        /*
        if (lastX == 0)
        {
            lastX = me.getX();
        }
        if (lastY == 0)
        {
            lastY = me.getY();
        }
        Log.d("OBJToolkit", String.valueOf((me.getY() - lastY) * 0.1f));
        renderer.moveMesh(me.getY() - lastY);
        */
        lastY = me.getY();

        return true;
    }

    @Override
    public boolean onDown(MotionEvent e) {
        // TODO Auto-generated method stub
        //Log.d("OBJToolkit", "Registered onDown Event");
        return false;
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
            float velocityY) {
        // TODO Auto-generated method stub
        //Log.d("OBJToolkit", "Registered onFling Event");
        return false;
    }

    @Override
    public void onLongPress(MotionEvent e) {
        // TODO Auto-generated method stub
        //Log.d("OBJToolkit", "Registered onLongPress Event");

    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
            float distanceY) {
        // TODO Auto-generated method stub
        //Log.d("OBJToolkit", "Registered onScroll Event");
        return false;
    }

    @Override
    public void onShowPress(MotionEvent e) {
        // TODO Auto-generated method stub
        //Log.d("OBJToolkit", "Registered onShowPress Event");
    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        // TODO Auto-generated method stub
        //Log.d("OBJToolkit", "Registered onSIngleTapUp Event");
        return false;
    }

}

OpenGL渲染器:

public class OpenGLRenderer implements Renderer
{
    //SmoothColoredSquare smoothSquare = new SmoothColoredSquare();
    //Cube cube = new Cube(1, 1, 1);
    public Mesh plane;

    public float meshMoveSpeed = .05f, planePosition = 0f;

    float zNear = 0.01f, zFar = 1000.0f, fieldOfView = 45.0f, size;

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        Log.d(getClass().getName(), "About to attempt to load model");
        try {
            plane = OBJToolkit.loadOBJ(Environment.getExternalStorageDirectory().getPath() + "/testModel.obj");
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            Log.d("FNF", "testModel.obj not found");
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            Log.d("IOE", "testModel.obj not found IOE");
            e.printStackTrace();
        }
        //.z = -7.7f;
        //plane.rx = -10;
        gl.glEnable(GL11.GL_DEPTH_TEST);
        gl.glDepthFunc(GL10.GL_LEQUAL);
        gl.glMatrixMode(GL11.GL_MODELVIEW);
        gl.glShadeModel(GL11.GL_SMOOTH);
        gl.glClearDepthf(1.0f);
        gl.glEnable(GL11.GL_LIGHTING);
        gl.glEnable(GL11.GL_LIGHT0);
        float ambientColor[] = {0.2f, 0.2f, 0.2f, 1.0f};
        float diffuseColor[] = {0.2f, 0.2f, 0.2f, 1.0f};
        float lightPosition[] = {-2f, 5f, -2f, 1f};
        gl.glLightfv(GL11.GL_LIGHT0, GL11.GL_AMBIENT, ambientColor, 0);
        gl.glLightfv(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, diffuseColor, 0);
        gl.glLightfv(GL11.GL_LIGHT0, GL11.GL_POSITION, lightPosition, 0);
        gl.glLoadIdentity();
        gl.glClearColor(0.8f, 0.8f, 0.8f, 1.0f);
        gl.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        //Reset viewport
        gl.glViewport(0, 0, width, height);
        //Select projection matrix
        gl.glMatrixMode(GL10.GL_PROJECTION);
        size = (float) (zNear * Math.tan((fieldOfView / 180.0f) * Math.PI) / 2.0f);
        gl.glFrustumf(-size, size, -size / (width / height), size / (width / height), zNear, zFar);
        gl.glViewport(0, 0, width, height);
        //Reset projection matrix
        gl.glLoadIdentity();
        //Calculate aspect ratio of window
        GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 0.1f, 100.0f);
        //GLU.gluLookAt(gl, -5f, 2f, 0f, 0f, 0f, 0f, 0f, 1f, 0f);
        //Select modelview matrix
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        //Reset modelview matrix
        gl.glLoadIdentity();
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        //Clear the screen before drawing
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

        //plane.ry += 2f;
        //plane.rz += 2f;

        plane.x += meshMoveSpeed;
        plane.z = planePosition;
        if (plane.x > 3f)
        {
            meshMoveSpeed *= -1;
        }
        else if(plane.x < -3f)
        {
            meshMoveSpeed *= -1;
        }

        //Reset the current position held by OpenGL, otherwise the
        //camera will be pushed farther and farther back every frame
        gl.glLoadIdentity();

        //Move the camera backwards in order to actually see the face
        gl.glTranslatef(0, 0f, -15f);

        plane.draw(gl);
    }

    public void moveMesh(float distance)
    {
        planePosition += distance * 0.05f;
    }
}
于 2013-04-10T15:45:54.263 回答