Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I calculate WPF all camera setting dynamically in the code?

Tags:

c#

.net

wpf

I have Viewport3D in the Window. it will change the size when the window size changed.

<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).

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 ?

I've already tried this, but can't calculate correctly: WPF 3D: Fitting entire image to view with PerspectiveCamera

like image 656
qakmak Avatar asked Jul 06 '16 09:07

qakmak


2 Answers

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>
like image 97
Markus Hütter Avatar answered Nov 17 '22 16:11

Markus Hütter


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.

like image 21
qakmak Avatar answered Nov 17 '22 17:11

qakmak