четверг, 30 июня 2011 г.

Анимация и трансформация 3d модели в WPF


В прошлой статье мы с вами создали 3d модель кирпича. В этой статье мы научимся его вращать. Но сначала как всегда немного теории.

Трехмерную модель можно поворачивать несколькими способами. При обычном преобразовании поворота указывается ось и угол поворота вокруг этой оси. Класс RotateTransform3D позволяет определить Rotation3D со свойством Rotation. Затем для определения преобразования следует указать свойства AxisAngle в Rotation3D (в данном случае — AxisAngleRotation3D). В следующих примерах модель поворачивается на 60 градусов вокруг оси Y.

Обратите внимание: Windows Presentation Foundation (WPF) является правовинтовой системой, поэтому указание положительного значения угла поворота приведет к повороту против часовой стрелки вокруг оси.

Осе-угловой поворот предполагает поворот относительно начала координат, если в RotateTransform3D не указаны значения свойств CenterX, CenterY и CenterZ. Как и при масштабировании, следует помнить, что при повороте преобразуется все координатное пространство модели целиком. Если модель была создана не от начала координат или была преобразована ранее, то поворот может быть произведен относительно начала координат, а не относительно местоположения модели.

Чтобы повернуть модель «на месте», следует указать фактический центр модели в качестве центра поворота. Геометрия обычно моделируется от начала координат, поэтому для получения ожидаемого результата от набора преобразований необходимо вначале изменить размер модели (т.е. отмасштабировать), задать ее направление (повернуть), а затем перенести ее в нужное место (преобразовать).

Теперь давайте поговорим об анимации в 3d.

Трехмерная реализация Windows Presentation Foundation (WPF) участвует в той же системе анимации и времени, что и двумерная графика. Другими словами, для анимации трехмерной сцены необходимо анимировать свойства ее моделей. Можно непосредственно анимировать свойства примитивов, но обычно проще анимировать преобразования, изменяющие позицию или внешний вид моделей. Поскольку преобразования можно применить и к объектам Model3DGroup, и к отдельным моделям, то возможно применение одного набора анимаций к дочернему элементу Model3DGroup, а другого набора — к группе дочерних объектов.
Для анимации объекта в приложении Windows Presentation Foundation (WPF) создайте временную шкалу, определите анимацию (которая изменяет значение некоторого свойства во времени) и укажите свойство, к которому применяется анимация. Это свойство должно быть свойством FrameworkElement. Поскольку все объекты в трехмерной сцене являются дочерними элементами Viewport, то свойства, требуемые для анимации сцены, являются свойствами свойств Viewport3D. Важно правильно указать путь к свойству для анимации, так как синтаксис может быть подробным.

Предположим, требуется повернуть объект на месте, а также применить качательное движение, чтобы лучше показать объект. Можно применить к модели класс RotateTransform3D и анимировать ее ось вращения от одного вектора к другому. В следующем примере показано применение Vector3DAnimation к свойству Axis преобразования элемента Rotation3D, при условии, что RotateTransform3D будет одним из нескольких преобразований, применяемых к модели с TransformGroup.

Поскольку камеры также являются моделями, их свойства также могут быть преобразованы. Хотя безусловно можно изменить внешний вид сцены, преобразуя расстояния расположения или плоскости камеры, в результате преобразования проекции всей сцены, обратите внимание на то, что множество эффектов, можно достичь таким образом не смысл столько "visual" в средстве просмотра как преобразования расположение или расположение моделей в сцене.
Теперь давайте рассмотрим наш пример. В прошлой статье я описывала как создать 3d объект и мы с вам создали кирпич. Сейчас попробуем анимировать его, используя теорию, которую только что изучили.

Перейдём к практике.

Для повората нашей модели мы будем использовать элемент  RotateTransform3D который задаёт центр вращения и угол поворота. Также создадим анимацию которая  непрерывно изменяет свойство Angle элементе AxisAngleRotation3D. Чтобы выполнить вращение  готовой модели, запустим анимацию с помощью тригера событий.

