Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find out if a certain Point3D is inside the camera view bounds?

Tags:

c#

.net

wpf

directx

3d

So that's it. I have a certain Point3D. I have a camera. I know the view angle of the camera, which is 45 degrees; I know camera position and LookDirection vector. Now I want some way to find out whether the point will be visible to the camera or not.

So p1 Should be visible, p2 should not Thanks for those who have answered and commented, but:

  1. This is not a straightforward problem for me. This may seem a simple thing, but I didn't find any special method or helper class to solve the problem. I have tried solving it myself, in a purely math way, but the solution is unstable and works unpredictable:

    bool isPointInCameraView(Point3D P, Point3D CP, Vector3D LD, double CameraAngle) {
        //first calculate Distance to the plane formed by normal vector LD and point P on it
        var D = -LD.X*P.X-LD.Y*P.Y-LD.Z*P.Z; // -AXb-BYb-CZb
        //L is the distance to the plane.
        double L = Math.Abs( (LD.X * CP.X + LD.Y * CP.Y + LD.Z * CP.Z + D)) / Math.Sqrt(LD.X * LD.X +             LD.Y * LD.Y+LD.Z * LD.Z);            
        var BL = L * Math.Tan(CameraAngle); //length of bound part
        var PL = Math.Sqrt(((new Vector3D(P.X - CP.X, P.Y - CP.Y, P.Z -   CP.Z)).LengthSquared - L * L)); // length of point part
        //test if point is out of bounds!
        return PL <= BL;
    }
    
  2. I do know about Helix3D and I am using it. My Viewport and Camera are from helix framework.

I think that it will be easier to understand the problem if I explain the reason why I need this kind of test. I am building a geoscience visualisation application, and I need to be able to zoom deep into the texture to see details. The problem was that I couldn't use too large textures, as they would take up too much memory, and take too long to draw. I decided then to divide my plane into several subrectangles, each of which should be handled separatedly. So the idea is that when the user zooms into certain part of the plane, I would render that part only. It worked ok, except the code still repainted textures for those subrectangles that were invisible to the camera. Now I want to optimize this. I tried searching for any special function that would let me do it, but no success. So for now the solution is only mathematical and it's unstable, it's working wrong. That's why I asked this question here.

like image 933
Timur Nuriyasov Avatar asked May 14 '12 08:05

Timur Nuriyasov


1 Answers

Nice picture!

I think it's not so easy if you don't have the Camera in a Viewport3D. You'd need to compose through the Visual3D transformations with the Camera transformation.

Easiest would be to put the stuff into a Viewport3D. Then your question is similar to this one: Projecting a 3D point to a 2D screen coordinate and this one: 3D Projection information.

Note that some of the answers were written before .NET 3.5, which added the helper function Visual3D.TransformToAncestor, which is probably what you need. More info about TransformToAncestor here: http://blogs.msdn.com/b/wpf3d/archive/2009/05/13/transforming-bounds.aspx.

And if you're doing anything with WPF 3D, you need to know about the awesome Helix Toolkit, which is a replacement for 3DTools, containing view controls and various helpers, and is actively being worked on.

like image 86
Govert Avatar answered Oct 03 '22 14:10

Govert