65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 WPF 创建 3D 应用程序

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.83/5 (8投票s)

2009年10月20日

CPOL

4分钟阅读

viewsIcon

69824

downloadIcon

5081

WPF_3D_Application

引言

这是一个非常简单的 3D 应用程序,用 WPF 编写。这是一个完全的 3D 应用程序,它还具有鼠标滚轮缩放控制,以及键盘箭头的手动水平旋转功能。
我发布这篇文章的原因是为了向其他人和其他开发者展示 WPF 框架的可能性!

背景

此应用程序的可能性是无限的。唯一的问题是“您的硬件能承受吗?!”

Using the Code

这个应用程序完全是直接的。从开发者的角度来看,它包含几个文本框、按钮、一个 MediaElement (对于那些没有使用过 WPF 的人来说,MediaElement 是一个可以用来播放媒体文件的控件)、listview...正如我已经说过的,非常直接,但这个应用程序在正常桌面应用程序方面有一些例外。对于那些做过 3D 编程的人来说,其中大部分会很熟悉。

我提到 3D 编程是因为这个应用程序就是这样制作的。在这里,我有 ViewPort3D 控件、相机控件、灯光控件和 3D 模型,没有它们一切都将毫无意义!让我们看看这一切在 XAML 代码中是什么样的(我展示它在 XAML 中的样子是因为从这里创建一个 3D 场景要容易得多)。

<Grid>
   <Viewport3D x:Name="view" ClipToBounds="False" RenderOptions.EdgeMode="Aliased">
   <!--3D Scene-->
   <Viewport3D.Camera>
       <PerspectiveCamera x:Name="camera" FieldOfView="59" 
		Position="0.5,0.5,2" LookDirection="0,0,-1">
           <PerspectiveCamera.Transform>
               <RotateTransform3D x:Name="rot" CenterY="0.5" CenterX="0.5" CenterZ="-0.5">
                   <RotateTransform3D.Rotation>
                       <!-- rotation -->
                       <AxisAngleRotation3D x:Name="camRotation" Axis="0,1,0" Angle="0"/>
                   </RotateTransform3D.Rotation>
               </RotateTransform3D>
           </PerspectiveCamera.Transform>
       </PerspectiveCamera>    
   </Viewport3D.Camera>
   <!--Light-->
   <ModelVisual3D>
       <ModelVisual3D.Content>
           <AmbientLight Color="White" />
       </ModelVisual3D.Content>
   </ModelVisual3D>
</Grid>

这是在 WPF 和 XAML 中创建 3D 场景的简单示例。现在我们有了 3D 场景,我们需要创建一个需要渲染的 3D 模型。你们中的许多人现在可能会想,这肯定不简单,但事实并非如此!

您需要的唯一东西就是您的大脑和一点数学知识,但您也可以使用一些外部软件来创建更复杂的 3D 模型。(3D Studio Max、Blender、Maya....)

在我继续之前,我想对那些能够并且想要制作 3D 模型的人说,Blender 是一个很棒的 3D 动画工具,它还可以直接导出模型到 XAML,也可以导出为 *.x 和许多其他格式。另外,最重要的是它是免费的;)

可以从 这里 下载 Blender。

现在让我们看看如何制作立方体的一个面并向其中添加一些内容。