Обратите внимание на выделенный код.
<Window x:Class="_3DDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="3D Demo" Height="240" Width="500">
    <Window.Resources>


        <VisualBrush x:Key="mainCover">
            <VisualBrush.Visual>
                <Border Background="Yellow" BorderThickness="2">
                    <Image Source="/3DDemo;component/3201019298_b2099760e0_m.jpg" />
                </Border>
            </VisualBrush.Visual>
        </VisualBrush>

        <SolidColorBrush x:Key="top" Color="BurlyWood" />
        <SolidColorBrush x:Key="pages" Color="BurlyWood" />
        <SolidColorBrush x:Key="back" Color="BurlyWood" />
        <SolidColorBrush x:Key="side" Color="BurlyWood" />
    </Window.Resources>
    <Viewport3D>
        <Viewport3D.Camera>
            <PerspectiveCamera Position="0,0,25" LookDirection="15,6,-50" />
        </Viewport3D.Camera>

        <ModelVisual3D>
            <ModelVisual3D.Content>
                <!--<AmbientLight Color="White" />-->
                <SpotLight Color="White" InnerConeAngle="20" OuterConeAngle="60" Direction="15,6,-50" Position="0,0,25" />
             </ModelVisual3D.Content>
        </ModelVisual3D>

        <ModelVisual3D>
            <ModelVisual3D.Content>
                <Model3DGroup>

                    <!-- front -->
                    <GeometryModel3D>
                        <GeometryModel3D.Geometry>
                            <MeshGeometry3D
                                Positions="0 0 0, 10 0 0, 0 16 0, 10 16 0, 10 0 0"
                                TriangleIndices="0, 1, 2, 2, 4, 3"
                                TextureCoordinates="0 1, 1 1, 0 0, 1 0, 1 1"
                                />
                        </GeometryModel3D.Geometry>

                        <GeometryModel3D.Material>
                            <MaterialGroup>
                                <SpecularMaterial SpecularPower="99">
                                    <SpecularMaterial.Brush>
                                        <SolidColorBrush>Yellow</SolidColorBrush>
                                    </SpecularMaterial.Brush>
                                </SpecularMaterial>
                                <DiffuseMaterial Brush="{StaticResource mainCover}" />
                            </MaterialGroup>

                        </GeometryModel3D.Material>
                    </GeometryModel3D>



              

                    <!-- left -->
                    <GeometryModel3D>
                        <GeometryModel3D.Geometry>
                            <MeshGeometry3D
                            Positions="0 0 -4, 0 0 0, 0 14 -4, 0 14 0, 0 0 0"
                            TriangleIndices="0, 1, 2, 2, 4, 3" />
                        </GeometryModel3D.Geometry>

                        <GeometryModel3D.Material>
                            <MaterialGroup>
                                <DiffuseMaterial Brush="{StaticResource side}" />
                            </MaterialGroup>
                        </GeometryModel3D.Material>
                        <GeometryModel3D.BackMaterial>
                            <DiffuseMaterial Color="Blue" />
                        </GeometryModel3D.BackMaterial>
                    </GeometryModel3D>

                    <GeometryModel3D>
                        <GeometryModel3D.Geometry>
                            <MeshGeometry3D
                            Positions="0 14 -4, 0 14 0, 0 16 -4, 0 16 0, 0 14 0"
                            TriangleIndices="0, 1, 2, 2, 4, 3" />
                        </GeometryModel3D.Geometry>

                        <GeometryModel3D.Material>
                            <MaterialGroup>
                                <DiffuseMaterial Brush="{StaticResource top}" />
                            </MaterialGroup>
                        </GeometryModel3D.Material>
                        <GeometryModel3D.BackMaterial>
                            <DiffuseMaterial Color="Blue" />
                        </GeometryModel3D.BackMaterial>
                    </GeometryModel3D>

                    <!-- right  -->
                    <GeometryModel3D>
                        <GeometryModel3D.Geometry>
                            <MeshGeometry3D
                            Positions="10 0 0, 10 0 -4, 10 16 0, 10 16 -4, 10 0 -4"
                            TriangleIndices="0, 1, 2, 2, 4, 3" />
                        </GeometryModel3D.Geometry>

                        <GeometryModel3D.Material>
                            <MaterialGroup>
                                <DiffuseMaterial Brush="{StaticResource top}" />
                            </MaterialGroup>
                        </GeometryModel3D.Material>
                        <GeometryModel3D.BackMaterial>
                            <DiffuseMaterial Color="Blue" />
                        </GeometryModel3D.BackMaterial>
                    </GeometryModel3D>


                    <!-- top side -->
                    <GeometryModel3D>
                        <GeometryModel3D.Geometry>
                            <MeshGeometry3D
                            Positions="0 16 0, 0 16 -4, 10 16 0, 10 16 -4, 0 16 -4"
                            TriangleIndices="0, 2, 1, 2, 3, 4"
                                TextureCoordinates="0 1, 0 0, 1 1, 1 0, 0 0"
                                />
                        </GeometryModel3D.Geometry>

                        <GeometryModel3D.Material>
                            <MaterialGroup>
                                <DiffuseMaterial Brush="{StaticResource pages}" />
                            </MaterialGroup>

                        </GeometryModel3D.Material>
                        <GeometryModel3D.BackMaterial>
                            <DiffuseMaterial Color="Blue" />
                        </GeometryModel3D.BackMaterial>
                    </GeometryModel3D>

                    <!-- bottom -->
                    <GeometryModel3D>
                        <GeometryModel3D.Geometry>
                            <MeshGeometry3D
                            Positions="0 0 0, 0 0 -4, 10 0 0, 10 0 -4, 0 0 -4"
                            TriangleIndices="0, 1, 2, 2, 4, 3"
                                TextureCoordinates="0 1, 0 0, 1 1, 1 0, 0 0"
                                />
                        </GeometryModel3D.Geometry>

                        <GeometryModel3D.Material>
                            <DiffuseMaterial Brush="{StaticResource pages}" />
                        </GeometryModel3D.Material>
                        <GeometryModel3D.BackMaterial>
                            <DiffuseMaterial Color="Blue" />
                        </GeometryModel3D.BackMaterial>
                    </GeometryModel3D>

                    <!-- back -->
                    <GeometryModel3D>
                        <GeometryModel3D.Geometry>
                            <MeshGeometry3D
                            Positions="0 0 -4, 10 0 -4, 0 16 -4, 10 16 -4, 10 0 -4"
                            TriangleIndices="0, 2, 1, 2, 3, 4" />
                        </GeometryModel3D.Geometry>

                        <GeometryModel3D.Material>
                            <MaterialGroup>
                                <DiffuseMaterial Brush="{StaticResource back}" />
                            </MaterialGroup>
                        </GeometryModel3D.Material>
                        <GeometryModel3D.BackMaterial>
                            <DiffuseMaterial Color="Blue" />
                        </GeometryModel3D.BackMaterial>
                    </GeometryModel3D>


                    <Model3DGroup.Transform>
                        <RotateTransform3D CenterX="0" CenterY="0" CenterZ="0">
                            <RotateTransform3D.Rotation>
                                <AxisAngleRotation3D x:Name="angle" Axis="-1,-1,-1" Angle="70" />
                            </RotateTransform3D.Rotation>

                        </RotateTransform3D>
                    </Model3DGroup.Transform>

                </Model3DGroup>

            </ModelVisual3D.Content>
        </ModelVisual3D>
       
    </Viewport3D>
    <Window.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation From="0" To="360" Duration="00:00:10" Storyboard.TargetName="angle" Storyboard.TargetProperty="Angle" RepeatBehavior="Forever" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Window.Triggers>
</Window>


В результате у нас получился вращающийся кирпич. J






Комментариев нет:

Отправить комментарий