当前位置:网站首页 / WPF / 正文

[Aaronyang] 写给自己的WPF4.5 笔记23 [3d交互与动画 4/4]

时间:2015年03月17日 | 作者 : aaronyang | 分类 : WPF | 浏览: 4067次 | 评论 0

效果图预览:

1. 3d中的命中测试

我新建了一个空的窗口,用zam做了一个长方体,深度很小。然后导出xaml

<Viewport3D x:Name="ZAM3DViewport3D" ClipToBounds="true" Width="400" Height="300" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/interactivedesigner/2006" xmlns:c="http://schemas.openxmlformats.org/markup-compatibility/2006" c:Ignorable="d">
    <Viewport3D.Resources>
        <ResourceDictionary>
            <MaterialGroup x:Key="ER___Flat_06MR1" >
                <DiffuseMaterial>
                    <DiffuseMaterial.Brush>
                        <SolidColorBrush Color="#999999" Opacity="1.000000"/>
                    </DiffuseMaterial.Brush>
                </DiffuseMaterial>
            </MaterialGroup>
            <Transform3DGroup x:Key="SceneTR7" >
                <TranslateTransform3D OffsetX="0" OffsetY="0" OffsetZ="0"/>
                <ScaleTransform3D ScaleX="1" ScaleY="1" ScaleZ="1"/>
                <RotateTransform3D>
                    <RotateTransform3D.Rotation>
                        <AxisAngleRotation3D Angle="0" Axis="0 1 0"/>
                    </RotateTransform3D.Rotation>
                </RotateTransform3D>
                <TranslateTransform3D OffsetX="0" OffsetY="0" OffsetZ="0"/>
            </Transform3DGroup>
            <Transform3DGroup x:Key="立方体OR9TR8" >
                <TranslateTransform3D OffsetX="0" OffsetY="0" OffsetZ="0"/>
                <ScaleTransform3D ScaleX="1" ScaleY="1" ScaleZ="1"/>
                <RotateTransform3D>
                    <RotateTransform3D.Rotation>
                        <AxisAngleRotation3D Angle="0" Axis="0 1 0"/>
                    </RotateTransform3D.Rotation>
                </RotateTransform3D>
                <TranslateTransform3D OffsetX="-0.258329" OffsetY="0.0941457" OffsetZ="-0.662509"/>
            </Transform3DGroup>
            <MeshGeometry3D x:Key="立方体OR9GR10" 
                TriangleIndices="0,1,2 2,3,0 4,5,6 6,7,4 8,9,10 10,11,8 12,13,14 14,15,12 16,17,18 18,19,16 20,21,22 22,23,20 "
                Normals="0,0,-1 0,0,-1 0,0,-1 0,0,-1 0,0,1 0,0,1 0,0,1 0,0,1 0,-1,0 0,-1,0 0,-1,0 0,-1,0 1,0,0 1,0,0 1,0,0 1,0,0 0,1,0 0,1,0 0,1,0 0,1,0 -1,0,0 -1,0,0 -1,0,0 -1,0,0 "
                Positions="-0.66,-0.405,0 -0.66,0.405,0 0.66,0.405,0 0.66,-0.405,0 -0.66,-0.405,0 0.66,-0.405,0 0.66,0.405,0 -0.66,0.405,0 -0.66,-0.405,0 0.66,-0.405,0 0.66,-0.405,0 -0.66,-0.405,0 0.66,-0.405,0 0.66,0.405,0 0.66,0.405,0 0.66,-0.405,0 0.66,0.405,0 -0.66,0.405,0 -0.66,0.405,0 0.66,0.405,0 -0.66,0.405,0 -0.66,-0.405,0 -0.66,-0.405,0 -0.66,0.405,0 "
            />
        </ResourceDictionary>
    </Viewport3D.Resources>

    <Viewport3D.Camera>
        <PerspectiveCamera x:Name="前视OR6" FarPlaneDistance="10" LookDirection="0,0,-1" UpDirection="0,1,0" NearPlaneDistance="2" Position="0,0,2.38396" FieldOfView="39.5978" />
    </Viewport3D.Camera>

    <ModelVisual3D>
        <ModelVisual3D.Content>
            <Model3DGroup x:Name="Scene" Transform="{DynamicResource SceneTR7}"> <!-- 场景 (XAML Path = ) -->
                <AmbientLight Color="#333333" />
                <DirectionalLight Color="#FFFFFF" Direction="0.0397419,0.00265522,-0.999206" />
                <DirectionalLight Color="#FFFFFF" Direction="0.648078,0.0259535,-0.761131" />
                <Model3DGroup x:Name="立方体OR9" Transform="{DynamicResource 立方体OR9TR8}"> <!-- 立方体 (XAML Path = (Viewport3D.Children)[0].(ModelVisual3D.Content).(Model3DGroup.Children)[3]) -->
                    <GeometryModel3D x:Name="立方体OR9GR10" Geometry="{DynamicResource 立方体OR9GR10}" Material="{DynamicResource ER___Flat_06MR1}" BackMaterial="{DynamicResource ER___Flat_06MR1}"/>
                </Model3DGroup>
            </Model3DGroup>
        </ModelVisual3D.Content>
    </ModelVisual3D>
