WPF 3D:装修的整个图片查看与PerspectiveCamera [英] WPF 3D: Fitting entire image to view with PerspectiveCamera

查看:1124
本文介绍了WPF 3D:装修的整个图片查看与PerspectiveCamera的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下的形象,我需要在显示 Viewport3D

I have the following image which I need to display in a Viewport3D:

图片的纹理的中心在(0,0)和其角坐标(-1,-1,0),(1,-1,0),( - 1,1,0),(1, 1,0)。

The image texture is centered at (0,0) and its corner coordinates are (-1,-1,0), (1,-1,0),(-1,1,0),(1,1,0).

由于我使用的 PerspectiveCamera 与视图中的固定场,我必须计算足够的距离,把整个图像眼帘:

Since I am using PerspectiveCamera with a fixed field of view, I have to compute sufficient distance to put entire image into view:

图像重新以蓝线psented $ P $,是W 是图像的宽度(W = 2)。

Image is represented by a blue line, w is image width (w=2).

相机位置为(0,0,D),从而生成一个三角形:

Camera position is (0,0,d) and hence a triangle is formed:

tan(fov/2) = (w/2) / d

d = (w/2) / tan(fov/2)

现在我放在一起的XAML code为3D模型和code-behing计算相机间的距离:

Now I put together XAML code for the 3D model and code-behing for computing camera distance:

XAML

<Window x:Class="Render3DTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="256" Width="256" Loaded="Window_Loaded">
    <Grid>

        <Viewport3D Name="viewport">

            <Viewport3D.Camera>
                <PerspectiveCamera Position="0,0,1" LookDirection="0,0,-1" FieldOfView="90" />
            </Viewport3D.Camera>

            <ModelVisual3D>
                <ModelVisual3D.Content>
                    <AmbientLight/>
                </ModelVisual3D.Content>
            </ModelVisual3D>

            <ModelVisual3D>
                <ModelVisual3D.Content>
                    <GeometryModel3D>
                        <GeometryModel3D.Material>
                            <DiffuseMaterial>
                                <DiffuseMaterial.Brush>
                                    <ImageBrush ImageSource="image.jpg"/>
                                </DiffuseMaterial.Brush>
                            </DiffuseMaterial>
                        </GeometryModel3D.Material>
                        <GeometryModel3D.Geometry>
                            <MeshGeometry3D Positions="-1,1,0 -1,-1,0 1,-1,0 1,1,0" TextureCoordinates="0,0 0,1 1,1 1,0" TriangleIndices="0 1 2, 0 2 3" />
                        </GeometryModel3D.Geometry>
                    </GeometryModel3D>
                </ModelVisual3D.Content>
            </ModelVisual3D>

        </Viewport3D>

    </Grid>
</Window>

code-背后

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    PerspectiveCamera camera = (PerspectiveCamera)this.viewport.Camera;

    double d = (1.0 / Math.Tan(camera.FieldOfView / 2.0));

    camera.Position = new Point3D(0.0, 0.0, d);
}

不过, Viewport3D 不显示整幅图像:

有一些其他的因素发挥的作用?我不想用我的计算任何调整或捏造的。

Is there some other factor playing role? I don't want to use any tweaks or fudge factors in my computation.

请注意,调整窗口的大小不会对观水平范围的影响,因为这是由相机视场角和距离的影响,所以这个问题没有什么关系控制尺寸 - 这涉及到WPF项目如何分从3D到2D。

Please note that resizing the window does not have effect on horizontal range of view as this is determined by camera FOV and its distance, so the problem does not have anything to do with control size - it is related to how WPF projects points from 3D to 2D.

推荐答案

我想出了一个可能的解决方案利用了透视相机的线性度。

I figured out one possible solution making use of the linearity of the perspective camera.

  1. 设置相机已知距离(即1.0)
  2. 使用 Visual3D.TransformToAncestor 模型
  3. 的计算二维边框
  4. 在计算比例因子(边界框尺寸/视口大小)
  5. 的比例因子乘以相机间的距离
  1. Set camera to a known distance (i.e. 1.0)
  2. Compute 2D bounding box of the model using Visual3D.TransformToAncestor
  3. Compute scale factor (bounding box size / viewport size)
  4. Multiply camera distance by the scale factor

在换句话说,如果照相机是两次进一步,图像小两倍...

In other words, if the camera is twice further, the image is twice smaller...

PerspectiveCamera camera = (PerspectiveCamera)this.viewport.Camera;

// set camera to a known distance
camera.Position = new Point3D(0.0, 0.0, 100.0);

Point3D[] points3D = new[]
{
    new Point3D(-1.0, -1.0, 0.0),
    new Point3D(1.0, -1.0, 0.0),
    new Point3D(-1.0, 1.0, 0.0),
    new Point3D(1.0, 1.0, 0.0)
};

double minX = Double.MaxValue;
double maxX = Double.MinValue;
double minY = Double.MaxValue;
double maxY = Double.MinValue;

GeneralTransform3DTo2D transform = this.viewport.Children[1].TransformToAncestor(this.viewport);

foreach (var point3D in points3D)
{
    Point point2D = transform.Transform(point3D);

    minX = Math.Min(minX, point2D.X);
    maxX = Math.Max(maxX, point2D.X);

    minY = Math.Min(minY, point2D.Y);
    maxY = Math.Max(maxY, point2D.Y);
}

Size currentSize = new Size(maxX - minX, maxY - minY);
Size desiredSize = new Size(this.viewport.ActualWidth, this.viewport.ActualHeight);

double scaleFactor = Math.Max(
    currentSize.Width / desiredSize.Width,
    currentSize.Height / desiredSize.Height);

camera.Position = new Point3D(0.0, 0.0, 100.0 * scaleFactor); // the known distance of 100.0 is multiplied by scaleFactor

这篇关于WPF 3D:装修的整个图片查看与PerspectiveCamera的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