一、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,搞定,看看最后效果: