Balder 3D开发系列之--创建自己的primitives

一、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类

using Balder.Objects.Geometries;
 
namespace MeshDemo
{
    
public class MyMesh:Geometry
    {
    }
}

这样,你就可以把该对象加到页面中去了,就像这样:

 1 <UserControl x:Class="MeshDemo.MainPage"
 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()方法:

1 public override void Prepare(Viewport viewport)
2 {
3 }
4 

 通过该方法,我们将加入3D网格数据,以创建基本体三棱锥,这里主要由三部分组成:

1.Vertices( 顶点)

2.Lines (线)

3.Face(面)

为了使得结构更清晰,我们把它们分别封装在三函数中:

private void GenerateVertices()  //创建顶点

private void GenerateLines()   //创建线

 private void GenerateFaces()  //创建面

接下来,我们一个个来分别完成,首先是创建顶点的:

 1  private void GenerateVertices()
 2         {
 3             var dimensionAsVector = new Vertex(5f, 5f, 5f);
 4             var halfDimension = new Vertex(2.5f2.5f2.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         }
在balder中的3D点是通过Vertex(x,y,z)对象生成的,其参数代表在所在坐标。前面两行只是实例化了两个Vertex对象,在后面可以通过其的X,Y,Z属性进行初始化三棱锥顶点坐标位置。三棱锥一共有4个顶点,所以FullDetailLevel.AllocateVertices(4);分配了4个顶点。其中的sqt是一个常量,为了控制在空间中的位置,不必理会,你可以自己定义基本体的空间位子。
对于线的函数,与之类似,就不详细介绍,直接看代码:
 1    private void GenerateLines()
 2         {
 3             FullDetailLevel.AllocateLines(6);
 4             FullDetailLevel.SetLine(0new Line(01));
 5             FullDetailLevel.SetLine(1new Line(13));
 6             FullDetailLevel.SetLine(2new Line(02));
 7             FullDetailLevel.SetLine(3new Line(32));
 8             FullDetailLevel.SetLine(4new Line(12));
 9             FullDetailLevel.SetLine(5new Line(03));
10         
11 
12         }

完成这两个函数,我们在 Prepare函数中调用它们,运行后你会看到这样的结果:

 这样一个基本体就创建好了,当然,如果想要看到实体的话,就还需要完成面的组成函数:

 private void GenerateFaces()
        {

            FullDetailLevel.AllocateFaces(
4);
            FullDetailLevel.SetFace(
0new Face(310));
            FullDetailLevel.SetFace(
1new Face(230));
            FullDetailLevel.SetFace(
2new Face(201));
            FullDetailLevel.SetFace(
3new Face(321));
          

        }

 

 

 

 在创建面的时候需要注意,就是顶点的连接顺序,每个面由三个顶点组成的,依次连接它们,在balder中连接顺序是按照顺时针方向的(这和Opengl正好相反),而且是你必须在几何体的外面来观察它。自己画个图形,应该容易理解,弄好后,别忘了加入到Prepare函数,运行,看结果:

 

你会发现,怎么是黑的?主要有两个原因:一是还没有给场景添加灯光照亮,二是需要法向量。balder中提供了一个 GeometryHelper对象,通过它,就可以方便的创建法向量:

在创建好顶点和面后加入:    GeometryHelper.CalculateNormals(FullDetailLevel); 

然后我们在修改xaml文件:

1 <Grid x:Name="LayoutRoot">
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,搞定,看看最后效果:

posted @ 2011-01-17 15:04 Sirk 阅读(...) 评论(...) 编辑 收藏