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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM