WPF 3D - 将 ModelVisual3D 放入相机的视野中?

发布于 2024-07-15 18:35:39 字数 1470 浏览 6 评论 0原文

我有一个长方体,其尺寸是从 XML 导入的,因此我需要确保无论模型大小如何,相机始终可以看到所有模型。 这是出于预览目的。 为了清楚起见,我可能会在顶部显示一个标题,显示比例。

我想我需要一些函数来告诉我 ModelVisual3D 是否适合相机的 FieldOfView 或 ViewPort3D 本身的边界。

到目前为止,当维度属性更改定义如下时,我有静态回调(维度属性是 DependencyProperty)。 目前还很粗糙,但你明白我正在考虑的想法。 注释掉的部分大致显示了我正在寻找的逻辑类型

    private static void OnCubeDimensionsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (!valueSemaphore)
        {
            //while(mainModel.WillClip(mainCamera))
            //{
            //     mainCamera.FieldOfView--;
            //}

            valueSemaphore = true;
            double propertyValue = 0.0;
            Product3D p = d as Product3D;

            switch (e.Property.Name)
            {
                case "CubeHeight":
                    propertyValue = (double.Parse(e.NewValue.ToString()) / 100) * 8;
                    p.CubeHeight = propertyValue;
                    break;
                case "CubeWidth":
                    propertyValue = (double.Parse(e.NewValue.ToString()) / 100) * 5.3;
                    p.CubeWidth = propertyValue;
                    break;
                case "CubeDepth":
                    propertyValue = (double.Parse(e.NewValue.ToString()) / 100) * 2.6;
                    p.CubeDepth = propertyValue;
                    break;
            }
            valueSemaphore = false;
        }
    }

如果有人知道注释掉的部分应该放在哪里,我将永远感激不已。
提前致谢。

I have a cuboid who's dimensions are imported from XML so i need to be sure that no matter what the size of the model, the camera can always see all of it. This is for preview purposes. I'll likely render a caption over the top showing the scale for clarity.

I think i need some function which will tell me whether the ModelVisual3D fits inside the bounds of the FieldOfView of the camera or maybe the ViewPort3D itself.

So far i have the static callback (the dimension properties are DependencyPropertys) when dimensions properties change define as below. It's pretty crude at the moment but you get the idea I'm looking at. The commented out section shows roughly what kind of logic I'm looking for

    private static void OnCubeDimensionsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (!valueSemaphore)
        {
            //while(mainModel.WillClip(mainCamera))
            //{
            //     mainCamera.FieldOfView--;
            //}

            valueSemaphore = true;
            double propertyValue = 0.0;
            Product3D p = d as Product3D;

            switch (e.Property.Name)
            {
                case "CubeHeight":
                    propertyValue = (double.Parse(e.NewValue.ToString()) / 100) * 8;
                    p.CubeHeight = propertyValue;
                    break;
                case "CubeWidth":
                    propertyValue = (double.Parse(e.NewValue.ToString()) / 100) * 5.3;
                    p.CubeWidth = propertyValue;
                    break;
                case "CubeDepth":
                    propertyValue = (double.Parse(e.NewValue.ToString()) / 100) * 2.6;
                    p.CubeDepth = propertyValue;
                    break;
            }
            valueSemaphore = false;
        }
    }

If anyone knows what should go where the commented-out section is I'd be eternally grateful.
Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

提赋 2024-07-22 18:35:39

您需要掌握的是立方体在视图平面上的二维投影的范围。 然后,您可以对最小和最大 X & 进行简单检查。 Y 值可查看整个立方体是否可见。

在范围内添加容差因子将解决任何舍入误差。

我从此处复制了看似相关的代码部分。 然后您可以相应地设置视口的大小。

public static Rect Get2DBoundingBox(ModelVisual3D mv3d)
{
    bool bOK;

    Matrix3D m = MathUtils.TryWorldToViewportTransform(vpv, out bOK);

    bool bFirst = true;    
    Rect r = new Rect();

    if (mv3d.Content is GeometryModel3D)
    {
        GeometryModel3D gm3d = (GeometryModel3D) mv3d.Content;

        if (gm3d.Geometry is MeshGeometry3D)
        {
            MeshGeometry3D mg3d = (MeshGeometry3D)gm3d.Geometry;

            foreach (Point3D p3d in mg3d.Positions)
            {
                Point3D pb = m.Transform(p3d);
                Point p2d = new Point(pb.X, pb.Y);
                if (bFirst)
                {
                    r = new Rect(p2d, new Size(1, 1));
                    bFirst = false;
                }
                else
                {
                    r.Union(p2d);
                }
            }
        }
    }

What you need to get hold of is the extent of the 2D projection of the cube on the view plane. You can then do a simple check on the min and max X & Y values to see whether the whole of the cube is visible.

Adding a tolerance factor to the extent will take care of any rounding errors.

I've copied what looks to be the relevant section of code from here. You can then set the size of the viewport accordingly.

public static Rect Get2DBoundingBox(ModelVisual3D mv3d)
{
    bool bOK;

    Matrix3D m = MathUtils.TryWorldToViewportTransform(vpv, out bOK);

    bool bFirst = true;    
    Rect r = new Rect();

    if (mv3d.Content is GeometryModel3D)
    {
        GeometryModel3D gm3d = (GeometryModel3D) mv3d.Content;

        if (gm3d.Geometry is MeshGeometry3D)
        {
            MeshGeometry3D mg3d = (MeshGeometry3D)gm3d.Geometry;

            foreach (Point3D p3d in mg3d.Positions)
            {
                Point3D pb = m.Transform(p3d);
                Point p2d = new Point(pb.X, pb.Y);
                if (bFirst)
                {
                    r = new Rect(p2d, new Size(1, 1));
                    bFirst = false;
                }
                else
                {
                    r.Union(p2d);
                }
            }
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文