android - OpenGL ES 2.0 基于运动画线,线总是从原点开始

标签 android opengl-es-2.0

我刚开始学习 Android 版 OpenGL,在画线时遇到了一个奇怪的问题。我想要做的就是根据手指运动画一条线。现在,一旦我开始滑动,我总是会得到一条从原点 (0,0) 开始跟随我的运动的线。

这里是一张图片:

http://imageshack.us/photo/my-images/137/screenshot2012061312174.jpg/

箭头表示我的手指运动,从原点(红色圆圈)开始的线是我整个运动之后提到的线。

不要为 Coords 数组而烦恼 我知道这不是最佳实践,但我调试了整个程序并且找不到涉及此数组的任何错误。

我可能应该提到 ArrayList 点包含我生成的所有点。

我想暂时解决这个问题,但我真的无法理解任何可能有帮助的建议

这是我的整个渲染类。

公共(public)类 HelloOpenGLES20Renderer 实现 GLSurfaceView.Renderer {

private FloatBuffer triangleVB;
private int mProgram;
private int maPositionHandle;
public ArrayList<PointWrapper> points;

private int muMVPMatrixHandle;
private float[] mMVPMatrix = new float[16];
private float[] mMMatrix = new float[16];
private float[] mVMatrix = new float[16];
private float[] mProjMatrix = new float[16];
private int[] viewport = new int[4];

private ArrayList<Float> coordinates;

float[] Coords = new float[100000];

boolean first;
private int counter;
private PointWrapper last;

private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;   \n" +

"attribute vec4 vPosition;  \n" + "void main(){               \n" +

// the matrix must be included as a modifier of gl_Position
        " gl_Position = uMVPMatrix * vPosition; \n" +
        "}  \n";

private final String fragmentShaderCode = "precision mediump float;  \n"
        + "void main(){              \n"
        + " gl_FragColor = vec4 (0.63671875, 0.76953125, 0.22265625, 1.0); \n"
        + "}                         \n";

private int loadShader(int type, String shaderCode) {

    // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
    // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
    int shader = GLES20.glCreateShader(type);

    // add the source code to the shader and compile it
    GLES20.glShaderSource(shader, shaderCode);
    GLES20.glCompileShader(shader);

    return shader;
}

public HelloOpenGLES20Renderer() {
    points = new ArrayList<PointWrapper>();
    first = true;
    this.counter = 0;
    last = new PointWrapper();

    coordinates = new ArrayList<Float>();
}

private float[] convertCoordinates(PointWrapper f) {
    float[] vector = new float[4];
    GLU.gluUnProject(f.point.x, f.point.y, 0.0f, mVMatrix, 0, mProjMatrix,
            0, viewport, 0, vector, 0);

    return vector;
}

private void initShapes() {
    ArrayList<PointWrapper> points2 = new ArrayList<PointWrapper>(points);
    float[] vector;


    if (!points2.isEmpty()) {
        if(points2.size()%2==1){
            points2.remove(points2.size()-1);
        }

        for (int i = counter/2; i < points2.size(); i++) {

            vector = convertCoordinates(points2.get(i));
            Coords[counter] = vector[0] / vector[3];
            Coords[counter+1] = -1 * (vector[1] / vector[3]);

            counter= counter+2;
        }


    }

    // initialize vertex Buffer for triangle
    ByteBuffer vbb = ByteBuffer.allocateDirect(
    // (# of coordinate values * 4 bytes per float)
            Coords.length * 4);
    vbb.order(ByteOrder.nativeOrder());// use the device hardware's native
    // byte order
    triangleVB = vbb.asFloatBuffer(); // create a floating point buffer from
    // the ByteBuffer
    triangleVB.put(Coords); // add the coordinates to the
    // FloatBuffer
    triangleVB.position(0); // set the buffer to read the first coordinate

}

public void onSurfaceCreated(GL10 unused, EGLConfig config) {

    // Set the background frame color
    GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);

    // initialize the triangle vertex array
    // initShapes();

    int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
    int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,
            fragmentShaderCode);

    mProgram = GLES20.glCreateProgram(); // create empty OpenGL Program
    GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader
                                                    // to program
    GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment
                                                        // shader to program
    GLES20.glLinkProgram(mProgram); // creates OpenGL program executables

    // get handle to the vertex shader's vPosition member
    maPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
}

public void onDrawFrame(GL10 unused) {

    // Redraw background color
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

    initShapes();

    // Add program to OpenGL environment
    GLES20.glUseProgram(mProgram);

    // Prepare the triangle data
    GLES20.glVertexAttribPointer(maPositionHandle, 2, GLES20.GL_FLOAT,
            false, 0, triangleVB);
    GLES20.glEnableVertexAttribArray(maPositionHandle);

    // Apply a ModelView Projection transformation
    Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
    GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);

    GLES20.glLineWidth(5f);

    GLES20.glDrawArrays(GLES20.GL_LINE_STRIP, 0, counter);


}

public void onSurfaceChanged(GL10 unused, int width, int height) {
    GLES20.glViewport(0, 0, width, height);

    float ratio = (float) width / height;
    viewport[0] = 0;
    viewport[1] = 0;
    viewport[2] = width;
    viewport[3] = height;

    // this projection matrix is applied to object coodinates
    // in the onDrawFrame() method
    Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);

    muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");

    Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
}

提前致谢

最佳答案

for (int i = counter/2; i < points2.size(); i++) {

        vector = convertCoordinates(points2.get(i));
        Coords[counter] = vector[0] / vector[3];
        Coords[counter+1] = -1 * (vector[1] / vector[3]);

        counter= counter+2;
    }

您已初始化 Coords 以容纳 100000 个 float ,并将它们初始化为 0。在此循环中,最后一次迭代具有“计数器”,其中包含您在数组中设置的 float 。

传递给 glDrawArrays 的应该是要绘制的 VERTICES 的数量。所以在这种情况下是“计数器”的一半。

GLES20.glDrawArrays(GLES20.GL_LINE_STRIP, 0, counter);

您的 for 循环在数组的末尾添加了“counter”/2 个额外数量的 (0,0) 顶点。最快的解决方法是将 'counter'/2 传递给 glDrawArrays,但我建议采用更清晰的方法。

numOfVertices = points2.size(); //make field 
int counter = 0; //make local
for (int i = 0; i < numOfVertices; i++) {
        vector = convertCoordinates(points2.get(i));
        Coords[counter] = vector[0] / vector[3];
        Coords[counter+1] = -1 * (vector[1] / vector[3]);
        counter= counter+2;
    }

然后

GLES20.glDrawArrays(GLES20.GL_LINE_STRIP, 0, numOfVertices);

关于android - OpenGL ES 2.0 基于运动画线,线总是从原点开始,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11015374/

相关文章:

android - 如何将 Android 应用程序连接到 MySQL 数据库?

java - 是否有任何类可以处理 RecyclerView ViewHolders 的数据绑定(bind)?

android - 如何包装首选项标题? (真的)

java - 未导入支持库

c++ - 如何在 visual studio 2015 中创建 .vcxitems

java - 每 15 分钟创建一次 Android 通知

javascript - WebGL - 使用多个纹理时的条纹

webgl - 如果片段着色器不支持高精度,带有 `varying` 限定符的顶点着色器 `highp` 变量会发生什么情况?

iphone - 释放由 GLKTextureLoader 分配的纹理(GLKTextureInfo 对象)

c++ - 纹理映射到瓷砖