public ProgramTask() { Monitor.ClientSize = new Size(640, 480); ColoredChessboard = new ColoredChessboard(Chessboard, Color.CornflowerBlue.Alpha(0.9f), Color.Orange.Alpha(0.3f)); var maybeSecondaryScreen = Screen.AllScreens.Where(s => s != Screen.PrimaryScreen).FirstOrDefault() ?? Screen.PrimaryScreen; // Projector = new RealProjector("Optoma EW1610", "1018", maybeSecondaryScreen.Bounds.Size, maybeSecondaryScreen); var virtualProjectorOrbit = new OrbitCamera("Virtual Projector Orbit", "N/A", new Size(1280, 800), new PointF(640, 850), 100, 2, 134); Projector = new VirtualProjector(Monitor, virtualProjectorOrbit); WorldCamera = new OrbitCamera("World Orbit", "1018", Monitor.Size, Monitor.Size.CenterF(), Monitor.Size.Width, 0.1f, 100) { Center = Chessboard.VertexCenter, Distance = 56, YawPitch = new Vector2(0.2f, -0.2f), }; WorldScene = new Scene(WorldCamera) { // MakeColoredAxisOfLength(Vector3.UnitX, Color.Red, length: 20.0f), // MakeColoredAxisOfLength(Vector3.UnitY, Color.Green, length: 20.0f), // MakeColoredAxisOfLength(Vector3.UnitZ, Color.Blue, length: 20.0f), // ColoredChessboard, // new Grid(Matrix.CreateRotationX(MathHelper.PiOver2), Color.Red.Lerp(Color.White, 0.9f).Alpha(0.3f), Color.Red.Alpha(0.5f)), // new Grid(Matrix.CreateRotationY(-MathHelper.PiOver2), Color.Green.Lerp(Color.White, 0.9f).Alpha(0.1f), Color.Green.Alpha(0.3f)), // new Grid(Matrix.Identity, Color.Blue.Lerp(Color.White, 0.9f).Alpha(0.1f), Color.Blue.Alpha(0.4f)), new MeshModel("ManStanding", Matrix.CreateScale(0.1f) * Matrix.CreateRotationY(-MathHelper.PiOver2) * Matrix.CreateTranslation(4, 0, 2)) { ProjectorViewProject = Projector }, new MeshModel("MutantStanding", Matrix.CreateScale(0.4f) * Matrix.CreateRotationY(0) * Matrix.CreateTranslation(8, 0, 1)) { ProjectorViewProject = Projector }, new MeshModel("HeadFemale", Matrix.CreateScale(0.2f) * Matrix.CreateRotationX(-MathHelper.PiOver2) * Matrix.CreateTranslation(-3, 6, 0)) { ProjectorViewProject = Projector }, }; CaptureCameras = CreateCaptureCameras().ToList(); if (CaptureCameras.IsEmpty()) AddVirtualCaptureCamera("VirCam 1", "1018", Color.Red); CaptureCameraSelectionPictureGray = new Picture2D(CaptureCameraSelected.Intrinsics.ImageSize.LimitProportional(290, 290).AnchorWithin(Monitor.ClientRectangle, AnchorPoints.BottomLeft), CaptureCameraSelected.Capture.GrayTexture2D); CaptureCameraSelectionPictureRgba = new Picture2D(CaptureCameraSelected.Intrinsics.ImageSize.LimitProportional(290, 290).ToRect(CaptureCameraSelectionPictureGray.Rectangle.Left, CaptureCameraSelectionPictureGray.Rectangle.Top, AnchorPoints.BottomLeft), CaptureCameraSelected.Capture.RgbaTexture2D); CaptureCameraSelected.Highlight = true; WorldScene.Add(CaptureCameras); WorldScene.Add(Projector); Monitor.Scene = new Scene(new ScreenCamera(Monitor)) { new Clear(Color.LightGray), WorldScene, CaptureCameraSelectionPictureGray, CaptureCameraSelectionPictureRgba, }; LocateTrigger = new Trigger(() => new LocateTask(Monitor, CaptureCameraSelected, Chessboard).Run(), Keys.L); CalibrateTrigger = new Trigger(() => new CalibrateTask(Monitor, CaptureCameraSelected, Chessboard).Run(CaptureCameraSelected), Keys.C); ChessboardShapeTrigger = new Trigger(() => new ChessboardShapeTask(Monitor, Projector, Chessboard).Run(), Keys.S); CalibrateIndirectlyTrigger = new Trigger(() => { WorldScene.Remove(ColoredChessboard); return new CalibrateIndirectlyTask(Monitor, CaptureCameras, Projector, Chessboard).Run(WorldScene); }, Keys.I); GrayScanTrigger = new Trigger(() => new GrayScanTask(Monitor, CaptureCameras.First(), Projector).Run(WorldScene), Keys.G); AttachInputToCamera(Program.WhenInput.Where(input => !input.KeyPressed(Keys.LeftAlt)), Monitor, WorldCamera); AttachInputToCamera(Program.WhenInput.Where(input => input.KeyPressed(Keys.LeftAlt)), Monitor, virtualProjectorOrbit); AttachPerformanceBar(); Program.WhenInput.Where(input => input.KeyDown(Keys.Tab)).Subscribe(input => { CaptureCameraSelected.Highlight = false; CaptureCameraSelectionIdx = (CaptureCameraSelectionIdx + 1) % CaptureCameras.Count; CaptureCameraSelected.Highlight = true; CaptureCameraSelectionPictureGray.Texture2D = CaptureCameraSelected.Capture.GrayTexture2D; CaptureCameraSelectionPictureRgba.Texture2D = CaptureCameraSelected.Capture.RgbaTexture2D; }); }
public async Task<PinHole> Run(Services services, IEnumerable<Intrinsics> intrinsics) { var monitor = services.Monitor; var projector = services.Projectors.First(); monitor.FullScreen = false; projector.FullScreen = true; monitor.Show(); projector.Show(); Vector3[] projectorCorners; var chessboard = SculptChessboardTask.Load(out projectorCorners, projector.ClientSize); var confirmTrigger = from key in projector.KeyDown where key.KeyCode == Keys.Space select default(Unit); var closeTrigger = from close in monitor.FormClosingObservable select close; bool done = false; var doneTrigger = Observable.Amb(confirmTrigger, closeTrigger); var pinHoles = services.Captures.Select((capture, idx) => new PinHole(capture, intrinsics.ToArray()[idx], services.Renderer)).ToArray(); var capture1 = services.Captures.First(); var texture2D = services.Renderer.LeaseFor(capture1); PointF[] corners = new PointF[chessboard.SaddleCount.Area()]; using (doneTrigger.Subscribe(_ => done = true)) using (capture1.Subscribe(picture => { using (picture) { CvInvoke.cvDrawChessboardCorners(picture.Bgra.Ptr, chessboard.SaddleCount, corners, corners.Length, 1); texture2D.SetData(picture.Bytes); } })) { var homography = chessboard.GetVertexHomographyTo(projectorCorners); var camera = new ScreenCamera2D(homography, Matrix.CreateOrthographicOffCenter(0, projector.ClientSize.Width, projector.ClientSize.Height, 0, 0, 1)); var orbitCamera = monitor.CreateOrbitCamera(50, monitor.Size.Ratio(), null); var picture2D = new Picture2D(services.Captures.First().Size.Scale(0.5f).AnchorWithin(monitor.ClientRectangle, AnchorPoints.BottomRight), texture2D) { Color = Color.White.Scale(0.9f), }; foreach (var pinHole in pinHoles) pinHole.LocateUsing(chessboard, corners); while (!done) { var pf = projector.Begin(services.Renderer); pf.Add(Color.White); pf.Add(camera); pf.Add(chessboard); await pf.PresentAsync(); var mf = monitor.Begin(services.Renderer); mf.Add(Color.DarkGray); mf.Add(chessboard); foreach (var pinHole in pinHoles) { var crns = pinHole.BoundingFrustum.GetCorners().Skip(4).Take(4).ToArray(); mf.Add(new Quad(crns[2], crns[3], crns[1], crns[0], picture2D.Texture2D, Color.White.Scale(0.8f))); mf.Add(pinHole.BoundingFrustum); if (corners != null) { var position = pinHole.World.Translation; mf.Add(new LineSegment(position, Vector3.Zero, 0.03f) { Color = Color.Fuchsia, }); for (int i = 0; i < corners.Length; ++i) { var corner = corners[i]; var ray = pinHole.BoundingFrustum.ThroughPixel(position, corner.X, corner.Y, pinHole.ImageWidth, pinHole.ImageHeight); var lineSegment = new LineSegment(ray.Position, ray.Position + 5.4f * ray.Direction, 0.005f) { Color = Palette.Get(i), }; mf.Add(lineSegment); } } } await mf.PresentAsync(); } } return null; }