ARCore 2D-объект неправильно прикреплен к якору - PullRequest
1 голос
/ 08 марта 2019

Я возился с HelloAR Xamarin sample .В настоящее время я работаю с некоторыми 2D-фигурами и пытаюсь привязать треугольник к якору.Это в основном работает , при включении телефона треугольник, кажется, прилипает к своему якору, а при движении вперед и назад треугольник сжимается и растет.Тем не менее, при перемещении телефона (т. Е. При перемещении себя вбок параллельно стороне треугольника) треугольник слегка перемещается в том же направлении, что и камера.Точно так же, перемещаясь назад и вперед, треугольник действительно перемещается вверх и вниз в сцене.Вот несколько рисунков, которые показывают, что происходит (добавленные мной вертикальные линии):

enter image description here

Как видно из рисунков, по мере продвижения кслева треугольник медленно ползет к боковой части ноутбука, а также медленно исчезает из рамки.Я чувствую, что мой код очень похож на ObjectRenderer.cs , использованный в исходном примере.Вот мои эквиваленты updateModelMatrix, CreateOnGlThread и Draw:

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-объекты.Есть идеи?

...