简体   繁体   中英

c# WPF 3D hitTest error: singular MatrixCamera not supported

this is the code I use to do the hitTest:

RayHitTestResult hit = VisualTreeHelper.HitTest(
      App.MainWin.Viewport, location) as RayHitTestResult;

This code works when the camera width is small (ie objects are big). When I zoom out the camera (ie objects become smaller) to certain point, then when I click on the viewport, it shows an error on the above code, and the error details is like this:

System.NotSupportedException was unhandled : Hit testing with a singular MatrixCamera is not supported.

I googled and found nobody having this error. Any idea how to solve it? Thanks!

The code I used to create / update the MatrixCamera: (They are inspired by the examples in the book "3D Programming for Windows: Three-Dimensional Graphics Programming for the Windows Presentation Foundation" by Charles Petzold, Chapter 7)

    //create a new camera, initialize it and attach it to the viewport.
    public void initCamera(Point3D position, Point3D AimPoint, 
                           Vector3D upDirection, double farDistance, 
                           double nearDistance, double Width)
    {
        this._Camera = new MatrixCamera();

        this.CameraAimPoint = (Vector3D)AimPoint;

        //check and adjust the camera depth if needed
        this.CameraZAxis = Point3D.Subtract(position, AimPoint); 

        this.CameraDepth = CameraZAxis.Length;

        this.CameraZAxis.Normalize();
        this.CameraPosition = this.CameraAimPoint + (this.CameraZAxis *  this.CameraDepth);

        this.CameraFarDistance = farDistance;
        this.CameraNearDistance = nearDistance;
        this.CameraWidth = Width;

        this.CameraXAxis = Vector3D.CrossProduct(upDirection, this.CameraZAxis);
        this.CameraXAxis.Normalize();

        this.CameraYAxis = Vector3D.CrossProduct(this.CameraZAxis, this.CameraXAxis);

        this._CameraViewMatrix = new Matrix3D();
        this._CameraViewMatrix.M14 = 0;
        this._CameraViewMatrix.M24 = 0;
        this._CameraViewMatrix.M34 = 0;
        this._CameraViewMatrix.M44 = 1;

        this.updateViewMatrix();

        this._CameraProjectMatrix = new Matrix3D();
        this._CameraProjectMatrix.M14 = 0;
        this._CameraProjectMatrix.M24 = 0;
        this._CameraProjectMatrix.M34 = 0;
        this._CameraProjectMatrix.M44 = 1;

        this.updateProjectionMatrix();

        this._Viewport.Camera = this._Camera;

    }

    private void updateViewMatrix(bool axisChanged=true)
    {
        if (axisChanged==true)
        {
            this._CameraViewMatrix.M11 = this.CameraXAxis.X;
            this._CameraViewMatrix.M12 = this.CameraYAxis.X;
            this._CameraViewMatrix.M13 = this.CameraZAxis.X;

            this._CameraViewMatrix.M21 = this.CameraXAxis.Y;
            this._CameraViewMatrix.M22 = this.CameraYAxis.Y;
            this._CameraViewMatrix.M23 = this.CameraZAxis.Y;

            this._CameraViewMatrix.M31 = this.CameraXAxis.Z;
            this._CameraViewMatrix.M32 = this.CameraYAxis.Z;
            this._CameraViewMatrix.M33 = this.CameraZAxis.Z;
        }

        this._CameraViewMatrix.OffsetX = -Vector3D.DotProduct(this.CameraXAxis, this.CameraPosition);
        this._CameraViewMatrix.OffsetY = -Vector3D.DotProduct(this.CameraYAxis, this.CameraPosition);
        this._CameraViewMatrix.OffsetZ = -Vector3D.DotProduct(this.CameraZAxis, this.CameraPosition);

        this._Camera.ViewMatrix = this._CameraViewMatrix;
        this._3DTo2DTransformMatrixIsDefined = false;

        AfterDraw();
    }

    //
    private void updateProjectionMatrix() {
        double ScaleX = 2 / CameraWidth;
        double ScaleY = _Viewport.ActualWidth / _Viewport.ActualHeight * ScaleX;
        double ScaleZ = 1 / (CameraNearDistance - CameraFarDistance);
        double zOffset = CameraNearDistance * ScaleZ;

        _CameraProjectMatrix.M11 = ScaleX;
        _CameraProjectMatrix.M22 = ScaleY;
        _CameraProjectMatrix.M33 = ScaleZ;
        _CameraProjectMatrix.OffsetZ = zOffset;

        _Camera.ProjectionMatrix = _CameraProjectMatrix;
        _3DTo2DTransformMatrixIsDefined = false;

        _PixelToWorldUnit = CameraWidth / _Viewport.ActualWidth;

        AfterDraw();

    }

The code to perform camera zooming:

    private void _cameraZoomToScale(double width)
    {
        if (width< 1) width = 1;
        this.CameraWidth = width;
        updateProjectionMatrix();

    }

It seems pretty clear that you are zooming further than the MatrixCamera supports. Figure out at what zoom level this exception occurs and prevent the user from getting that far. It looks like you might already be trying to do that already with if (scale < 1) scale = 1; but scale doesn't seem to be used elsewhere in the posted code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM