■ VisualTreeHelper 클래스 : HitTest 정적 메소드를 사용해 히트 테스트하기

------------------------------------------------------------------------------------------------------------------------


TestProject.zip


MainWindow.xaml

 

 

<Window x:Class="TestProject.MainWindow"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Title="VisualTreeHelper 클래스 : HitTest 정적 메소드를 사용해 히트 테스트하기"

    Width="800"

    Height="600">

    <Window.Resources>

        <!-- 단위 큐브 : 전면, 후면, 왼쪽 면, 오른쪽 면, 위쪽 면, 아래쪽 면 -->

        <MeshGeometry3D x:Key="CubeMeshGeometry3DKey"

            Positions="-0.5  0.5  0.5,  0.5  0.5  0.5,

                       -0.5 -0.5  0.5,  0.5 -0.5  0.5,

                        0.5  0.5 -0.5, -0.5  0.5 -0.5,

                        0.5 -0.5 -0.5, -0.5 -0.5 -0.5,

                       -0.5  0.5 -0.5, -0.5  0.5  0.5,

                       -0.5 -0.5 -0.5, -0.5 -0.5  0.5,

                        0.5  0.5  0.5,  0.5  0.5 -0.5,

                        0.5 -0.5  0.5,  0.5 -0.5 -0.5,

                       -0.5  0.5 -0.5,  0.5  0.5 -0.5,

                       -0.5  0.5  0.5,  0.5  0.5  0.5,

                        0.5 -0.5 -0.5, -0.5 -0.5 -0.5,

                        0.5 -0.5  0.5, -0.5 -0.5  0.5"

            TriangleIndices=" 0  2  1,  1  2  3

                              4  6  5,  5  6  7,

                              8 10  9,  9 10 11,

                             12 14 13, 13 14 15

                             16 18 17, 17 18 19

                             20 22 21, 21 22 23" />

        <DiffuseMaterial x:Key="WoodDiffuseMaterialKey"

            Brush="BurlyWood" />

        <!-- 테이블 다리 -->

        <GeometryModel3D x:Key="TableLegGeometryModel3DKey"

            Geometry="{StaticResource CubeMeshGeometry3DKey}"

            Material="{StaticResource WoodDiffuseMaterialKey}">

            <GeometryModel3D.Transform>

                <ScaleTransform3D

                    CenterY="-1"

                    ScaleX="0.1"

                    ScaleY="2"

                    ScaleZ="0.1" />

            </GeometryModel3D.Transform>

        </GeometryModel3D>

        <!-- 테이블 -->

        <Model3DGroup x:Key="TableModel3DGroupKey">

            <!-- 테이블 다리 4개 -->

            <Model3DGroup>

                <StaticResource ResourceKey="TableLegGeometryModel3DKey" />

                <Model3DGroup.Transform>

                    <TranslateTransform3D

                        OffsetX="-1"

                        OffsetZ="-1" />

                </Model3DGroup.Transform>

            </Model3DGroup>

            <Model3DGroup>

                <StaticResource ResourceKey="TableLegGeometryModel3DKey" />

                <Model3DGroup.Transform>

                    <TranslateTransform3D

                        OffsetX="1"

                        OffsetZ="-1" />

                </Model3DGroup.Transform>

            </Model3DGroup>

            <Model3DGroup>

                <StaticResource ResourceKey="TableLegGeometryModel3DKey" />

                <Model3DGroup.Transform>

                    <TranslateTransform3D

                        OffsetX="-1"

                        OffsetZ="1" />

                </Model3DGroup.Transform>

            </Model3DGroup>

            <Model3DGroup>

                <StaticResource ResourceKey="TableLegGeometryModel3DKey" />

                <Model3DGroup.Transform>

                    <TranslateTransform3D

                        OffsetX="1"

                        OffsetZ="1" />

                </Model3DGroup.Transform>

            </Model3DGroup>

            <!-- 테이블 위쪽 -->

            <GeometryModel3D

                Geometry="{StaticResource CubeMeshGeometry3DKey}"

                Material="{StaticResource WoodDiffuseMaterialKey}">

                <GeometryModel3D.Transform>

                    <Transform3DGroup>

                        <ScaleTransform3D

                            ScaleX="2.5"

                            ScaleZ="2.5"

                            ScaleY="0.1" />

                        <TranslateTransform3D OffsetY="2.05" />

                    </Transform3DGroup>

                </GeometryModel3D.Transform>

            </GeometryModel3D>

        </Model3DGroup>

        <!-- 의자 -->

        <Model3DGroup x:Key="ChairModel3DGroupKey">

            <!-- 전면 오른쪽 다리 -->

            <GeometryModel3D

                Geometry="{StaticResource CubeMeshGeometry3DKey}"

                Material="{StaticResource WoodDiffuseMaterialKey}">

                <GeometryModel3D.Transform>

                    <Transform3DGroup>

                        <ScaleTransform3D

                            ScaleX="0.1"

                            ScaleY="1.5"

                            ScaleZ="0.1" />

                        <TranslateTransform3D

                            OffsetX="0.5"

                            OffsetY="0.75"

                            OffsetZ="0.5" />

                    </Transform3DGroup>

                </GeometryModel3D.Transform>

            </GeometryModel3D>

            <!-- 전면 왼쪽 다리 -->

            <GeometryModel3D

                Geometry="{StaticResource CubeMeshGeometry3DKey}"

                Material="{StaticResource WoodDiffuseMaterialKey}">

                <GeometryModel3D.Transform>

                    <Transform3DGroup>

                        <ScaleTransform3D

                            ScaleX="0.1"

                            ScaleY="1.5"

                            ScaleZ="0.1" />

                        <TranslateTransform3D

                            OffsetX="-0.5"

                            OffsetY="0.75"

                            OffsetZ="0.5" />

                    </Transform3DGroup>

                </GeometryModel3D.Transform>

            </GeometryModel3D>

            <!-- 후면 오른쪽 다리 -->

            <GeometryModel3D

                Geometry="{StaticResource CubeMeshGeometry3DKey}"

                Material="{StaticResource WoodDiffuseMaterialKey}">

                <GeometryModel3D.Transform>

                    <Transform3DGroup>

                        <ScaleTransform3D

                            ScaleX="0.1"

                            ScaleY="3.0"

                            ScaleZ="0.1" />

                        <TranslateTransform3D

                            OffsetX="0.5"

                            OffsetY="1.5"

                            OffsetZ="-0.5" />

                    </Transform3DGroup>

                </GeometryModel3D.Transform>

            </GeometryModel3D>

            <!-- 후면 왼쪽 다리 -->

            <GeometryModel3D

                Geometry="{StaticResource CubeMeshGeometry3DKey}"

                Material="{StaticResource WoodDiffuseMaterialKey}">

                <GeometryModel3D.Transform>

                    <Transform3DGroup>

                        <ScaleTransform3D

                            ScaleX="0.1"

                            ScaleY="3.0"

                            ScaleZ="0.1" />

                        <TranslateTransform3D

                            OffsetX="-0.5"

                            OffsetY="1.5"

                            OffsetZ="-0.5" />

                    </Transform3DGroup>

                </GeometryModel3D.Transform>

            </GeometryModel3D>

            <!-- 의자 시트 -->

            <GeometryModel3D

                Geometry="{StaticResource CubeMeshGeometry3DKey}"

                Material="{StaticResource WoodDiffuseMaterialKey}">

                <GeometryModel3D.Transform>

                    <Transform3DGroup>

                        <ScaleTransform3D

                            ScaleX="1.25"

                            ScaleY="0.1"

                            ScaleZ="1.25" />

                        <TranslateTransform3D OffsetY="1.55" />

                    </Transform3DGroup>

                </GeometryModel3D.Transform>

            </GeometryModel3D>

            <!-- 등받이 -->

            <GeometryModel3D

                Geometry="{StaticResource CubeMeshGeometry3DKey}"

                Material="{StaticResource WoodDiffuseMaterialKey}">

                <GeometryModel3D.Transform>

                    <Transform3DGroup>

                        <ScaleTransform3D

                            ScaleX="0.9"

                            ScaleY="0.25"

                            ScaleZ="0.1" />

                        <TranslateTransform3D

                            OffsetZ="-0.5"

                            OffsetY="2.75" />

                    </Transform3DGroup>

                </GeometryModel3D.Transform>

            </GeometryModel3D>

        </Model3DGroup>

    </Window.Resources>

    <Viewport3D Name="viewport3d">

        <!-- 녹색 리놀륨 바닥 -->

        <ModelVisual3D x:Name="floorModelVisual3D">

            <ModelVisual3D.Content>

                <GeometryModel3D Geometry="{StaticResource CubeMeshGeometry3DKey}">

                    <GeometryModel3D.Material>

                        <DiffuseMaterial Brush="Lime" />

                    </GeometryModel3D.Material>

                </GeometryModel3D>

            </ModelVisual3D.Content>

            <ModelVisual3D.Transform>

                <Transform3DGroup>

                    <ScaleTransform3D

                        ScaleX="8"

                        ScaleY="0.1"

                        ScaleZ="8" />

                    <TranslateTransform3D OffsetY="-0.05" />

                </Transform3DGroup>

            </ModelVisual3D.Transform>

        </ModelVisual3D>

        <!-- 테이블 -->

        <ModelVisual3D x:Name="tableModelVisual3D" Content="{StaticResource TableModel3DGroupKey}">

            <ModelVisual3D.Transform>

                <Transform3DGroup>

                    <TranslateTransform3D x:Name="tableTranslateTransform3D" />

                    <RotateTransform3D>

                        <RotateTransform3D.Rotation>

                            <AxisAngleRotation3D x:Name="tableAxisAngleRotation3D" />

                        </RotateTransform3D.Rotation>

                    </RotateTransform3D>

                </Transform3DGroup>

            </ModelVisual3D.Transform>

        </ModelVisual3D>

        <!-- 4개 의자 -->

        <ModelVisual3D x:Name="charModelVisual3D1"

            Content="{StaticResource ChairModel3DGroupKey}">

            <ModelVisual3D.Transform>

                <Transform3DGroup>

                    <RotateTransform3D>

                        <RotateTransform3D.Rotation>

                            <AxisAngleRotation3D Angle="-90" />

                        </RotateTransform3D.Rotation>

                    </RotateTransform3D>

                    <TranslateTransform3D OffsetX="2.5" />

                </Transform3DGroup>

            </ModelVisual3D.Transform>

        </ModelVisual3D>

        <ModelVisual3D x:Name="charModelVisual3D2"

            Content="{StaticResource ChairModel3DGroupKey}">

            <ModelVisual3D.Transform>

                <Transform3DGroup>

                    <RotateTransform3D>

                        <RotateTransform3D.Rotation>

                            <AxisAngleRotation3D Angle="180" />

                        </RotateTransform3D.Rotation>

                    </RotateTransform3D>

                    <TranslateTransform3D OffsetZ="2.5" />

                </Transform3DGroup>

            </ModelVisual3D.Transform>

        </ModelVisual3D>

        <ModelVisual3D x:Name="charModelVisual3D3"

            Content="{StaticResource ChairModel3DGroupKey}">

            <ModelVisual3D.Transform>

                <Transform3DGroup>

                    <RotateTransform3D>

                        <RotateTransform3D.Rotation>

                            <AxisAngleRotation3D Angle="90" />

                        </RotateTransform3D.Rotation>

                    </RotateTransform3D>

                    <TranslateTransform3D OffsetX="-2.5" />

                </Transform3DGroup>

            </ModelVisual3D.Transform>

        </ModelVisual3D>

        <ModelVisual3D x:Name="charModelVisual3D4"

            Content="{StaticResource ChairModel3DGroupKey}">

            <ModelVisual3D.Transform>

                <Transform3DGroup>

                    <RotateTransform3D>

                        <RotateTransform3D.Rotation>

                            <AxisAngleRotation3D Angle="0" />

                        </RotateTransform3D.Rotation>

                    </RotateTransform3D>

                    <TranslateTransform3D OffsetZ="-2.5" />

                </Transform3DGroup>

            </ModelVisual3D.Transform>

        </ModelVisual3D>

        <!-- 조명 -->

        <ModelVisual3D>

            <ModelVisual3D.Content>

                <Model3DGroup>

                    <AmbientLight Color="#404040" />

                    <DirectionalLight

                        Color="#c0c0c0"

                        Direction="2, -3 -1" />

                </Model3DGroup>

            </ModelVisual3D.Content>

        </ModelVisual3D>

        <!-- 카메라 -->

        <Viewport3D.Camera>

            <PerspectiveCamera

                Position="3 4 12"

                LookDirection="-1.5 -1.5 -5"

                UpDirection="0 1 0"

                FieldOfView="45" />

        </Viewport3D.Camera>

    </Viewport3D>

</Window>

 

 

MainWindow.xaml.cs

 

 

using System;

using System.Windows;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Animation;

using System.Windows.Media.Media3D;

 

namespace TestProject

{

    /// <summary>

    /// 메인 윈도우

    /// </summary>

    public partial class MainWindow : Window

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - MainWindow()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainWindow()

        {

            InitializeComponent();

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Protected

 

        #region 마우스 DOWN 처리하기 - OnMouseDown(e)

 

        /// <summary>

        /// 마우스 DOWN 처리하기

        /// </summary>

        /// <param name="e">이벤트 인자</param>

        protected override void OnMouseDown(MouseButtonEventArgs e)

        {

            Point mousePoint = e.GetPosition(this.viewport3d);

 

            VisualTreeHelper.HitTest(this.viewport3d, null, HitTestFilter, new PointHitTestParameters(mousePoint));

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region 히트 테스트 필터 처리하기 - HitTestFilter(hitTestResult)

 

        /// <summary>

        /// 히트 테스트 필터 처리하기

        /// </summary>

        /// <param name="hitTestResult">히트 테스트 결과</param>

        /// <returns>히트 테스트 결과 비헤이비어</returns>

        private HitTestResultBehavior HitTestFilter(HitTestResult hitTestResult)

        {

            RayMeshGeometry3DHitTestResult rayMeshGeometry3DHitTestResult = hitTestResult as RayMeshGeometry3DHitTestResult;

 

            if(rayMeshGeometry3DHitTestResult == null)

            {

                return HitTestResultBehavior.Continue;

            }

 

            ModelVisual3D modelVisual3D = rayMeshGeometry3DHitTestResult.VisualHit as ModelVisual3D;

 

            if(modelVisual3D == null)

            {

                return HitTestResultBehavior.Continue;

            }

 

            if(modelVisual3D == this.floorModelVisual3D)

            {

                GeometryModel3D geometryModel3D = rayMeshGeometry3DHitTestResult.ModelHit as GeometryModel3D;

 

                DiffuseMaterial diffuseMaterial = geometryModel3D.Material as DiffuseMaterial;

 

                Random random = new Random();

 

                diffuseMaterial.Brush = new SolidColorBrush

                (

                    Color.FromRgb

                    (

                        (byte)random.Next(256),

                        (byte)random.Next(256),

                        (byte)random.Next(256)

                    )

                );

 

                return HitTestResultBehavior.Stop;

            }

 

            if(modelVisual3D == this.tableModelVisual3D)

            {

                Storyboard storyboard = new Storyboard();

 

                DoubleAnimation doubleAnimation;

 

                #region 테이블을 위로 이동시키는 애니메이션을 정의한다.

 

                doubleAnimation = new DoubleAnimation();

 

                doubleAnimation.From = 0;

                doubleAnimation.To   = 2;

 

                Storyboard.SetTargetName(doubleAnimation, "tableTranslateTransform3D");

                Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath(TranslateTransform3D.OffsetYProperty));

 

                storyboard.Children.Add(doubleAnimation);

 

                #endregion

                #region 테이블을 회전시키는 애니메이션을 정의한다.

 

                doubleAnimation = new DoubleAnimation();

 

                doubleAnimation.From      = 0;

                doubleAnimation.To        = 90;

                doubleAnimation.BeginTime = TimeSpan.FromSeconds(1);

 

                Storyboard.SetTargetName(doubleAnimation, "tableAxisAngleRotation3D");

                Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath(AxisAngleRotation3D.AngleProperty));

 

                storyboard.Children.Add(doubleAnimation);

 

                #endregion

                #region 테이블을 아래로 이동시키는 애니메이션을 정의한다.

 

                doubleAnimation = new DoubleAnimation();

 

                doubleAnimation.From      = 2;

                doubleAnimation.To        = 0;

                doubleAnimation.BeginTime = TimeSpan.FromSeconds(2);

 

                Storyboard.SetTargetName(doubleAnimation, "tableTranslateTransform3D");

                Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath(TranslateTransform3D.OffsetYProperty));

 

                storyboard.Children.Add(doubleAnimation);

 

                #endregion

 

                storyboard.Begin(this);

 

                return HitTestResultBehavior.Stop;

            }

 

