android opengl es 2显示几次旋转错误

时间:2016-09-06 21:10:51

标签: android arraylist opengl-es rotation

我正在尝试绘制相互连接的线条。让我们说他们正在创造一个 长方形。在每个角落我也有积分。当我在我的测试中测试代码 三星Galaxy Note 4经过几次旋转后,使用触控,所有矩形都结束了 在中心有一个点。我无法弄清楚为什么会这样。 代码在模拟器中工作正常。另外,我将行和点数据存储为数组列表 在我的代码中。这些数组列表用于创建行和点对象类 渲染。

public class GLRender implements GLSurfaceView.Renderer {

private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private float[] mRotationMatrix = new float[16];
private float[] mVRMatrix = new float[16];
private static ArrayList<Line> DrLine = new ArrayList<Line>();
private static ArrayList<Point> DrPoint = new ArrayList<Point>();
private float ratio;
private float Joint1;
private float Joint2;
private float x1, y1, z1, x2, y2, z2;
private float px, py, pz, ps;
private float[] nearN = new float[4];

private static ArrayList<ArrayList<String>> LineArray =  new ArrayList<ArrayList<String>>();
private ArrayList<String> L = new ArrayList<String>();
private ArrayList<String> P = new ArrayList<String>();
private static ArrayList<ArrayList<String>> PointArray = new ArrayList<ArrayList<String>>();
private static ArrayList<String> EmptyLine = new ArrayList<String>();
private static ArrayList<String> EmptyPoint = new ArrayList<String>();
private static ArrayList<ArrayList<ArrayList<String>>> UndoL = new ArrayList<ArrayList<ArrayList<String>>>();
private static ArrayList<ArrayList<ArrayList<String>>> UndoP = new ArrayList<ArrayList<ArrayList<String>>>();

public GLRender(Activity activity) {
}

public void onSurfaceCreated(GL10 unused, EGLConfig config) {
    // Set the background frame color
    //GLES20.glClearColor(0.53f, 0.53f, 0.53f, 1.0f);
    GLES20.glClearColor(0.474f, 0.537f, 0.078f, 1.0f);
}

public void onDrawFrame(GL10 unused) {

    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

    Drawer();

    Line XLine = new Line();
    XLine.SetVerts(0.0f, 0.0f, 0.0f, 1.0f / 10, 0.0f, 0.0f);
    XLine.SetColor(1.0f, 0.0f, 0.0f, 1.0f);

    Line YLine = new Line();
    YLine.SetVerts(0.0f, 0.0f, 0.0f, 0.0f, 1.0f / 10, 0.0f);
    YLine.SetColor(0.0f, 1.0f, 0.0f, 1.0f);

    Line ZLine = new Line();
    ZLine.SetVerts(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f / 10);
    ZLine.SetColor(0.0f, 0.0f, 1.0f, 1.0f);

    Matrix.setIdentityM(mViewMatrix, 0);
    Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 1.0f , 0f, 0f, 0f, 0f, 1.0f, 0.0f);

    Matrix.setIdentityM(mRotationMatrix, 0);
    Matrix.rotateM(mRotationMatrix, 0, mXAngle, 0, 1f, 0);
    Matrix.rotateM(mRotationMatrix, 0, mYAngle, 1f, 0, 0);
    Matrix.setIdentityM(mVRMatrix, 0);
    Matrix.multiplyMM(mVRMatrix, 0, mViewMatrix, 0, mRotationMatrix, 0);
    Matrix.setIdentityM(mMVPMatrix, 0);
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mVRMatrix, 0);
    Matrix.scaleM(mMVPMatrix,0,mScale,mScale,mScale);

    if (DrLine.size() > 0) {
        for (Line LineX : DrLine) {
            LineX.draw(mMVPMatrix);
        }
    }

    if (DrPoint.size() > 0) {
        for (Point PointX : DrPoint) {
            PointX.draw(mMVPMatrix);
        }
    }

    XLine.draw(mMVPMatrix);
    YLine.draw(mMVPMatrix);
    ZLine.draw(mMVPMatrix);
}

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

    //Matrix.frustumM(mProjectionMatrix, 0, -ratio*10, ratio*10, -10, 10, 1, 9);
    Matrix.orthoM(mProjectionMatrix, 0, -ratio, ratio, -1.0f, 1.0f, -5.0f, 5.0f);
}

public static 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;
}

private Float TempMaxPointHolder = 0.0f;
private Float MaxPointHolder = 0.0f;

