I have Viewport3D in the Window. it will change the size when the window size changed.
窗口中有Viewport3D。当窗口大小改变时,它会改变大小。
<Window>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition/>
<Grid.RowDefinitions>
<Label Grid.Row="0" Content="top label"/>
<Viewport3D Grid.Row="1" x:Name="vp3D" >
<Viewport3D.Camera >
<PerspectiveCamera x:Name="pCamera" LookDirection="0 0 -1" UpDirection="0 1 0" />
</Viewport3D.Camera>
<Viewport2DVisual3D x:Name="v2dv3d">
<Viewport2DVisual3D.Geometry>
<MeshGeometry3D x:Name="mg3d" TextureCoordinates="0,0 0,1 1,1 1,0" TriangleIndices="0 1 2 0 2 3"/>
</Viewport2DVisual3D.Geometry>
<Viewport2DVisual3D.Material>
<DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial="True" Brush="White"/>
</Viewport2DVisual3D.Material>
<Image Height="{Binding ElementName=vp3D, Path=ActualHeight}" Width="{Binding ElementName=vp3D, Path=ActualWidth}" Stretch="Fill"/>
</Viewport2DVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFFFF" Direction="0,0,-1"/>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D>
</Grid>
</Window
Now I want the image show on like it's the original 2d window(look like nothing changed, but actually the image is 3d).
现在我希望图像显示的是原来的2d窗口(看起来没什么变化,但实际上图像是3d的)。
But problem is If I want it looking same as the same as WPF original look at, I must change some Camera settings, like PerspectiveCamera.Position
or MeshGeometry3D.Position
. because the Viewport3D
will change the size dynamically when the window change size, I must dynamically calculate the Viewport3D
settings. Is there anyway to do ?
但问题是,如果我想让它看起来和WPF最初的样子一样,我必须改变一些相机设置,比如透视照相机。位置或MeshGeometry3D.Position。因为Viewport3D会在窗口改变大小时动态地改变大小,所以我必须动态地计算Viewport3D设置。有什么可做的吗?
I've already tried this, but can't calculate correctly: WPF 3D: Fitting entire image to view with PerspectiveCamera
我已经试过了,但是不能正确计算:WPF 3D:用perspective tivecamera拟合整个图像
2 个解决方案
#1
4
I'm not sure if that is what you want, but have you tried this?
我不确定这是不是你想要的,但是你试过了吗?
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="top label"/>
<Image HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="1" Stretch="Fill"/>
<Viewport3D Grid.Row="1" x:Name="vp3D">
<Viewport3D.Camera >
<PerspectiveCamera x:Name="pCamera" Position="0,0,1" LookDirection="0,0,-1" />
</Viewport3D.Camera>
<Viewport2DVisual3D x:Name="v2dv3d">
<Viewport2DVisual3D.Geometry>
<MeshGeometry3D x:Name="mg3d" 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"/>
</Viewport2DVisual3D.Geometry>
<Viewport2DVisual3D.Material>
<DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial="True" Brush="White"/>
</Viewport2DVisual3D.Material>
</Viewport2DVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFFFF" Direction="0,0,-1"/>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D>
</Grid>
#2
1
I finish it by myself.
我自己完成的。
// get the Viewport3D size first, If you want to use .ActualWidth or .ActualHeight property get it, make sure your application loaded finish, otherwise it will return 0.
double height = ; // get the Viewport3D height or calculate the height first
double width = ; // get the Viewport3D width or calculate the width first
mg3d.Positions.Clear();
mg3d.Positions.Add(new Point3D(-width, height, 0.0));
mg3d.Positions.Add(new Point3D(-width, -height, 0.0));
mg3d.Positions.Add(new Point3D(width, -height, 0.0));
mg3d.Positions.Add(new Point3D(width, height, 0.0));
double fieldOfViewInRadians = pCamera.FieldOfView * (Math.PI / 180.0);
var z = (width) / Math.Tan(0.5 * fieldOfViewInRadians);
pCamera.Position = new Point3D(0.0, 0.0, z);
You also need to make sure calculate it again if your window size changed. After that, you could do any 3d animation which you want.
您还需要确保在窗口大小发生变化时再次计算它。之后,你可以做任何你想要的3d动画。
#1
4
I'm not sure if that is what you want, but have you tried this?
我不确定这是不是你想要的,但是你试过了吗?
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="top label"/>
<Image HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="1" Stretch="Fill"/>
<Viewport3D Grid.Row="1" x:Name="vp3D">
<Viewport3D.Camera >
<PerspectiveCamera x:Name="pCamera" Position="0,0,1" LookDirection="0,0,-1" />
</Viewport3D.Camera>
<Viewport2DVisual3D x:Name="v2dv3d">
<Viewport2DVisual3D.Geometry>
<MeshGeometry3D x:Name="mg3d" 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"/>
</Viewport2DVisual3D.Geometry>
<Viewport2DVisual3D.Material>
<DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial="True" Brush="White"/>
</Viewport2DVisual3D.Material>
</Viewport2DVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFFFF" Direction="0,0,-1"/>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D>
</Grid>
#2
1
I finish it by myself.
我自己完成的。
// get the Viewport3D size first, If you want to use .ActualWidth or .ActualHeight property get it, make sure your application loaded finish, otherwise it will return 0.
double height = ; // get the Viewport3D height or calculate the height first
double width = ; // get the Viewport3D width or calculate the width first
mg3d.Positions.Clear();
mg3d.Positions.Add(new Point3D(-width, height, 0.0));
mg3d.Positions.Add(new Point3D(-width, -height, 0.0));
mg3d.Positions.Add(new Point3D(width, -height, 0.0));
mg3d.Positions.Add(new Point3D(width, height, 0.0));
double fieldOfViewInRadians = pCamera.FieldOfView * (Math.PI / 180.0);
var z = (width) / Math.Tan(0.5 * fieldOfViewInRadians);
pCamera.Position = new Point3D(0.0, 0.0, z);
You also need to make sure calculate it again if your window size changed. After that, you could do any 3d animation which you want.
您还需要确保在窗口大小发生变化时再次计算它。之后,你可以做任何你想要的3d动画。