using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using OpenTK; using OpenTK.Graphics.OpenGL; using bbiwarg.Images; using bbiwarg.Recognition.TouchRecognition; using bbiwarg.Utility; using Emgu.CV; using Emgu.CV.Structure; namespace bbiwarg.Graphics { class OutputWindow : GameWindow { private VideoHandle videoHandle; private uint textureId; private bool paused = false; private long timeSpacePressed, timeLeftPressed, timeRightPressed; private Stopwatch watch; public OutputWindow(VideoHandle videoHandle) : base((int) (Constants.OutputScaleFactor * Math.Max(1, Math.Min(Constants.OutputNumImagesPerRow, videoHandle.OutputImages.Length)) * videoHandle.Width), (int) (Constants.OutputScaleFactor * (1 + (videoHandle.OutputImages.Length - 1) / Constants.OutputNumImagesPerRow) * videoHandle.Height)) { this.videoHandle = videoHandle; watch = new Stopwatch(); watch.Start(); } protected override void OnLoad(EventArgs e) { base.OnLoad(e); Title = "BBIWARG - Output"; GL.ClearColor(Color.Black); // transparency GL.Enable(EnableCap.Blend); GL.BlendEquation(BlendEquationMode.Max); //Depth Test GL.Enable(EnableCap.DepthTest); // Texture GL.Enable(EnableCap.Texture2D); GL.GenTextures(1, out textureId); GL.BindTexture(TextureTarget.Texture2D, textureId); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); } protected override void OnResize(EventArgs e) { base.OnResize(e); int screenWidth = ClientRectangle.Width; int screenHeight = ClientRectangle.Height; int imageWidth = videoHandle.Width; int imageHeight = videoHandle.Height; float imageAspectRatio = (float)imageWidth / (float)imageHeight; int numImages = videoHandle.OutputImages.Length; int numRows = 1 + (numImages - 1) / Constants.OutputNumImagesPerRow; int numCols = Math.Min(videoHandle.OutputImages.Length, Constants.OutputNumImagesPerRow); int heightForWidth = (int)((float)screenWidth / ((float)numCols * imageAspectRatio) * (float)numRows); GL.Viewport(0, (screenHeight - heightForWidth) / 2, screenWidth, heightForWidth); // top left at (0,0) every image from (i, j) to (i + 1, j + 1) Matrix4 projection = Matrix4.CreateOrthographicOffCenter(0, numCols, numRows, 0, 0.001f, 10f); GL.MatrixMode(MatrixMode.Projection); GL.LoadMatrix(ref projection); } protected override void OnRenderFrame(FrameEventArgs e) { Timer.start("onRenderFrame"); base.OnRenderFrame(e); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); Matrix4 modelview = Matrix4.LookAt(Vector3.Zero, -Vector3.UnitZ, Vector3.UnitY); GL.MatrixMode(MatrixMode.Modelview); GL.LoadMatrix(ref modelview); const int autoRepeatDelay = 100; // ms if (videoHandle.sourceIsMovie()) { // pause and unpause with space long elapsed = watch.ElapsedMilliseconds; if (OpenTK.Input.Keyboard.GetState().IsKeyDown(OpenTK.Input.Key.Space) && (elapsed - timeSpacePressed) >= autoRepeatDelay) { timeSpacePressed = elapsed; if (paused) videoHandle.unpauseMovie(); else videoHandle.pauseMovie(); paused = !paused; } // when paused go to next / previous frame with right / left keys if (paused) { if (OpenTK.Input.Keyboard.GetState().IsKeyDown(OpenTK.Input.Key.Right) && (elapsed - timeRightPressed) >= autoRepeatDelay) { timeRightPressed = elapsed; videoHandle.unpauseMovie(); videoHandle.nextFrame(); videoHandle.pauseMovie(); } else if (OpenTK.Input.Keyboard.GetState().IsKeyDown(OpenTK.Input.Key.Left) && (elapsed - timeLeftPressed) >= autoRepeatDelay) { timeLeftPressed = elapsed; videoHandle.unpauseMovie(); videoHandle.reversePlay(); videoHandle.nextFrame(); videoHandle.reversePlay(); videoHandle.pauseMovie(); } } else { videoHandle.nextFrame(); } } else { videoHandle.nextFrame(); } if (videoHandle.sourceIsMovie()) Title = "BBIWARG - Output (Frame " + videoHandle.CurrentFrame + ")"; Timer.start("buildTextures"); GL.Enable(EnableCap.Texture2D); int imageIndex = 0; foreach (OutputImage image in videoHandle.OutputImages) { int x = imageIndex % Constants.OutputNumImagesPerRow; int y = imageIndex / Constants.OutputNumImagesPerRow; GL.BindTexture(TextureTarget.Texture2D, textureId); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, videoHandle.Width, videoHandle.Height, 0, PixelFormat.Rgb, PixelType.UnsignedByte, image.Image.MIplImage.imageData); GL.Begin(PrimitiveType.Quads); GL.Color3(1.0, 1.0, 1.0); GL.TexCoord2(0, 0); GL.Vertex3(0 + x, 0 + y, -1); GL.TexCoord2(1, 0); GL.Vertex3(1 + x, 0 + y, -1); GL.TexCoord2(1, 1); GL.Vertex3(1 + x, 1 + y, -1); GL.TexCoord2(0, 1); GL.Vertex3(0 + x, 1 + y, -1); GL.End(); ++imageIndex; } Timer.stop("buildTextures"); Timer.start("swapBuffers"); SwapBuffers(); Timer.stop("swapBuffers"); Timer.stop("onRenderFrame"); Timer.outputAll(); } } }