public Float Scaler(){

    Float TempScaler = 1.0f;
    Iterator<ArrayList<String>> MaxPointFinder = PointArray.iterator();

    while (MaxPointFinder.hasNext()){
        ArrayList<String> MaxPoint = MaxPointFinder.next();
        TempMaxPointHolder = Math.abs(Math.max(Math.max(Float.parseFloat(MaxPoint.get(1)),Float.parseFloat(MaxPoint.get(2))),Float.parseFloat(MaxPoint.get(3))));

        if (TempMaxPointHolder > MaxPointHolder){
            MaxPointHolder = TempMaxPointHolder;
        }
    }

    TempScaler = 0.9f / MaxPointHolder;
    return TempScaler;
}

public void Drawer(){

    Float Scaler = Scaler();
    Integer Lindex = 0;

    ArrayList<Point> TempDrPoint = new ArrayList<Point>();
    ArrayList<Line> TempDrLine = new ArrayList<Line>();

    Iterator<ArrayList<String>> Litr = LineArray.iterator();

    while (Litr.hasNext()) {

        L = Litr.next();

        Joint1 = Float.parseFloat(L.get(1));
        Joint2 = Float.parseFloat(L.get(2));

        Iterator<ArrayList<String>> PitrL = PointArray.iterator();

        while (PitrL.hasNext()){

            P = PitrL.next();

            if (Float.parseFloat(P.get(0)) == Joint1) {
                x1 = Float.parseFloat(P.get(1)) * Scaler;
                y1 = Float.parseFloat(P.get(2)) * Scaler;
                z1 = Float.parseFloat(P.get(3)) * Scaler;
            }

            if (Float.parseFloat(P.get(0)) == Joint2) {
                x2 = Float.parseFloat(P.get(1)) * Scaler;
                y2 = Float.parseFloat(P.get(2)) * Scaler;
                z2 = Float.parseFloat(P.get(3)) * Scaler;
            }
        }

        Line TempLine = new Line();
        TempLine.SetVerts(x1, y1, z1, x2, y2, z2);
        if (L.get(3) == "0") {
            TempLine.SetColor(0.0f, 0.0f, 0.0f, 1.0f);
        }
        else if (L.get(3) == "1"){
            TempLine.SetColor(0.66f, 0.73f, 0.21f, 1.0f);
        }

        TempDrLine.add(TempLine);
        Lindex = Lindex + 1;
    }

    setDrLine(TempDrLine);
    Integer Pindex = 0;
    Iterator<ArrayList<String>> Pitr = PointArray.iterator();

    while (Pitr.hasNext()){

        P = Pitr.next();

        px = Float.parseFloat(P.get(1)) * Scaler;
        py = Float.parseFloat(P.get(2)) * Scaler;
        pz = Float.parseFloat(P.get(3)) * Scaler;
        ps = Float.parseFloat(P.get(4));

        Point TempPoint = new Point();
        TempPoint.SetPointVerts(px, py, pz);

        if (ps == 0.0f) {
            TempPoint.SetPointColor(0.65f, 0.37f, 0.11f, 1.0f);
        }
        else if (ps == 1.0f) {
            TempPoint.SetPointColor(0.68f, 0.07f, 0.32f, 1.0f);
        }

        TempDrPoint.add(TempPoint);
        Pindex = Pindex + 1;
    }
    setDrPoint(TempDrPoint);
}

public volatile float mXAngle;
public volatile float mYAngle;

public ArrayList<Line> getDrLine() {
    return DrLine;
}

public ArrayList<Point> getDrPoint(){
    return DrPoint;
}

public void setDrLine(ArrayList<Line> XDrLine) {
    DrLine = XDrLine;
}

public void setDrPoint(ArrayList<Point> XDrPoint) {
    DrPoint = XDrPoint;
}

public float getXAngle() {
    return mXAngle;
}

public float getYAngle(){
    return mYAngle;
}

public void setAngleX(float Xangle) {
    mXAngle = Xangle;
}

public void setAngleY(float Yangle) {
    mYAngle = Yangle;
}

public volatile float mScale = 1;
public volatile float mXFocus;
public volatile float mYFocus;

public void setZoom(float scale){
    mScale = scale;
}

public void setFocus(float XFocus, float YFocus){
    mXFocus = XFocus;
    mYFocus = YFocus;
}

public float getmScale(){
    return mScale;
}

public float getmXFocus(){
    return mXFocus;
}

public float getmYFocus(){
    return mYFocus;
}

public void setLineArray(ArrayList<ArrayList<String>> XLine){
    LineArray = XLine;
}

public ArrayList<ArrayList<String>> getLineArray(){
    return LineArray;
}

public void setUndoL(ArrayList<ArrayList<String>> UndoLine){
    this.UndoL.add(new ArrayList<ArrayList<String>>(UndoLine));
}

public ArrayList<ArrayList<ArrayList<String>>> getUndoL() {
    return UndoL;
}

