«Полеты» трехмерных фигур

22

Распространенный эффект, часто присутствующий в трехмерных сценах — перемещение камеры вокруг объекта. Эта задача концептуально проста для реализации в WPF: просто нужно использовать TranslateTransform для перемещения камеры.

Однако должны быть учтены два обстоятельства:

Следующий код разметки показывает анимацию, при которой камера "пролетает" через центр тора, оборачивается к его задней стороне и в конечном итоге возвращается в начальную точку:

<Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"></RowDefinition>
      <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>

    <StackPanel Orientation="Horizontal" Margin="5">
      <Button Margin="3" Padding="3">
        <Button.Content>Rotate Torus</Button.Content>
        <Button.Triggers>
          <EventTrigger RoutedEvent="Button.Click">
            <BeginStoryboard>
              <Storyboard RepeatBehavior="Forever">
                <DoubleAnimation Storyboard.TargetName="ring"
               Storyboard.TargetProperty="Transform.Children[0].Rotation.Angle" To="360" Duration="0:0:2.5"/>
                <DoubleAnimation Storyboard.TargetName="ring"
             Storyboard.TargetProperty="Transform.Children[1].Rotation.Angle" To="360" Duration="0:0:2.5"/>
              </Storyboard>
            </BeginStoryboard>
          </EventTrigger>

        </Button.Triggers>
      </Button>

      <Button  Margin="3" Padding="3">
      <Button.Content>Begin Fly-Through</Button.Content>
      <Button.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
          <BeginStoryboard>
            <Storyboard>
              <Point3DAnimationUsingKeyFrames
               Storyboard.TargetName="camera"
               Storyboard.TargetProperty="Position"
               >
                <LinearPoint3DKeyFrame Value="0,0.2,-1" KeyTime="0:0:10"/>
                <LinearPoint3DKeyFrame Value="-0.5,0.2,-1" KeyTime="0:0:15"/>
                <LinearPoint3DKeyFrame Value="-0.5,0.5,0" KeyTime="0:0:20"/>
                <LinearPoint3DKeyFrame Value="0,0,2" KeyTime="0:0:23"/>
                </Point3DAnimationUsingKeyFrames>

              <Vector3DAnimationUsingKeyFrames
               Storyboard.TargetName="camera"
               Storyboard.TargetProperty="LookDirection"
               >
                <LinearVector3DKeyFrame Value="-1,-1,-3" KeyTime="0:0:4"/>
                <LinearVector3DKeyFrame Value="-1,-1,3" KeyTime="0:0:10"/>
                <LinearVector3DKeyFrame Value="1,0,3" KeyTime="0:0:14"/>
                <LinearVector3DKeyFrame Value="0,0,-1" KeyTime="0:0:22"/>
               </Vector3DAnimationUsingKeyFrames>

              <!-- Add this to wiggle the camera. -->
              <!--    <Vector3DAnimation
                Storyboard.TargetName="camera"
               Storyboard.TargetProperty="UpDirection"
                From="0,0,-1" To="0,0.1,-1" Duration="0:0:0.5" AutoReverse="True"  RepeatBehavior="Forever"
                ></Vector3DAnimation>-->
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>

      </Button.Triggers>
    </Button>
    </StackPanel>
    
    <Viewport3D Grid.Row="1">
      <Viewport3D.Camera>
        <PerspectiveCamera x:Name="camera" FarPlaneDistance="10" LookDirection="0,0,-1" UpDirection="0,1,0" NearPlaneDistance="0.2" Position="0,0,2" FieldOfView="50" />
      </Viewport3D.Camera>

      <ModelVisual3D>
        <ModelVisual3D.Content>
          <Model3DGroup x:Name="Scene">         
            
            <AmbientLight Color="#333333" />
            <DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
            <DirectionalLight Color="#FFFFFF" Direction="0.612372,-0.5,-0.612372" />
            
            <Model3DGroup x:Name="ring">            
              <Model3DGroup.Transform>
                <Transform3DGroup>                  
                  <RotateTransform3D>
                    <RotateTransform3D.Rotation>
                      <AxisAngleRotation3D Angle="0" Axis="1 0 0.14"/>
                    </RotateTransform3D.Rotation>
                  </RotateTransform3D>
                  <RotateTransform3D>
                    <RotateTransform3D.Rotation>
                      <AxisAngleRotation3D Angle="0" Axis="0 1 0.14"/>
                    </RotateTransform3D.Rotation>
                  </RotateTransform3D>
                </Transform3DGroup>
              </Model3DGroup.Transform>
              <GeometryModel3D x:Name="Torus01OR9GR10">
                <GeometryModel3D.Material>
                  <MaterialGroup>
                    <DiffuseMaterial>
                      <DiffuseMaterial.Brush>
                        <SolidColorBrush Color="DarkBlue" />
                      </DiffuseMaterial.Brush>
                    </DiffuseMaterial>

                    <SpecularMaterial SpecularPower="24">
                      <SpecularMaterial.Brush>
                        <SolidColorBrush Color="LightBlue" Opacity="1.000000"/>
                      </SpecularMaterial.Brush>
                    </SpecularMaterial>
                    <!--EmissiveMaterial Brush="DarkRed">
                  </EmissiveMaterial>-->
                  </MaterialGroup>
                </GeometryModel3D.Material>
                <GeometryModel3D.BackMaterial>
                  <MaterialGroup>
                    <DiffuseMaterial>
                      <DiffuseMaterial.Brush>
                        <SolidColorBrush Color="#7F7F92" Opacity="1.000000"/>
                      </DiffuseMaterial.Brush>
                    </DiffuseMaterial>
                    <SpecularMaterial SpecularPower="64">
                      <SpecularMaterial.Brush>
                        <SolidColorBrush Color="#DBDBDB" Opacity="1.000000"/>
                      </SpecularMaterial.Brush>
                    </SpecularMaterial>
                  </MaterialGroup>
                </GeometryModel3D.BackMaterial>
                <GeometryModel3D.Geometry>
                  <MeshGeometry3D
                    TriangleIndices="... "
                    Normals="..."
                    Positions="..."
							/>
                </GeometryModel3D.Geometry>
              </GeometryModel3D>
            </Model3DGroup>
          </Model3DGroup>
        </ModelVisual3D.Content>
      </ModelVisual3D>
    </Viewport3D>
  </Grid>
Полет трехмерного тора

Производительность 3-D

Визуализация трехмерной сцены требует намного больше работы, чем визуализация двухмерной сцены. В случае анимации трехмерной сцены WPF пытается обновлять изменяемые части по 60 раз в секунду. В зависимости от сложности сцены, это легко может исчерпать ресурсы памяти видеокарты, что приведет к снижению частоты кадров, и анимация станет дергаться.

Существует несколько базовых приемов для повышения производительности 3-D. Вот некоторые стратегии обращения с окном обзора, позволяющие сократить накладные расходы визуализации 3-D:

Выполняя эти несложные рекомендации, можно обеспечить максимально возможную производительность при отображении трехмерной графики и максимально возможную частоту кадров для трехмерной анимации.

Пройди тесты
Лучший чат для C# программистов