</Viewport3D>

我们给ModelVisual3D.Transform中的RotateTransform3D中的AxisAngleRotation3D加上一个名字axisRotation

<ModelVisual3D.Transform>
                    <Transform3DGroup>
                        <TranslateTransform3D OffsetZ="0" OffsetX="0" OffsetY="0"/>
                        <ScaleTransform3D ScaleZ="1" ScaleY="1" ScaleX="1"/>
                        <RotateTransform3D d:EulerAngles="-1,0,0">
                            <RotateTransform3D.Rotation>
                                <AxisAngleRotation3D Axis="-1,0,0" Angle="1"
                                                     x:Name="axisRotation"/>
                            </RotateTransform3D.Rotation>
                        </RotateTransform3D>
                        <TranslateTransform3D OffsetZ="0" OffsetX="0" OffsetY="0"/>
                    </Transform3DGroup>
                </ModelVisual3D.Transform>

然后给Viewport3D加上一个名字recTest,并添加两个事件

MouseDown="recTest_MouseDown" MouseUp="recTest_MouseUp"

OK,然后后台我们完成代码,拿到鼠标单击point,然后还是调用VisualTreeHelper.HitTest方法

bool isPressed = false;
        private void recTest_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (!isPressed) {
                isPressed = true;
                Point location = e.GetPosition(recTest);
                RayMeshGeometry3DHitTestResult meshHitResult = (RayMeshGeometry3DHitTestResult)VisualTreeHelper.HitTest(recTest, location);

                axisRotation.Axis = new Vector3D(
                         -meshHitResult.PointHit.Y, meshHitResult.PointHit.X, 0);

                DoubleAnimation animation = new DoubleAnimation();
                animation.To = 10;
                animation.DecelerationRatio = 1;
                animation.Duration = TimeSpan.FromSeconds(0.1);
                animation.AutoReverse = false;
                axisRotation.BeginAnimation(AxisAngleRotation3D.AngleProperty, animation);
                recTest.CaptureMouse(); 
            }
        }

        private void recTest_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (isPressed) {
                isPressed = false;
                recTest.ReleaseMouseCapture();
                DoubleAnimation animation = new DoubleAnimation();
                animation.To = 0;
                animation.DecelerationRatio = 1;
                animation.Duration = TimeSpan.FromSeconds(0.1);
                animation.AutoReverse = false;
                axisRotation.BeginAnimation(AxisAngleRotation3D.AngleProperty, animation);
            }
        }

由于我们旋转不涉及z轴,所以我们就设置Axis的z轴为0。这里我捕获了鼠标,因为按下后,方块离开了鼠标释放时候的位置,所以这里我是如上那样处理的。

我们运行来看看效果图:

       =============潇洒的版权线==========www.ayjs.net===== Aaronyang ========= AY =========== 安徽 六安 杨洋 ==========   未经允许不许转载 =========

 

OK,接下来我们来看看如何将二维控件贴到三维空间去

ModelUIElement3D类,继承Visual3D(3个重要的类:ModelVisual3D,UIElement3D(包括ModelUIElement3D,ContainerUIElement3D),Viewport2DVisual3D)

Viewport2DVisual3D对象表示被放入3D空间的2D元素。

我有重新新建了个窗口,拷贝了上面的例子的代码,然后将ModelVisual3D =>ModelUIElement3D,Content=>Model

运行效果,同上个例子一样。区别在于,UIElement需要单击到模型了,不然不会触发

关于ContainerUIElement3D类,支持所有继承自Visual3D的对象组合,所以能包含普通的ModelVisual3D对象,也能包括可交互的ModelUIElement3D对象以及Viewport2DVisual3D对象。

接下来,我们使用Viewport2DVisual3D将2d的控件放入平面

Viewport2DVisual3D.Geometry定义网格

 

<Viewport2DVisual3D.Material>设置true使材质能显示内容
                   <DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial="True" />
               </Viewport2DVisual3D.Material>

