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);

转载于:https://www.cnblogs.com/enjoyeclipse/archive/2012/09/27/2706265.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值