public void setUndoP(ArrayList<ArrayList<String>> UndoPoint){
    this.UndoP.add(new ArrayList<ArrayList<String>>(UndoPoint));
}

public ArrayList<ArrayList<ArrayList<String>>> getUndoP() {
    return UndoP;
}

public void setPointArray(ArrayList<ArrayList<String>> XPoint){
    PointArray = XPoint;
}

public ArrayList<ArrayList<String>> getPointArray(){
    return PointArray;
}

给出错误contents_sample_state:[agr({[3,38] = 11,[3,7,38] = 28})]

public class Line {

private FloatBuffer VertexBuffer;

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;" +

                "attribute vec4 vPosition;" +
                "void main() {" +
                // the matrix must be included as a modifier of gl_Position
                "  gl_Position = uMVPMatrix * vPosition;" +
                "}";

private final String FragmentShaderCode =
        "precision mediump float;" +
                "uniform vec4 vColor;" +
                "void main() {" +
                "  gl_FragColor = vColor;" +
                "}";

protected int GlProgram;
protected int PositionHandle;
protected int ColorHandle;
protected int MVPMatrixHandle;

// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static float LineCoords[] = {
        0.0f, 0.0f, 0.0f,
        1.0f, 0.0f, 0.0f
};

private final int VertexCount = LineCoords.length / COORDS_PER_VERTEX;
private final int VertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex

// Set color with red, green, blue and alpha (opacity) values
float color[] = { 0.0f, 0.0f, 0.0f, 1.0f };

public Line() {
    // initialize vertex byte buffer for shape coordinates
    ByteBuffer bb = ByteBuffer.allocateDirect(
            // (number of coordinate values * 4 bytes per float)
            LineCoords.length * 4);
    // use the device hardware's native byte order
    bb.order(ByteOrder.nativeOrder());

    // create a floating point buffer from the ByteBuffer
    VertexBuffer = bb.asFloatBuffer();
    // add the coordinates to the FloatBuffer
    VertexBuffer.put(LineCoords);
    // set the buffer to read the first coordinate
    VertexBuffer.position(0);

    int vertexShader = GLRender.loadShader(GLES20.GL_VERTEX_SHADER, VertexShaderCode);
    int fragmentShader = GLRender.loadShader(GLES20.GL_FRAGMENT_SHADER, FragmentShaderCode);

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

public void SetVerts(float v0, float v1, float v2, float v3, float v4, float v5) {
    LineCoords[0] = v0;
    LineCoords[1] = v1;
    LineCoords[2] = v2;
    LineCoords[3] = v3;
    LineCoords[4] = v4;
    LineCoords[5] = v5;

    VertexBuffer.put(LineCoords);
    // set the buffer to read the first coordinate
    VertexBuffer.position(0);
}

public void SetColor(float red, float green, float blue, float alpha) {
    color[0] = red;
    color[1] = green;
    color[2] = blue;
    color[3] = alpha;
}

public void draw(float[] mvpMatrix) {
    // Add program to OpenGL ES environment
    GLES20.glUseProgram(GlProgram);

    // get handle to vertex shader's vPosition member
    PositionHandle = GLES20.glGetAttribLocation(GlProgram, "vPosition");

    // Enable a handle to the triangle vertices
    GLES20.glEnableVertexAttribArray(PositionHandle);

    // Prepare the triangle coordinate data
    GLES20.glVertexAttribPointer(PositionHandle, COORDS_PER_VERTEX,
            GLES20.GL_FLOAT, false,
            VertexStride, VertexBuffer);

    // get handle to fragment shader's vColor member
    ColorHandle = GLES20.glGetUniformLocation(GlProgram, "vColor");

    // Set color for drawing the triangle
    GLES20.glUniform4fv(ColorHandle, 1, color, 0);

    // get handle to shape's transformation matrix
    MVPMatrixHandle = GLES20.glGetUniformLocation(GlProgram, "uMVPMatrix");
    //GLRender.checkGlError("glGetUniformLocation");

    // Apply the projection and view transformation
    GLES20.glUniformMatrix4fv(MVPMatrixHandle, 1, false, mvpMatrix, 0);
    //GLRender.checkGlError("glUniformMatrix4fv");

    GLES20.glLineWidth(5);
    // Draw the triangle
    GLES20.glDrawArrays(GLES20.GL_LINES, 0, VertexCount);

    // Disable vertex array
    GLES20.glDisableVertexAttribArray(PositionHandle);
}
}