使用 <Viewport2DVisual3D.Visual>来定以材质上显示的内容

Transform是用来变换这个Viewport2DVisual3D.Visual

<Viewport2DVisual3D>
                <Viewport2DVisual3D.Geometry>
                    <MeshGeometry3D 
                        TriangleIndices="0,1,2 2,3,0 4,5,6 6,7,4 8,9,10 11,12,13 14,15,16 17,18,19 20,21,22 23,24,25 26,27,28 29,30,31 "
                TextureCoordinates="1,1 1,0 -0,0 -0,1 0,1 1,1 1,0 0,0 0,-1"
                Positions="-0.66,-0.405,0 -0.66,0.405,0 0.66,0.405,0 0.66,-0.405,0 -0.66,-0.405,0 0.66,-0.405,0 0.66,0.405,0 -0.66,0.405,0 -0.66,-0.405,0 0.66,-0.405,0 0.66,-0.405,0 0.66,-0.405,0 -0.66,-0.405,0 -0.66,-0.405,0 0.66,-0.405,0 0.66,0.405,0 0.66,0.405,0 0.66,0.405,0 0.66,-0.405,0 0.66,-0.405,0 0.66,0.405,0 -0.66,0.405,0 -0.66,0.405,0 -0.66,0.405,0 0.66,0.405,0 0.66,0.405,0 -0.66,0.405,0 -0.66,-0.405,0 -0.66,-0.405,0 -0.66,-0.405,0 -0.66,0.405,0 -0.66,0.405,0 "/>
                </Viewport2DVisual3D.Geometry>

                <Viewport2DVisual3D.Material>
                    <DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial="True" />
                </Viewport2DVisual3D.Material>

                <Viewport2DVisual3D.Visual>
                    <Border BorderBrush="#ffffff">
                        <StackPanel Margin="10">
                            <TextBlock Margin="3">ay的label</TextBlock>
                            <Button Margin="3">ay的按钮</Button>
                            <TextBox Margin="3">ay的文本框</TextBox>
                        </StackPanel>
                    </Border>
                </Viewport2DVisual3D.Visual>

                <Viewport2DVisual3D.Transform>
                    <Transform3DGroup>
                        <TranslateTransform3D OffsetZ="0" OffsetX="0" OffsetY="0"/>
                        <ScaleTransform3D ScaleZ="1" ScaleY="1" ScaleX="1"/>
                        <RotateTransform3D d:EulerAngles="186.328,8.578,-132.64">
                            <RotateTransform3D.Rotation>
                                <AxisAngleRotation3D Axis="0.398,-0.917,0.02" Angle="{Binding ElementName=axisRotation, Path=Angle}"/>
                            </RotateTransform3D.Rotation>
                        </RotateTransform3D>
                        <TranslateTransform3D OffsetZ="0" OffsetX="0" OffsetY="0"/>
                        <TranslateTransform3D OffsetZ="-0.133" OffsetX="-0.062" OffsetY="-0.104"/>
                    </Transform3DGroup>
                </Viewport2DVisual3D.Transform>
            </Viewport2DVisual3D>

注意MeshGeometry3D的TextureCoordinates不写值,是不会在图形上贴上材质的,这里的值我调了很久还没很好的调好,最后我在ZAM中使用拖拽的方式贴上了一张图,然后拷贝了贴图的TextureCoordinates,然后稍微修改了下,位置才马马虎虎的对

OK,到目前为止,WPF的基础3D知识已经讲完了,谢谢你的阅读。

       =============潇洒的版权线==========www.ayjs.net===== Aaronyang ========= AY =========== 安徽 六安 杨洋 ==========   未经允许不许转载 =========

 

推荐您阅读更多有关于“WPF4.5,”的文章

猜你喜欢

额 本文暂时没人评论 来添加一个吧

发表评论

必填

选填

选填

必填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

  查看权限

抖音:wpfui 工作wpf,目前主maui

招聘合肥一枚WPF工程师,跟我一个开发组,10-15K,欢迎打扰

目前在合肥市企迈科技就职

AYUI8全源码 Github地址:前往获取

杨洋(AaronYang简称AY,安徽六安人)AY唯一QQ:875556003和AY交流

高中学历,2010年开始web开发,2015年1月17日开始学习WPF

声明:AYUI7个人与商用免费,源码可购买。部分DEMO不免费

不是从我处购买的ayui7源码,我不提供任何技术服务,如果你举报从哪里买的,我可以帮你转正为我的客户,并送demo

查看捐赠

AYUI7.X MVC教程 更新如下:

第一课 第二课 程序加密教程

标签列表