/// <summary> /// Callback from the EasyAR component whic renders the foreground nodes. /// </summary> /// <param name="oFrame"></param> /// <param name="cameraParameters"></param> /// <param name="aspectRatio"></param> /// <param name="rotation"></param> protected void OnARFrameUpdated(OutputFrame oFrame, CameraParameters cameraParameters, float aspectRatio, int rotation) { var far = 100f; var near = 0.01f; Matrix44F sp = cameraParameters.projection(near, far, aspectRatio, rotation, true, false); foreach (Optional <FrameFilterResult> unTypedResult in oFrame.results()) { if (unTypedResult.OnSome) { if (unTypedResult.Some is ImageTrackerResult result) { int targetIndex = 0; List <TargetInstance> targetInstances = result.targetInstances(); foreach (TargetInstance targetInstance in targetInstances) { TargetStatus status = targetInstance.status(); if (status == TargetStatus.Tracked) { Optional <Target> optionalTarget = targetInstance.target(); if (optionalTarget.OnSome) { Target target = optionalTarget.Some; if (target is ImageTarget imageTarget) { List <Image> images = imageTarget.images(); Image targetImage = images[0]; Matrix4 prj = sp.ToUrhoMatrix(); prj.M34 /= 2f; prj.M33 = far / (far - near); prj.M43 *= -1; fgCamera.SetProjection(prj); Matrix4 convertedPoseMatrix = targetInstance.pose().ToUrhoMatrix(); Vector3 scale = new Vector3(imageTarget.scale(), imageTarget.scale() * targetImage.height() / targetImage.width(), 1); UpdateArScene(targetIndex, convertedPoseMatrix, scale); foreach (Image targetImageToRelease in images) { targetImageToRelease.Dispose(); } } target.Dispose(); } } targetInstance.Dispose(); targetIndex++; } // Remove any targets that can no longer be located while (targetNodes.Count > targetIndex) { Node node = targetNodes[targetIndex]; targetNodes.RemoveAt(targetIndex); node.Remove(); } } unTypedResult.Some.Dispose(); } } }
/// <summary> /// Detects new output frames and updates the camera, then passes the output frame through an event to update the foreground /// </summary> /// <param name="timeStep"></param> protected override void OnUpdate(float timeStep) { if (paused) { return; } Optional <OutputFrame> optionalOframe = OutputFrameBuffer.peek(); if (optionalOframe.OnSome) { OutputFrame oframe = optionalOframe.Some; Optional <InputFrame> optionalIframe = oframe.inputFrame(); if (optionalIframe.OnSome) { InputFrame iframe = optionalIframe.Some; CameraParameters cameraParameters = iframe.cameraParameters(); if (cameraParameters != null) { Image image = iframe.image(); float aspectRatio = (float)(DeviceDisplay.MainDisplayInfo.Width / DeviceDisplay.MainDisplayInfo.Height); int rotation = 0; switch (DeviceDisplay.MainDisplayInfo.Rotation) { case DisplayRotation.Rotation90: rotation = 90; break; case DisplayRotation.Rotation180: rotation = 180; break; case DisplayRotation.Rotation270: rotation = 270; break; } if (iframe.index() != previousInputFrameIndex) { Matrix44F ip = cameraParameters.imageProjection(aspectRatio, rotation, true, false); Matrix4 iprj = ip.ToUrhoMatrix(); bgCamera.SetProjection(iprj); EasyAR.Buffer buffer = image.buffer(); try { backgroundUpdater.UpdateTexture(Application, image.format(), image.width(), image.height(), buffer); } finally { buffer.Dispose(); } previousInputFrameIndex = iframe.index(); } ARFrameUpdated?.Invoke(oframe, cameraParameters, aspectRatio, rotation); image.Dispose(); cameraParameters.Dispose(); } iframe.Dispose(); } oframe.Dispose(); } base.OnUpdate(timeStep); }