一、About primitives
在Balder中,有很多已经创建好了的基本体,你只要直接调用就可以了,这和3DMax等软件类似,里面也提供了一系列的基本体,给设计者扩展使用。目前,Balder的Geometries命名空间下已经有Box,Cylinder,Ring等等基本体。在之前的文章中,我们已经使用过了其中的Box,也就是那个立方体。当然,如果就这么些基本体,对于越来越复杂的需求,是不够的,因此Balder提供更大的扩展性。那么,该如何实现呢?请往下看...
二、How to create your own primitives
想要创建自定义的基本体,其实很简单,基本体,说到底其实就是一个Geometry(几何体)。而在Balder中,每个Geometry拥有一个实现了IGeometryContext 接口的GeometryContext类的属性,通过GeometryContext就可以创建被称为GeometryDetailLevel的东西。那么GeometryDetailLevel又是什么东西呢?它其实就是按照Balder想要进行渲染的细分级别来被渲染的一个对象。在大部分情况下,balder使用full detail level来进行渲染。在Geometry中有一个FullDetailLevel 属性,通过它,我们就可以方便的来产生一个几何体了。
三、a demo for creating a primitive
接下来,通过一个实例,来示范下基本体的创建过程,这里,我们通过创建一个三棱锥来作为例子:
首先,你需要创建一个你自己的基本体类继承自Geometry类
namespace MeshDemo
{
public class MyMesh:Geometry
{
}
}
这样,你就可以把该对象加到页面中去了,就像这样:
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6 xmlns:Execution="clr-namespace:Balder.Execution;assembly=Balder"
7 xmlns:View="clr-namespace:Balder.View;assembly=Balder"
8 xmlns:Lighting="clr-namespace:Balder.Lighting;assembly=Balder"
9 xmlns:Local="clr-namespace:MeshDemo"
10 mc:Ignorable="d"
11 d:DesignHeight="300" d:DesignWidth="400">
12
13 <Grid x:Name="LayoutRoot">
14 <Execution:Game Width="640" Height="480" >
15 <Execution:Game.Camera>
16 <View:Camera Position="-10,5,-10"/>
17 </Execution:Game.Camera>
18 <Local:MyMesh/> <!--加进去的基本体对象-->
19 </Execution:Game>
20 </Grid>
21 </UserControl>
但是,你此时编译运行它,在浏览器中,什么都看不到。因为,现在在几何体类中,没有创建任何的几何数据,为了创建这些,你需要实现重载Prepare()方法:
2 {
3 }
4
通过该方法,我们将加入3D网格数据,以创建基本体三棱锥,这里主要由三部分组成:
1.Vertices( 顶点)
2.Lines (线)
3.Face(面)
为了使得结构更清晰,我们把它们分别封装在三函数中:
private void GenerateVertices() //创建顶点
private void GenerateLines() //创建线
private void GenerateFaces() //创建面
接下来,我们一个个来分别完成,首先是创建顶点的:
2 {
3 var dimensionAsVector = new Vertex(5f, 5f, 5f);
4 var halfDimension = new Vertex(2.5f, 2.5f, 2.5f);
5 var Top = new Vertex(0f, dimensionAsVector.Y, 0f);
6 var backBottomLeft = new Vertex(-(halfDimension.X/2)*sqt, 0f, halfDimension.Z/2);
7 var backBottomRight = new Vertex(halfDimension.X/2*sqt, 0f, halfDimension.Z/2);
8 var frontBottom = new Vertex(0f, 0f, -halfDimension.Z);
9 FullDetailLevel.AllocateVertices(4);
10 FullDetailLevel.SetVertex(0, Top);
11 FullDetailLevel.SetVertex(1, backBottomLeft);
12 FullDetailLevel.SetVertex(2, backBottomRight);
13 FullDetailLevel.SetVertex(3, frontBottom);
14
15
16 }
2 {
3 FullDetailLevel.AllocateLines(6);
4 FullDetailLevel.SetLine(0, new Line(0, 1));
5 FullDetailLevel.SetLine(1, new Line(1, 3));
6 FullDetailLevel.SetLine(2, new Line(0, 2));
7 FullDetailLevel.SetLine(3, new Line(3, 2));
8 FullDetailLevel.SetLine(4, new Line(1, 2));
9 FullDetailLevel.SetLine(5, new Line(0, 3));
10
11
12 }
完成这两个函数,我们在 Prepare函数中调用它们,运行后你会看到这样的结果:
这样一个基本体就创建好了,当然,如果想要看到实体的话,就还需要完成面的组成函数:
{
FullDetailLevel.AllocateFaces(4);
FullDetailLevel.SetFace(0, new Face(3, 1, 0));
FullDetailLevel.SetFace(1, new Face(2, 3, 0));
FullDetailLevel.SetFace(2, new Face(2, 0, 1));
FullDetailLevel.SetFace(3, new Face(3, 2, 1));
}
在创建面的时候需要注意,就是顶点的连接顺序,每个面由三个顶点组成的,依次连接它们,在balder中连接顺序是按照顺时针方向的(这和Opengl正好相反),而且是你必须在几何体的外面来观察它。自己画个图形,应该容易理解,弄好后,别忘了加入到Prepare函数,运行,看结果:
你会发现,怎么是黑的?主要有两个原因:一是还没有给场景添加灯光照亮,二是需要法向量。balder中提供了一个 GeometryHelper对象,通过它,就可以方便的创建法向量:
在创建好顶点和面后加入: GeometryHelper.CalculateNormals(FullDetailLevel);
然后我们在修改xaml文件:
2 <Execution:Game Width="640" Height="480" >
3 <Execution:Game.Camera>
4 <View:Camera Position="-10,5,-10"/>
5 </Execution:Game.Camera>
6 <Lighting:OmniLight Position="10,20,-15" />
7 <Local:MyMesh InteractionEnabled="True" Color="Blue"/>
8 </Execution:Game>
9 </Grid>
加入灯光和物体颜色,ok,搞定,看看最后效果: