首页 | 互联网 | IT动态 | IT培训 | Cisco | Windows | Linux | Java | .Net | Oracle | 软件测试 | C/C++ | 嵌入式开发 | 存储世界 | 服务器
网络设备 | IDC | 安全 | 求职招聘 | 数字网校 | 网页设计 | 平面设计 | 技术专题 | 电子书下载 | 教学视频 | 源码下载 | 搜索 | 博客 | 论坛
 您现在的位置: 中国IT实验室 >> 游戏开发 >> 游戏开发文档 >> 正文
分享——Nebula引擎原理技术讲解
来源:ChinaItLab 作者: 时间:2005-4-12


  Nebula是德国一套开源的3d引擎,具体怎样这里不作评价,相关资料可从网上搜索.
  官方网站参见: http://www.radonlabs.de
  使用Nebula也算蛮久了, 为了给网站充数点内容,现在来说说它所用到的一些c++相关技术
  
  如何实现一套与脚本紧密联系的对象管理系统(将在后面给出自己仿照nebula而写的完整可运行的程序):
  
  一.基本的思想:
  1. 程序中所产生的对象用类似于windows操作系统中的目录结构来管理,
  也就是每个对象是一个结点(有对应的名称),每个结点下可以有多个子结点(也有各自对应的名称).如此循环...
  
  2. 程序中有了以上的"目录结构式的对象管理系统", 脚本可通过与程序结合来实现在脚本中调用相应方法来创建
  各目录及对象,并可在脚本中通过相应的目录结构名称来访问每一个对象,以及在各对象之间传递消息.当然也可以通过目录
  结构名来删除对象(包括其目录下的子对象也会自动删除).
  
  3. 有了以上的一切就有了一套与脚本紧密联系的对象管理系统.下面给出一个使用tcl脚本来撰写的例子参考如下
  (这个例子只供参考,具体可实际编译运行通过的例子将在后面详解后给出):
  #--------------------------------------------------------------------------
  # 创建:
  new  nd3d8server   /sys/servers/gfx
  # 访问:
  sel /sys/servers/gfx
     .setdisplaymode "-type(win)-w(800)-h(600)"
     .setclearcolor  0.0 0.0 0.0 0
     .setperspective 45 1.33 1.0 10000.0
  sel ..
  # 删除:
  delete /sys/servers/gfx
  #--------------------------------------------------------------------------
    [说明:]
    前面带"#"号的行表示注释.
    new 是nebula实现的方法, 可以根据给出的字符串参数产生对应的类型对象
    sel 是nebula实现的方法, 可以根据给出的字符串参数选择对应的类型对象, 当参数为".."时表示退到上一层目录
  
  二.具体实现:
  首先我们分析要实现如上的脚本目录对象系统所需要的技术:
  1. 程序中要实现目录结构的对象管理系统.
  2. 要有一套脚本系统,这可以用现成开源的.这里我们选择nebula习惯所用的tcl(当然你可以选择其它)
  3. 程序与脚本结合(交互).
  
  下面我们先分别讨论一下nebula是如何如何实现上述各点的:
  --> 1.先看如何实现第1点:
  a. 首先nebula有一个叫nRoot的类,它是所有对象类的基类,nRoot中有一个名字变量,有一个parent指针指向它的父结点,
  还有一个childlist链表保存它所拥有的子结点.因为结点也是nRoot类,所有结点的子结点中也可能有子结点,
  这样就形成了一个树形目录结构.nRoot中有一个nRoot* Find( const char* name )方法,功能很简单,就是遍历自已的
  childlist链表对比每一个nRoot结点对象的名字,如果相同就返回些对象的指针.
  
  b. 然后nebula还有一个叫nKernelServer的核心管理类,
  1) 一开始nKernelServer就产生了一个全局可见的单件对象(单件就是只有一件,也就是全局唯一,你可以把它想象成一个全局的静态对象)
  2) 这个nKernelServer对象有一个根据类名字符串来创建对象的方法: CheckCreatePath( const char* szClassName, const char *szPath );
  第一个参数是类名字符串,第2个参数就是目录对象名.例如你有一个图形管理类:nGfxServer,你可以创建它的一个对象并起名为"/sys/servers/gfx",
  如: ks->CheckCreatePath( "nGfxServer", "/sys/servers/gfx" );[注:ks即nKernelServer的单件对象]因为传的是类名字符串,所以从脚本中写下:
  new nGfxServer /sys/servers/gfx
  这样的语句时,tcl会把"nGfxServer"字符串返回给nebula的tclcmd_New函数(这个函数是nebula在初始tcl时注册告知tcl的),
  然后tclcmd_New通过调用单件ks的CheckCreatePath( "nGfxServer", "/sys/servers/gfx" );方法来创建了这么一个对象.
  3) 另外nKernelServer中有一个nRoot* Lookup( const char* szPath )的函数, 功能是你传入目录对象名,它会查到并返回对应对象指针.
  4) 当然nKernelServer中还有一个nRoot *cwd变量, 它是用来指向当前目录(或是对象)的,例如,你在脚本中写下:
  sel /sys/servers/gfx
  这样的语句时,tcl分析到sel时就调用nebula告诉它的tclcmd_Sel函数(如何注册函数告知tcl这是我们在后面第2点的内容), 而tclcmd_Sel函数
  会调用上述所说ks->Lookup函数来找到"/sys/servers/gfx"对象的地址,并把它赋给nKernelServer的cwd变量,以后,写下:
  .setdisplaymode "-type(win)-w(800)-h(600)"
  .setclearcolor  0.0 0.0 0.0 0
  .setperspective 45 1.33 1.0 10000.0
  [注意:前面带"."号]
  这时,tcl脚本没有这样的用法,于是它就把这些字符串传给一个叫tclcmd_Unknown的函数,nebula在其中分析字符串,把"."与后面的字符串一一分开,
  并把"."后的第一个字符串(如:"setdisplaymode")作为nKernelServer的cwd所指向的对象的方法来调用,并传给它接着后面的参数
  (如:"-type(win)-w(800)-h(600)").当然要让cwd对象把"setdisplaymode"字符串当成它的函数来调用是比较麻烦的.nebula是如何实现的呢?
  我们将在后面第3点祥细说明:), 说了这么多,现在还是让我们来看看一个实现上述目录对象管理系统的代码:
  [注: 这是我仿nebula写的简单程序,不考虑效率等问题,只作说明用]
  // tnd.cpp : Defines the entry point for the console application.
  //
  
  #include
  #include
  #include
  #pragma warning(disable: 4786)
  using namespace std;
  
  #ifndef MAX_PATH
  # define MAX_PATH 1024
  #endif
  //----------------------------------------------------------------
  class nRoot
  {
  string     m_strName;
  nRoot     *m_pParent;
  vector m_vecChild;
  public:
  nRoot(const char *szName) : m_strName(szName), m_pParent(0){}
  nRoot* Find( const char *szName ){
  for( unsigned int i=0; i  nRoot *pRoot = m_vecChild[i];
  if( 0 == pRoot->m_strName.compare( szName ) ){
  return m_vecChild[i];
  }
  }
  return 0;
  }
  void SetName( const char *szName ){
  m_strName = szName;
  }
  void AddChild( nRoot *pChild ){
  m_vecChild.push_back( pChild );
  }
  };
  //----------------------------------------------------------------
  class nGfxServer : public nRoot
  {
  public:
  nGfxServer(const char *szName) : nRoot(szName){}
  void Test(){
  __asm int 3 // 这里是测试看是否到这里中断(vc下支持的写法,其它编译器请用类似std::cout方法代替)
  }
  };
  //----------------------------------------------------------------
  class nKernelServer
  {
  nRoot *m_pRoot;
  nRoot *m_pCWD;
  nRoot* NewObject( const char *szClassName, const char *szName );
  public:
  nKernelServer(){
  this->m_pRoot = new nRoot("/");
  this->m_pCWD = this->m_pRoot;
  }
  nRoot* CheckCreatePath( const char* szClassName, const char *szPath );
  nRoot* Lookup( const char* szPath );
  void SetCwd( nRoot *o ){
  this->m_pCWD = o ? o : this->m_pRoot;
  }
  };
  static nKernelServer g_ks;
  //----------------------------------------------------------------
  //----------------------------------------------------------------
  nRoot* nKernelServer::CheckCreatePath( const char* szClassName, const char *szPath )
  {
    nRoot* parent = 0;
    nRoot* child = 0;
  if( '/' == szPath[0] ){ // AbsolutePath
  parent = this->m_pRoot;
  }else{
  parent = this->m_pCWD;
  }
  char strBuf[MAX_PATH];
  strcpy(strBuf, szPath);
  char *pNextPathComponent = NULL;
  char *pCurrPathComponent = strtok(strBuf, "/");
    if( pCurrPathComponent )
    {
      // for each directory path component
      while( (pNextPathComponent = strtok(NULL, "/") ))
      {
        child = parent->Find( pCurrPathComponent );
        if (!child)
        {
          child = new nRoot( pCurrPathComponent );
          parent->AddChild( child );
        }
        parent = child;
        pCurrPathComponent = pNextPathComponent;
  }
  }
    // curPathComponent is now name of last path component
    child = parent->Find( pCurrPathComponent );
    if (!child)
    {
      child = (nRoot*) this->NewObject( szClassName, pCurrPathComponent );
【责编:admin】

中国IT教育热线咨询

相关文章
dx8中关于用索引缓冲渲染索引图元
作为一个状态机的OpenGL
OGRE中的四元数与旋转
[RGSS]Sprite类方法教学
[RGSS]去掉“战斗|逃跑”选项
推荐文章

 精彩友情推荐
·Asp源码 PHP源码
·CGI源码 JSP源码
·建站书籍教程
·服务器软件 .net源码
·建站工具软件
·IDC资讯大全
·机房品质万里行
·IDC托管必备知识
·全国IDC报价
·网站推广优化
 基础入门  开发文档
 最新推荐
  多数的Windows程序都需要Windows.h和Windowsx.h这两个头文件,要确保使用它们。当然,你还需要其它......
游戏引擎演化史
在Windows上安装OGRE的方法
关于滤镜遮罩概念,Sobel 遮罩
游戏开发新手入门之Windows编程
游戏开发新手入门之位图化图形
教你实现卡通渲染的另类勾边方法
游戏设计大师谈如何成为一名游戏设
Visual C#编写 3D游戏框架示例
真正的 Java 学习从入门到精通
游戏开发经验——游戏开发的基本常
  为什么要研究攻击行为在人类有记载的5600年的历史中,共计发生了14,400次战争;今天,平均一天要发生............
游戏开发中显示对话的特殊句法
游戏原型设计的介绍
网络游戏中的攻击行为
谈动作类游戏的必要条件
规则的多元分析模式
载入位图文件到DirectDraw
Archer Game Suite 是什么?
浅谈游戏企划-新手入门篇
暴雪称霸游戏业界的六大秘密绝招
骨骼动画及示例Skinned Mesh的解析
  培训中心