您的位置:首页 > 其它

WPF 3D 加载局部模型

2012-09-27 20:59 465 查看
这篇主要介绍如何实现局部加载模型。阅读这篇博客前,需要参考我的另一篇博文,动态加载模型:/article/5865904.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)方法加载模型了。具体参考我的博客:/article/5865904.html
实现ModelVisual3DWithName的Clone方法:

[ContentProperty("Children")]

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

public object Tag { get; set; }

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);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: