/// <summary> /// Un-projects a 2D screen point. /// </summary> /// <param name="viewport">The viewport.</param> /// <param name="point2d">The input point.</param> /// <returns>The ray.</returns> public static Ray UnProject(this Viewport3DX viewport, Vector2 point2d)//, out Vector3 pointNear, out Vector3 pointFar) { var camera = viewport.Camera as ProjectionCamera; if (camera != null) { var px = (float)point2d.X; var py = (float)point2d.Y; var viewMatrix = camera.GetViewMatrix(); Vector3 v = new Vector3(); var matrix = CameraExtensions.InverseViewMatrix(ref viewMatrix); float w = (float)viewport.ActualWidth; float h = (float)viewport.ActualHeight; var aspectRatio = w / h; var projMatrix = camera.GetProjectionMatrix(aspectRatio); Vector3 zn, zf; v.X = (2 * px / w - 1) / projMatrix.M11; v.Y = -(2 * py / h - 1) / projMatrix.M22; v.Z = 1 / projMatrix.M33; Vector3.TransformCoordinate(ref v, ref matrix, out zf); if (camera is PerspectiveCamera) { zn = camera.Position.ToVector3(); } else { v.Z = 0; Vector3.TransformCoordinate(ref v, ref matrix, out zn); } Vector3 r = zf - zn; r.Normalize(); return(new Ray(zn, r)); } throw new HelixToolkitException("Unproject camera error."); }
/// <summary> /// Initial implementation of hittest for billboard. Needs further improvement. /// </summary> /// <param name="rayWS"></param> /// <param name="hits"></param> /// <returns></returns> protected override bool OnHitTest(IRenderMatrices context, Ray rayWS, ref List <HitTestResult> hits) { var g = this.geometryInternal as IBillboardText; var h = false; var result = new HitTestResult(); result.Distance = double.MaxValue; if (context == null || g.Width == 0 || g.Height == 0) { return(false); } if (g != null) { BoundingBox b = new BoundingBox(); var left = -g.Width / 2; var right = -left; var top = -g.Height / 2; var bottom = -top; if (FixedSize) { var viewportMatrix = context.ViewportMatrix; var projectionMatrix = context.ProjectionMatrix; var viewMatrix = context.ViewMatrix; var visualToScreen = viewMatrix * projectionMatrix * viewportMatrix; var center = new Vector4(g.Positions[0], 1); var screenPoint = Vector4.Transform(center, visualToScreen); var spw = screenPoint.W; var spx = screenPoint.X; var spy = screenPoint.Y; var spz = screenPoint.Z / spw / projectionMatrix.M33; var matrix = CameraExtensions.InverseViewMatrix(ref viewMatrix); var width = (float)context.ActualWidth; var height = (float)context.ActualHeight; Vector3 v = new Vector3(); var x = spx + left * spw; var y = spy + bottom * spw; v.X = (2 * x / width / spw - 1) / projectionMatrix.M11; v.Y = -(2 * y / height / spw - 1) / projectionMatrix.M22; v.Z = spz; Vector3 bl; Vector3.TransformCoordinate(ref v, ref matrix, out bl); x = spx + right * spw; y = spy + bottom * spw; v.X = (2 * x / width / spw - 1) / projectionMatrix.M11; v.Y = -(2 * y / height / spw - 1) / projectionMatrix.M22; v.Z = spz; Vector3 br; Vector3.TransformCoordinate(ref v, ref matrix, out br); x = spx + right * spw; y = spy + top * spw; v.X = (2 * x / width / spw - 1) / projectionMatrix.M11; v.Y = -(2 * y / height / spw - 1) / projectionMatrix.M22; v.Z = spz; Vector3 tr; Vector3.TransformCoordinate(ref v, ref matrix, out tr); x = spx + left * spw; y = spy + top * spw; v.X = (2 * x / width / spw - 1) / projectionMatrix.M11; v.Y = -(2 * y / height / spw - 1) / projectionMatrix.M22; v.Z = spz; Vector3 tl; Vector3.TransformCoordinate(ref v, ref matrix, out tl); b = BoundingBox.FromPoints(new Vector3[] { tl, tr, bl, br }); /* * var visualToScreen = viewport.GetViewProjectionMatrix() * viewport.GetViewportMatrix(); * * var screenToVisual = visualToScreen.Inverted(); * * var center = new Vector4(g.Positions[0], 1); * var screenPoint = Vector4.Transform(center, visualToScreen); * var spw = screenPoint.W; * var spx = screenPoint.X; * var spy = screenPoint.Y; * var spz = screenPoint.Z; * * //Debug.WriteLine(spw); * // Debug.WriteLine(string.Format("Z={0}; W={1}", spz, spw)); * var bl = new Vector4(spx + left * spw, spy + bottom * spw, spz, spw); * bl = Vector4.Transform(bl, screenToVisual); * bl /= bl.W; * * var br = new Vector4(spx + right * spw, spy + bottom * spw, spz, spw); * br = Vector4.Transform(br, screenToVisual); * br /= br.W; * * var tr = new Vector4(spx + right * spw, spy + top * spw, spz, spw); * tr = Vector4.Transform(tr, screenToVisual); * tr /= tr.W; * * var tl = new Vector4(spx + left * spw, spy + top * spw, spz, spw); * tl = Vector4.Transform(tl, screenToVisual); * tl /= tl.W; * * b = BoundingBox.FromPoints(new Vector3[] { tl.ToVector3(), tr.ToVector3(), bl.ToVector3(), br.ToVector3() }); */ } else { var center = new Vector4(g.Positions[0], 1); var viewMatrix = context.ViewMatrix; var vcenter = Vector4.Transform(center, viewMatrix); var vcX = vcenter.X; var vcY = vcenter.Y; var bl = new Vector4(vcX + left, vcY + bottom, vcenter.Z, vcenter.W); var br = new Vector4(vcX + right, vcY + bottom, vcenter.Z, vcenter.W); var tr = new Vector4(vcX + right, vcY + top, vcenter.Z, vcenter.W); var tl = new Vector4(vcX + left, vcY + top, vcenter.Z, vcenter.W); var invViewMatrix = CameraExtensions.InverseViewMatrix(ref viewMatrix); bl = Vector4.Transform(bl, invViewMatrix); bl /= bl.W; br = Vector4.Transform(br, invViewMatrix); br /= br.W; tr = Vector4.Transform(tr, invViewMatrix); tr /= tr.W; tl = Vector4.Transform(tl, invViewMatrix); tl /= tl.W; b = BoundingBox.FromPoints(new Vector3[] { tl.ToVector3(), tr.ToVector3(), bl.ToVector3(), br.ToVector3() }); } // this all happens now in world space now: //Debug.WriteLine(string.Format("RayPosition:{0}; Direction:{1};", rayWS.Position, rayWS.Direction)); if (rayWS.Intersects(ref b)) { float distance; if (Collision.RayIntersectsBox(ref rayWS, ref b, out distance)) { h = true; result.ModelHit = this; result.IsValid = true; result.PointHit = (rayWS.Position + (rayWS.Direction * distance)).ToPoint3D(); result.Distance = distance; Debug.WriteLine(string.Format("Hit; HitPoint:{0}; Bound={1}; Distance={2}", result.PointHit, b, distance)); } } } if (h) { hits.Add(result); } return(h); }
public override void Render(RenderContext context) { if (!this.renderHost.IsShadowMapEnabled) { return; } /// --- set rasterizes state here with proper shadow-bias, as depth-bias and slope-bias in the rasterizer this.Device.ImmediateContext.Rasterizer.SetViewport(0, 0, width, height, 0.0f, 1.0f); this.Device.ImmediateContext.OutputMerger.SetTargets(depthViewSM); this.Device.ImmediateContext.ClearDepthStencilView(depthViewSM, DepthStencilClearFlags.Depth | DepthStencilClearFlags.Stencil, 1.0f, 0); var root = context.Canvas.Renderable.Items; foreach (var item in root) { var light = item as Light3D; if (light != null) { Camera lightCamera = null; //if (light is PointLightBase3D) //{ // var plight = (PointLightBase3D)light; // lightCamera = new PerspectiveCamera() // { // Position = plight.Position, // LookDirection = plight.Direction, // UpDirection = Vector3.UnitY.ToVector3D(), // }; //} // else if (light is DirectionalLight3D) { var dlight = (DirectionalLight3D)light; var dir = light.Direction.Normalized(); var pos = -50 * light.Direction; //lightCamera = new PerspectiveCamera() //{ // LookDirection = dir.ToVector3D(), // Position = (System.Windows.Media.Media3D.Point3D)(pos.ToVector3D()), // UpDirection = Vector3.UnitZ.ToVector3D(), // NearPlaneDistance = 1, // FarPlaneDistance = 100, // FieldOfView = 10, //}; lightCamera = new OrthographicCamera() { LookDirection = dir.ToVector3D(), Position = (System.Windows.Media.Media3D.Point3D)(pos.ToVector3D()), UpDirection = Vector3.UnitZ.ToVector3D(), Width = 100, NearPlaneDistance = 1, FarPlaneDistance = 500, }; } if (lightCamera != null) { var sceneCamera = context.Camera; light.LightViewMatrix = CameraExtensions.GetViewMatrix(lightCamera); light.LightProjectionMatrix = CameraExtensions.GetProjectionMatrix(lightCamera, context.Canvas.ActualWidth / context.Canvas.ActualHeight); this.shadowPassContext.IsShadowPass = true; this.shadowPassContext.Camera = lightCamera; foreach (var e in root) { var smodel = e as IThrowingShadow; if (smodel != null) { if (smodel.IsThrowingShadow) { var model = smodel as IRenderable; model.Render(this.shadowPassContext); } } } context.Camera = sceneCamera; } } } this.texShadowMapVariable.SetResource(this.texShadowMapView); //this.texShadowMapVariable.SetResource(this.texColorMapView); this.vShadowMapInfoVariable.Set(new Vector4((float)this.Intensity, (float)this.FactorPCF, (float)this.Bias, 0)); this.vShadowMapSizeVariable.Set(new Vector2(width, height)); //System.Console.WriteLine("ShadowMap rendered!"); context.Canvas.SetDefaultRenderTargets(); }