public class GLSurface extends GLSurfaceView {

//public static GLRender xRender;
ScaleGestureDetector ScaleDetect;
MainActivity mMain;
OpenGL XOPL = mMain.xOpenGL;

public GLSurface(Context context, AttributeSet attrs){
    super(context,  attrs);

    // Render the view only when there is a change in the drawing data
    //setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

    ScaleDetect = new ScaleGestureDetector(context, new ScaleDetectorListener());
}

private float mPreviousX;
private float mPreviousY;
float density = this.getResources().getDisplayMetrics().density;

private static final int MAX_CLICK_DURATION = 300;
private long pressStartTime;

@Override
public boolean onTouchEvent(MotionEvent e) {

            ScaleDetect.onTouchEvent(e);

            float x = e.getX();
            float y = e.getY();

            switch (e.getAction()) {

                case MotionEvent.ACTION_MOVE:

                    if(!ScaleDetect.isInProgress()) {

                        float xMoveRange = x - mPreviousX;
                        float yMoveRange = y - mPreviousY;
                        float dx = 0.0f;
                        float dy = 0.0f;
                        float w = this.getWidth();
                        float h = this.getHeight();

                        if (Math.abs(xMoveRange) > w / 100 && Math.abs(yMoveRange) < h / 100){
                            dx = xMoveRange / density / 2.0f;
                            XOPL.xRender.setAngleX(XOPL.xRender.getXAngle() + dx);
                        }

                        if (Math.abs(xMoveRange) < w / 100 && Math.abs(yMoveRange) > h / 100){
                            dy = yMoveRange / density / 2.0f;
                            XOPL.xRender.setAngleY(XOPL.xRender.getYAngle() + dy);
                        }

                            XOPL.myGLView.requestRender();
                    }

                    break;

                case MotionEvent.ACTION_DOWN:

                    pressStartTime = System.currentTimeMillis();
                    break;

                case MotionEvent.ACTION_UP:

                    long pressDuration = System.currentTimeMillis() - pressStartTime;
                    if (pressDuration < MAX_CLICK_DURATION) {

                        float Nx = (x - Float.parseFloat(Double.toString(this.getWidth())) * 0.5f) / (Float.parseFloat(Double.toString(this.getWidth())) * 0.5f);
                        float Ny = (y - Float.parseFloat(Double.toString(this.getHeight())) * 0.5f) / (Float.parseFloat(Double.toString(this.getHeight())) * 0.5f);
                        float Nz = 1.0f;

                        XOPL.xRender.setNCoordinate(Nx, Ny, Nz);
                        XOPL.xRender.Selection();
                        XOPL.myGLView.requestRender();
                    }
                    break;
            }

            mPreviousX = x;
            mPreviousY = y;

    return true;
}

private float sizeCoef = 1;

public class ScaleDetectorListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

    float scaleFocusX = 0;
    float scaleFocusY = 0;

    public boolean onScale(ScaleGestureDetector arg0) {
        float scale = arg0.getScaleFactor() * sizeCoef;

        sizeCoef = scale;

        XOPL.xRender.setZoom(sizeCoef);
        XOPL.myGLView.requestRender();

        return true;
    }

    public boolean onScaleBegin(ScaleGestureDetector arg0) {
        invalidate();

        scaleFocusX = arg0.getFocusX();
        scaleFocusY = arg0.getFocusY();

        XOPL.xRender.setFocus(scaleFocusX,scaleFocusY);

        return true;
    }

    public void onScaleEnd(ScaleGestureDetector arg0) {
        scaleFocusX = 0;
        scaleFocusY = 0;

        XOPL.xRender.setFocus(scaleFocusX,scaleFocusY);
    }
}
}

1 个答案:

答案 0 :(得分:0)

不确定这是否是问题,但请注意以下事项:

  

XOPL.xRender.setAngleX(XOPL.xRender.getXAngle()+ dx)

...尤其是在着色器中使用mediump精度时。一般情况下,我建议更改setAngle函数以利用旋转对称性并将值包装起来,这样就可以得到API级别为+ -Pi的绝对范围。

在当前代码中,如果用户继续向一个方向滑动,最终你将运行我们的位,一切都将停止旋转(最好),或者无效或NaN结果失败(最坏的情况下)。 / p>

注意使用&#34; -Pi到+ Pi&#34;最好使用&#34; 0到+ 2Pi&#34;,因为符号位在大多数浮点表示中是空闲的,因此保留了更多的动态精度。

示例代码:

public float wrapRadians(float angle) {
    // If angle is negative ensure value is higher than minus pi
    if (angle < 0) {
        while (angle < -math.PI) {
            angle += 2 * math.PI;
        }
    // Else angle is positive so ensure value is less than pi
    } else {
        while (angle > math.PI) {
            angle -= 2 * math.PI;
        }
    }

    return angle;
}

public float setXAngle(float XAngle) {
    mXAngle = wrapRadians(XAngle);
}

public float setYAngle(float YAngle) {
    mYAngle = wrapRadians(YAngle);
}