<!-- cube front side -->
        <!--
        This is element which get controls and put them in 3D
        (make all scaling and transforming cordinates for you that looks like it is in 3D)
        -->
        <Viewport2DVisual3D Material="{StaticResource CubeSideMaterial}">
            <!--this is part where all drawing are done for this part-->
            <Viewport2DVisual3D.Geometry>
                <!--
                meshgeometry3d give you possibility to put bunch of points 
	       and to locate them in 3D and to connect them in what way 
	       you like (for connecting points we use 
                TriangleIndices-because all 3d graphic rendering are done with triangles)
                -->
                <MeshGeometry3D Positions="0,1,0 0,0,0 1,0,0 1,1,0"
                                TextureCoordinates="0,0 0,1 1,1 1,0"
                                TriangleIndices="0 1 2  0 2 3"/>
            </Viewport2DVisual3D.Geometry>
            <!--
            when we are finished our drawing we can put everything what we want in our
            Viewport2DVisual3D control,and it will be rendered like normal desktop app
            -->
            <Grid x:Name="FrontPanel" Background="
            	{StaticResource BlackBackground}" ShowGridLines="False" 
            	IsHitTestVisible="True" Margin="0">
                <Grid.BitmapEffect>
                    <OuterGlowBitmapEffect GlowSize="2" />
                </Grid.BitmapEffect>
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition Height="15"/>
                    <RowDefinition Height="15" MaxHeight="15" />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <Button Style="{DynamicResource SimpleButton}" 
                	Grid.Row="3" Grid.Column="0" 
                	Grid.ColumnSpan="2" Content="Ok" 
                	Foreground="White" Click="Button_Click" 
                	FlowDirection="LeftToRight" FontSize="3" 
                	VerticalContentAlignment="Top"
                        Width="40"
                        Height="5"
                        Margin="0,2,0,2"
                        />
                <TextBox Grid.Row="1" Grid.Column="1" 
                	Height="5" Width="45" Margin="1,1,2,1" 
                	x:Name="textBox1" BorderThickness="0" 
                	ClipToBounds="False" FontSize="3.5" 
                	Padding="0,0.3,0,0"/>
                <PasswordBox Grid.Row="2" Grid.Column="1" 
                	Height="5" Width="45" 
                	Margin="1,-9.5,2,1" x:Name="passwordBox1" 
                	VerticalAlignment="Center" BorderThickness="0" 
                	Padding="0,0.3,0,0" FontSize="3.5" />
                <Label Grid.Row="1" Grid.Column="0" 
                	x:Name="label1" Foreground="White" 
                	FontSize="4" HorizontalAlignment="Left" 
                	MinWidth="0" Padding="3,5,3,3" 
                	Content="Username:"/>
                <Label Grid.Row="2" Grid.Column="0" 
                	FontSize="4" Foreground="White" 
                	x:Name="label2" Margin="0,-3,0,0" 
                	Padding="3" Content="Password:"/>
                <Label FontSize="5" Foreground="White" 
                	Grid.Row="0" Grid.Column="0" 
                	Grid.ColumnSpan="2" x:Name="label3" 
                	FontStyle="Oblique" FontWeight="Bold" Content="LogIn"/> 
            </Grid>
        </Viewport2DVisual3D> 

在这里我们可以看到如何制作 3D Mesh。这是一个非常简单的网格,只有四个点,但它也是一个很好的例子。关于 TriangleIndices 的一个重要事情是,一个三角形中的点连接必须是逆时针方向,并且三角形需要相互面向,像这样。

Positions="0,1,0 0,0,0 1,0,0 1,1,0"
TriangleIndices="0 1 2  0 2 3" 

但是您可以尝试一下,您就会看到会发生什么!;)

我还将谈论媒体播放器和媒体搜寻位置。我提到这一点的原因是我在设置这个时遇到了一些问题,直到我找到了一篇帮助我解决这个问题的文章。为了进行媒体搜寻,我放了一个滑块控件,这很正常 :) 但是当您仔细观察并认为滑块会在某个时间间隔更新,并且每次更新都会运行滑块的 ValueChanged_Event 时,您就不能通过滑块的 ValueChanged_Event 来实现媒体搜寻,也不会在播放时出现媒体故障!

但 WPF 中一个有趣的事情是,您可以为控件的每个部分创建事件,正是在那里,您会发现您可以仅为滑块的拖动创建事件处理程序(但有一件重要的事情是,您需要区分拖放事件处理程序和滑块拖动事件)。

//slider control and thumb drag event
<Slider x:Name="PositionSlider" Thumb.DragCompleted="PositionSlider_DragCompleted" 
	Style="{DynamicResource SimpleSlider}" />
//and this is code behind
 private void PositionSlider_DragCompleted
	(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
 {
        mediaPlayer.Position = TimeSpan.FromMilliseconds(PositionSlider.Value);
 }

这就是我认为重要的全部内容。如果您有其他问题,请留言!

谢谢,Crashandburn

关注点

我只想在这里补充几句,说明这是一个多么棒且有用的东西……想想看,如果有人制作了一个 3D 操作系统,或者您如何在单个窗口中创建大型业务应用程序?!!

运行教程

对于那些只想运行此应用程序的人,他们将需要 .NET 3.0 Framework,您可以 在这里 下载,而且,我认为但不确定 - Windows Media Player 10 或更高版本!

可执行文件位于 \bin\Debug 目录中,登录信息是

  • 用户名:crash
  • 密码:burn

历史

  • 2009年10月20日:首次发布
使用 WPF 制作 3D 应用程序 - CodeProject - 代码之家
© . All rights reserved.