            if(modelVisual3D == this.charModelVisual3D1 || modelVisual3D == this.charModelVisual3D2 ||

                modelVisual3D == this.charModelVisual3D3 || modelVisual3D == this.charModelVisual3D4)

            {

                Transform3DGroup transform3DGroup = modelVisual3D.Transform as Transform3DGroup;

 

                if(transform3DGroup == null)

                {

                    return HitTestResultBehavior.Stop;

                }

 

                for(int i = 0; i < transform3DGroup.Children.Count; i++)

                {

                    TranslateTransform3D translateTransform3D = transform3DGroup.Children[i] as TranslateTransform3D;

 

                    if(translateTransform3D != null)

                    {

                        DoubleAnimation doubleAnimation = new DoubleAnimation();

 

                        DependencyProperty dependencyProperty = null;

 

                        if(translateTransform3D.OffsetZ == 0)

                        {

                            dependencyProperty = TranslateTransform3D.OffsetXProperty;

 

                            if(Math.Abs(translateTransform3D.OffsetX) < 2)

                            {

                                doubleAnimation.To = 2.5 * Math.Sign(translateTransform3D.OffsetX);

                            }

                            else

                            {

                                doubleAnimation.To = 1.25 * Math.Sign(translateTransform3D.OffsetX);

                            }

                        }

                        else

                        {

                            dependencyProperty = TranslateTransform3D.OffsetZProperty;

 

                            if(Math.Abs(translateTransform3D.OffsetZ) < 2)

                            {

                                doubleAnimation.To = 2.5 * Math.Sign(translateTransform3D.OffsetZ);

                            }

                            else

                            {

                                doubleAnimation.To = 1.25 * Math.Sign(translateTransform3D.OffsetZ);

                            }

                        }

 

                        translateTransform3D.BeginAnimation(dependencyProperty, doubleAnimation);

 

                        return HitTestResultBehavior.Stop;

                    }

                }

            }

 

            return HitTestResultBehavior.Continue;

        }

 

        #endregion

    }

}

 

------------------------------------------------------------------------------------------------------------------------

Posted by 사용자 icodebroker

댓글을 달아 주세요