ARCore 2D对象未正确粘在锚点上

时间:2019-03-08 02:59:06

标签: c# android xamarin opengl-es arcore

我一直在修补HelloAR Xamarin sample。目前,我正在处理某些2D形状,并且尝试将三角形绑定到锚点。 大多数情况下,当我将手机放到适当的位置时,三角形似乎固定在其锚点上,并且在来回移动时三角形会收缩并增大。但是,在移动电话时(即:使自己与三角形的侧面平行地向侧面移动),三角形沿与相机相同的方向稍微移动。同样,在来回移动时,三角形确实会在场景中上下移动。这是一些显示正在发生的事情的图片(我添加了垂直线):

enter image description here

从图片中可以看到,当我向左移动时,三角形正缓慢地爬到笔记本电脑的侧面,同时也逐渐从框架中消失。我觉得我的代码与原始示例中使用的ObjectRenderer.cs非常相似。这是我等效的updateModelMatrixCreateOnGlThreadDraw

public void updateModelMatrix(float[] modelMatrix, float scaleFactor) {
        float[] scaleMatrix = new float[16];
        Android.Opengl.Matrix.SetIdentityM(scaleMatrix, 0);
        scaleMatrix[0] = scaleFactor;
        scaleMatrix[5] = scaleFactor;
        scaleMatrix[10] = scaleFactor;
        Android.Opengl.Matrix.MultiplyMM(mViewMatrix, 0, modelMatrix, 0, scaleMatrix, 0);
    }

public void CreateOnGlThread(Context _context) {
        vertexBuffer = ByteBuffer
                    .AllocateDirect(triangleCords.Length * BYTES_PER_FLOAT).Order(ByteOrder.NativeOrder())
                    .AsFloatBuffer();
        vertexBuffer.Put(triangleCords).Position(0);

        indices = ByteBuffer.AllocateDirect(BYTES_PER_SHORT * triangleIndices.Length)
            .Order(ByteOrder.NativeOrder()).AsShortBuffer();
        indices.Put(triangleIndices).Position(0);

        int[] buffers = new int[2];
        GLES20.GlGenBuffers(2, buffers, 0);
        mVertexBufferId = buffers[0];
        mIndexBufferId = buffers[1];

        GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVertexBufferId);
        GLES20.GlBufferData(GLES20.GlArrayBuffer, triangleCords.Length * BYTES_PER_FLOAT, vertexBuffer, GLES20.GlStaticDraw);
        GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVertexBufferId);

        GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, mIndexBufferId);
        mIndexCount = triangleIndices.Length;
        GLES20.GlBufferData(
            GLES20.GlElementArrayBuffer, BYTES_PER_SHORT * mIndexCount, indices, GLES20.GlStaticDraw);
        GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, mIndexBufferId);

        int vertexShader = loadShader(GLES20.GlVertexShader, vertexShaderCode);
        int fragmentShader = loadShader(GLES20.GlFragmentShader, fragmentShaderCode);

        program = GLES20.GlCreateProgram();
        GLES20.GlAttachShader(program, vertexShader);
        GLES20.GlAttachShader(program, fragmentShader);
        GLES20.GlLinkProgram(program);
        positionHandle = GLES20.GlGetAttribLocation(program, "a_Position");
        colorHandle = GLES20.GlGetUniformLocation(program, "vColor");
        mModerViewMatrixHandle = GLES20.GlGetUniformLocation(program, "u_ModelView");
        mModelViewProjectionMatrixHandle = GLES20.GlGetUniformLocation(program, "u_ModelViewProjection");
        Android.Opengl.Matrix.SetIdentityM(mViewMatrix, 0);
    }
public void Draw(float[] _cameraView, float[] _cameraPerspective) {
        Android.Opengl.Matrix.MultiplyMM(mModelViewMatrix, 0, _cameraView, 0, mViewMatrix, 0);
        Android.Opengl.Matrix.MultiplyMM(mModelViewProjectionMatrix, 0, _cameraPerspective, 0, mModelViewMatrix, 0);
        GLES20.GlUseProgram(program);
        GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVertexBufferId);

        GLES20.GlVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GlFloat, false, 0, 0);
        GLES20.GlEnableVertexAttribArray(positionHandle);

        GLES20.GlUniform4fv(colorHandle, 1, COLOR, 0);
        GLES20.GlUniformMatrix4fv(mModerViewMatrixHandle, 1, false, mModelViewMatrix, 0);
        GLES20.GlUniformMatrix4fv(mModelViewProjectionMatrixHandle, 1, false, mModelViewProjectionMatrix, 0);


        GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, mIndexBufferId);
        GLES20.GlDrawElements(GLES20.GlTriangles, mIndexCount, GLES20.GlUnsignedShort, 0);
        GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0);
        GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, 0);
    }

GLSurfaceView.IRenderer.OnDrawFrame传递到这些函数的参数应该与原始示例的参数相同:

void GLSurfaceView.IRenderer.OnDrawFrame(IGL10 gl)
    {
        ...

        try {
            Frame frame = session.Update();
            Camera camera = frame.Camera;
            ...

            if (tap != null && camera.TrackingState == TrackingState.Tracking) {
                foreach (var hit in frame.HitTest(tap)) {

                    var trackable = hit.Trackable;
                    if (trackable is Plane && ((Plane)trackable).IsPoseInPolygon(hit.HitPose)) {

                        shapeAnchor = hit.CreateAnchor();
                        break;
                    }
                }
            }

            backgroundRenderer.Draw(frame);

            if (shapeAnchor != null && shapeAnchor.TrackingState == TrackingState.Tracking) {
                float[] projmtx = new float[16];
                camera.GetProjectionMatrix(projmtx, 0, 0.1f, 100.0f);

                float[] viewmtx = new float[16];
                camera.GetViewMatrix(viewmtx, 0);

                shapeAnchor.Pose.ToMatrix(anchorMatrix, 0);
                triangleRenderer.updateModelMatrix(anchorMatrix, 1);
                triangleRenderer.Draw(viewmtx, projmtx);
            }


        } catch (Exception _ex) {
            var x = true;
        }
    }

此外,我的顶点着色器非常简单:

        private string vertexShaderCode =
        "uniform mat4 u_ModelView;" +
        "uniform mat4 u_ModelViewProjection;" +
        "attribute vec4 a_Position;" +
        "varying vec3 v_ViewPosition;" +
        "void main() {" +
        "  v_ViewPosition = (u_ModelView * a_Position).xyz;" +
        "  gl_Position = u_ModelViewProjection * a_Position;" +
        "}";

最终它会脱离框架的事实令我有些困惑,在移至2D对象时我使用矩阵的方式肯定存在问题。有什么想法吗?

0 个答案:

没有答案