![]() |
|
Keeping an object the same size in the view - Printable Version +- AB4D Forum (https://forum.ab4d.com) +-- Forum: Products Forums (https://forum.ab4d.com/forumdisplay.php?fid=4) +--- Forum: Ab3d.PowerToys (https://forum.ab4d.com/forumdisplay.php?fid=9) +--- Thread: Keeping an object the same size in the view (/showthread.php?tid=4043) |
Keeping an object the same size in the view - tim.rutter - 10-11-2017 I am creating a view in which I want to highlight certain 3D points. The object I use to highlight the point is a cross hair and I need this object to stay in the selected 3D location but scale as the camera is zoomed/panned so that the cross hair is always the same size. I'm struggling to work out the maths to calculate the object size based on the camera distance and width. What I'm doing at present is drawing a small PlaneVisual3D on which I paste a bitmap of the cross hair. I then rotate this plane so that it always faces the camera by applying the same rotation as the camera - this part works well. I then want to scale the plane so that it is always the same size on the screen. This of course depends on where the plane is relative to the camera. I also need this to work with a perspective and an orthographic camera as I have two separate views that use both camera types. Here's what I have tried so far. This neither works in perspective nor orthographic views. It does work at times but I think I'm going about it wrong. var fieldOfViewInRadians = MainCamera.FieldOfView * (Math.PI / 180.0); var cam = MainCamera; var t = cam.TargetPosition; var camQuat = cam.ConvertCameraAnglesToQuaternion(); var vectorC2T = new Vector3D(0, 0, cam.Distance); //this part converts cameras rotation into a toration matrix var camMatrix = new Transformation(new Vector3D(), camQuat).ToMatrix(); //then calculate the camera to target vector vectorC2T = camMatrix.Transform(vectorC2T); //this is the vector of the target var vectorT = new Vector3D(t.X, t.Y, t.Z); foreach (var p in PCSPoints) { //this is the world position of the point (i have to swap hand conventions) var wp = p.WorldPosition.SwapHandedness(); //the vector of the point var vectorP = new Vector3D(wp.X, wp.Y, wp.Z); //calculate the vector of the camera to the point var vectorC2P = vectorC2T + vectorP - vectorT; //the distance is then length of this vector var distance = vectorC2P.Length; var width = 2 * distance * Math.Tan(fieldOfViewInRadians / 2); var newVSize = width * (_viewType == ViewType.Perspective ? 0.02 : 0.005); Debug.WriteLine($"fov:{CameraAndMouseController.MainCamera.FieldOfView} d:{CameraAndMouseController.MainCamera.Distance} w:{width} newsize:{newVSize}"); p.Plane.Size = new Size(newVSize, newVSize); //the plane is on x y plane so rotate to x z plane camQuat *= new Quaternion(new Vector3D(1, 0, 0), -90); p.Rotation = camQuat; } Of course if there is an entirely different way of doing this I'm open to suggestions. RE: Keeping an object the same size in the view - abenedik - 10-14-2017 One way to mark a location in 3D space is to use 2D overlay Canvas. For this you create a Canvas over the Viewport3D object (or DXViewportView if you are using DXEngine). Then on each camera change or Viewport3D size change, you call Point3DTo2D method on the camera to get a 2D position of a 3D object. Then you can put any WPF Shape, Border or other element to the overlay canvas to the calculated 2D coordinates. There are a few samples in the Ab3d.PowerToys samples project - just do a text search for "OverlayCanvas". A drawback of this solution is that the elements on OverlayCanvas is that those elements are always on top of 3D scene and cannot be hidden behind other 3D objects. For such situations you will need to create a real 3D object. I have developed a few helper methods that can be used to get the size of 3D object based on the desired screen size and position in 3D world. Those methods will be part of the next version of Ab3d.PowerToys, but for you convenience I am publishing two of the methods here: Code: /// <summary>See remarks to see how to calculate the lookDirectionDistance for the GetPerspectiveWorldSize method. RE: Keeping an object the same size in the view - tim.rutter - 10-16-2017 Looks good, I'll give that a go this week. thanks for the help |