Exemplo n.º 1
0
        /**
         * Draws the collection of tracked planes, with closer planes hiding more distant ones.
         *
         * @param allPlanes The collection of planes to draw.
         * @param cameraPose The pose of the camera, as returned by {@link Frame#getPose()}
         * @param cameraPerspective The projection matrix, as returned by
         *     {@link Session#getProjectionMatrix(float[], int, float, float)}
         */
        public void DrawPlanes(IEnumerable <Plane> allPlanes, Pose cameraPose, float[] cameraPerspective)
        {
            // Planes must be sorted by distance from camera so that we draw closer planes first, and
            // they occlude the farther planes.
            List <SortablePlane> sortedPlanes = new List <SortablePlane>();

            float[] normal  = new float[3];
            float   cameraX = cameraPose.Tx();
            float   cameraY = cameraPose.Ty();
            float   cameraZ = cameraPose.Tz();

            foreach (var plane in allPlanes)
            {
                if (plane.GetType() != Plane.Type.HorizontalUpwardFacing ||
                    plane.GetTrackingState() != Plane.TrackingState.Tracking)
                {
                    continue;
                }

                var center = plane.CenterPose;
                // Get transformed Y axis of plane's coordinate system.
                center.GetTransformedAxis(1, 1.0f, normal, 0);
                // Compute dot product of plane's normal with vector from camera to plane center.
                float distance = (cameraX - center.Tx()) * normal[0] +
                                 (cameraY - center.Ty()) * normal[1] + (cameraZ - center.Tz()) * normal[2];
                if (distance < 0)
                {  // Plane is back-facing.
                    continue;
                }
                sortedPlanes.Add(new SortablePlane(distance, plane));
            }

            sortedPlanes.Sort((x, y) => x.Distance.CompareTo(y.Distance));


            var cameraView = new float[16];

            cameraPose.Inverse().ToMatrix(cameraView, 0);

            // Planes are drawn with additive blending, masked by the alpha channel for occlusion.

            // Start by clearing the alpha channel of the color buffer to 1.0.
            GLES20.GlClearColor(1, 1, 1, 1);
            GLES20.GlColorMask(false, false, false, true);
            GLES20.GlClear(GLES20.GlColorBufferBit);
            GLES20.GlColorMask(true, true, true, true);

            // Disable depth write.
            GLES20.GlDepthMask(false);

            // Additive blending, masked by alpha chanel, clearing alpha channel.
            GLES20.GlEnable(GLES20.GlBlend);
            GLES20.GlBlendFuncSeparate(
                GLES20.GlDstAlpha, GLES20.GlOne,            // RGB (src, dest)
                GLES20.GlZero, GLES20.GlOneMinusSrcAlpha);  // ALPHA (src, dest)

            // Set up the shader.
            GLES20.GlUseProgram(mPlaneProgram);

            // Attach the texture.
            GLES20.GlActiveTexture(GLES20.GlTexture0);
            GLES20.GlBindTexture(GLES20.GlTexture2d, mTextures[0]);
            GLES20.GlUniform1i(mTextureUniform, 0);

            // Shared fragment uniforms.
            GLES20.GlUniform4fv(mGridControlUniform, 1, GRID_CONTROL, 0);

            // Enable vertex arrays
            GLES20.GlEnableVertexAttribArray(mPlaneXZPositionAlphaAttribute);

            ShaderUtil.CheckGLError(TAG, "Setting up to draw planes");

            foreach (var sortedPlane in sortedPlanes)
            {
                var     plane       = sortedPlane.Plane;
                float[] planeMatrix = new float[16];
                plane.CenterPose.ToMatrix(planeMatrix, 0);


                updatePlaneParameters(planeMatrix, plane.ExtentX,
                                      plane.ExtentZ, plane.PlanePolygon);

                // Get plane index. Keep a map to assign same indices to same planes.

                int planeIndex = -1;
                if (!mPlaneIndexMap.TryGetValue(plane, out planeIndex))
                {
                    planeIndex = Java.Lang.Integer.ValueOf(mPlaneIndexMap.Count).IntValue();
                    mPlaneIndexMap.Add(plane, planeIndex);
                }

                // Set plane color. Computed deterministically from the Plane index.
                int colorIndex = planeIndex % PLANE_COLORS_RGBA.Length;

                colorRgbaToFloat(mPlaneColor, PLANE_COLORS_RGBA[colorIndex]);
                GLES20.GlUniform4fv(mLineColorUniform, 1, mPlaneColor, 0);
                GLES20.GlUniform4fv(mDotColorUniform, 1, mPlaneColor, 0);

                // Each plane will have its own angle offset from others, to make them easier to
                // distinguish. Compute a 2x2 rotation matrix from the angle.
                float angleRadians = planeIndex * 0.144f;
                float uScale       = DOTS_PER_METER;
                float vScale       = DOTS_PER_METER * EQUILATERAL_TRIANGLE_SCALE;
                mPlaneAngleUvMatrix[0] = +(float)Math.Cos(angleRadians) * uScale;
                mPlaneAngleUvMatrix[1] = -(float)Math.Sin(angleRadians) * uScale;
                mPlaneAngleUvMatrix[2] = +(float)Math.Sin(angleRadians) * vScale;
                mPlaneAngleUvMatrix[3] = +(float)Math.Cos(angleRadians) * vScale;
                GLES20.GlUniformMatrix2fv(mPlaneUvMatrixUniform, 1, false, mPlaneAngleUvMatrix, 0);


                Draw(cameraView, cameraPerspective);
            }

            // Clean up the state we set
            GLES20.GlDisableVertexAttribArray(mPlaneXZPositionAlphaAttribute);
            GLES20.GlBindTexture(GLES20.GlTexture2d, 0);
            GLES20.GlDisable(GLES20.GlBlend);
            GLES20.GlDepthMask(true);

            ShaderUtil.CheckGLError(TAG, "Cleaning up after drawing planes");
        }