• WPF 3D 加载局部模型


    这篇主要介绍如何实现局部加载模型。阅读这篇博客前,需要参考我的另一篇博文,动态加载模型:http://www.cnblogs.com/enjoyeclipse/archive/2012/03/21/2410439.html

    1.效果:

        如图所示,因为整个沙盘场景太大,因此需要将桥墩加载并进行放大。不知道大家玩过实况足球没有,选择某个球员就有这种效果。

       

    2.思路:

         1). 首先需要构造一个容器,这个容器有ViewPort元素;

         2). 从大沙盘中选取需要的局部模型,并克隆一份(因为WPF中模型对象的Tree关系,因此不能直接将Add(model),必须Add(model.Clone()),

         3). 将局部模型添加到容器的ViewPort中。

    3.实现:

        1). 首先需要构造一个容器,这个容器有ViewPort元素。

             创建容器(UserControl):PartModelControl,最重要的里面要包含ViewPort,并提前把光照,摄像机什么的设置好

             xaml代码如下:

             <UserControl x:Class="UI.Common.UserControls.PartModelControl"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:converter="clr-namespace:UI.Common.Converters"
        Background="Transparent" 
        SnapsToDevicePixels="True"
        x:Name="modelPartControl" PreviewMouseDoubleClick="modelPartControl_MouseDoubleClick">
            ....
            <Viewport3D x:Name="_partViewPort">
                <Viewport3D.Camera>
                    <!--<PerspectiveCamera x:Name="camera" FieldOfView="45" FarPlaneDistance="1782.5084757839907" LookDirection="0,0,-607.743292014972" NearPlaneDistance="0.1" Position="-0.0207443237299856,-2.1316282072803E-14,407.743292014972" UpDirection="0,1,0"/>-->
                    <PerspectiveCamera x:Name="camera" FieldOfView="30" FarPlaneDistance="102122.68952517369" LookDirection="292.292480468755,-0.00048828125,-2204.4668208912" Position="-292.292480468755,0.00048828125,2204.4668208912" NearPlaneDistance="0.1"  UpDirection="0,1,0"/>
                </Viewport3D.Camera>
                <ModelVisual3D x:Name="World">
                    <ModelVisual3D x:Name="AmbientLightContainer">
                        <ModelVisual3D.Content>
                            <AmbientLight x:Name="AmbientLight" Color="#FF7F7F7F"/>
                        </ModelVisual3D.Content>
                    </ModelVisual3D>
                    <ModelVisual3D x:Name="DirectionalLightContainer">
                        <ModelVisual3D.Content>
                            <DirectionalLight x:Name="DirectionalLight" Color="#FF3F3F3F" Direction="0,0,-1">
                                <DirectionalLight.Transform>
                                    <TranslateTransform3D OffsetX="0" OffsetY="0" OffsetZ="3"/>
                                </DirectionalLight.Transform>
                            </DirectionalLight>
                        </ModelVisual3D.Content>
                    </ModelVisual3D>
                    <ModelVisual3D.Transform>
                        <TranslateTransform3D x:Name="transform" OffsetX="0" OffsetY="0" OffsetZ="0" />
                    </ModelVisual3D.Transform>
                </ModelVisual3D>
            </Viewport3D>
            <!--END Viewport-->
            ....

    </UserControl> 

    2). 从大沙盘中选取需要的局部模型,并克隆一份 

    • 从沙盘中选取模型:首先不能用WPF默认的方法制作3D,必须用第三方库WaveFrontObjLoader动态加载模型,因为这时候他会将3D的名字和模型形成Dictionary,就可以用Find(string Name)方法加载模型了。具体参考我的博客:http://www.cnblogs.com/enjoyeclipse/archive/2012/03/21/2410439.html 
    • 实现ModelVisual3DWithName的Clone方法:

            [ContentProperty("Children")]

        public class ModelVisual3DWithName : ModelVisual3D, ICloneable
        {
            public string Name { getset; }

            public object Tag { getset; }

            public object Clone()
            {
                var model = new ModelVisual3DWithName { Content = Content.Clone(), 
                                                        Name = Name, 
                                                        Tag = Tag
                                                       };
                model.SetColor(Brushes.DefaultSectionBrush);
                return model;
            }

            public void SetMaterial(Material material)
            {
                var geometrymodel = Content as GeometryModel3D;
                if (geometrymodel != null)
                {
                    geometrymodel.Material = material;
                }
                else
                {
                 
                }
            }

            public Material GetMaterial()
            {
                var geometrymodel = Content as GeometryModel3D;
                if (geometrymodel == null)
                {
                    return null;
                }
                return geometrymodel.Material;
            }

            public void SetColor(Brush color)
            {
                var geometrymodel = Content as GeometryModel3D;

                if (geometrymodel.Material is MaterialGroup)
                {
                    var materialGroup = geometrymodel.Material as MaterialGroup;
                    SetMaterialGroupColor(materialGroup, color);
                }
                else
                {
                    DiffuseMaterial material = geometrymodel.Material as DiffuseMaterial;
                    if (material != null && !material.IsFrozen)
                    {
                        material.Brush = color;
                    }
                }
            }


            private  void SetMaterialGroupColor(MaterialGroup materialGroup, Brush color)
            {
                foreach (var groupItem in materialGroup.Children)
                {
                    if (groupItem is DiffuseMaterial && !groupItem.IsFrozen)
                    {
                        var tmpItem = groupItem as DiffuseMaterial;
                        tmpItem.Brush = color;
                    }
                }
            }
        }

     3). 将刚才克隆的模型添加到容器中。

          调用world.children.Add()方法添加模型到容器中,逻辑如下:

          var findModel = _baseModel.Find(modelName) as ModelVisual3DWithName;

    if (findModel != null)
    {
                             model.Children.Add(findModel.Clone() as ModelVisual3DWithName);
    }
    world.Children.Add(findModel);
  • 相关阅读:
    Java加密AES算法及spring中应用
    IO流理解方式小结
    Spring CommonsMultipartResolver上传文件小结
    SpringMvc项目加载顺序及上下文小结
    Session学习小结
    MySql实现Oracle的row_number()over(partition by ... order by ...)
    Oracle存储过程小解
    mysql存储过程小解
    Java final关键字
    linux 同步 rsync的使用——远程服务器同步配置
  • 原文地址:https://www.cnblogs.com/enjoyeclipse/p/2706265.html
Copyright © 2020-2023  润新知