zoukankan      html  css  js  c++  java
  • 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,搞定,看看最后效果:

  • 相关阅读:
    模仿商品分类点击效果
    Element MenuNav刷新后点击菜单保留选中状态
    element后端管理布局
    Element NavMenu动态生成导航菜单
    谁的速度快!谁背锅(技术解析)
    “非科班自学”复盘两个月时间在年底成功拿下了字节、阿里offer,入职了字节!
    用了这么久,你真的明白 HttpClient的实现原理了吗?
    求你了,不要再在对外接口中使用枚举类型了
    Docker 实战总结(非常全面),收藏了!
    Service层和Dao层真的有必要每个类都加上接口吗?
  • 原文地址:https://www.cnblogs.com/vimsk/p/1937379.html
Copyright © 2011-2022 走看看