Irrlicht引擎手册示例(三):CustomSceneNode!


教程 3.CustomSceneNode

 

 

本教程的难度将会提高,所以如果你还没有相关的知识的话,请先阅读前面的教程。本教程将演示如何创建一个自定义场景节点,以及如何在引擎中使用如果你想实现Irrlicht引擎目前不支持的渲染技术的话,自定义场景节点是必要的例如你可以自己写一个基于室内渲染器一个先进的地形场景节点创建自定义场景节点你可以很容易地扩展Irrlicht引擎使其适应您的需求

我会继续让本教程简单易懂些:讲解尽可能简单明了些尽可能写在一个cpp文件,并在所有其他教程里将像这里一样使用引擎本教程结束后,结果将如下图所示这个看起来不是很美观,它提供了一个完整定制场景节点并且作为创建自己的场景节点是一个不错的开始

Irrlicht引擎手册示例(三):CustomSceneNode!_第1张图片


 

让我们开始吧!
 
 

首先,我包含头文件使用IRR命名空间告诉链接器链接lib文件

#include <irrlicht.h>
using namespace irr;
#pragma comment(lib, "Irrlicht.lib")

 

这里谈到了本教程的复杂部分我们定义场景节点为了保持简单
我们场景节点将不会是室内渲染器或者地形场景节点,而是一个简单的四面体,它由4连接顶点组成的三维对象,它只负责画自己外不做其它事
 
class CSampleSceneNode : public scene::ISceneNode
{

首先,我们声明一些成员变量用来保存四面体的数据:包围盒4个顶点四面体的材质

core::aabbox3d<f32> Box;
video::S3DVertex Vertices[4];
video::SMaterial Material;


构造函数的参数包含了场景节点场景管理指针场景节点ID在构造函数本身,我们调用父类的构造函数,设置我们用来绘制场景节点所使用的材质,并创建我们等下要画出来的4个顶点

public:
CSampleSceneNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id)
 : scene::ISceneNode(parent, mgr, id)
{ 
  Material.Wireframe = false;
  Material.Lighting = false;
  Vertices[0] = video::S3DVertex(0,0,10, 1,1,0,video::SColor(255,0,255,255),0,1);
  Vertices[1] = video::S3DVertex(10,0,-10, 1,0,0,video::SColor(255,255,0,255),1,1); 
  Vertices[2] = video::S3DVertex(0,20,0, 0,1,1,video::SColor(255,255,255,0),1,0);
  Vertices[3] = video::S3DVertex(-10,0,-10, 0,0,1,video::SColor(255,0,255,0),0,0);


Irrlicht引擎需要知道你的场景节点包围盒它会用自动裁剪和其他东西因此我们需要通过4个顶点创建包围盒如果你不想引擎使用自动裁剪或者你不想创建包围盒也可以这样写

AutomaticCullingEnabled = false;.

   Box.reset(Vertices[0].Pos); 
   for (s32 i=1; i<4; ++i) 			
       Box.addInternalPoint(Vertices[i].Pos);
}


在画出之前,场景管理器调用在场景中的每个场景节点的方法OnPreRender() 。如果场景节点想要把自己画出来,那么我们应该在场景管理器调用::render 方法之前,先在场景管理器当中注册一下,。 一般的场景节点都是一个一个的把它们的内容渲染出来,而后开始渲染模板缓冲阴影,并且相机或灯光场景节点需要在所有之前被渲染。这里我们只简单的注册下用来只提供一般的渲染,如果我们希望它像相机或灯光一样被渲染出来,我们可以这样写SceneManager->registerNodeForRendering(this, SNRT_LIGHT_AND_CAMERA);

在此之后,我们调用基类ISceneNode的OnPreRender方法这样就所有的子场景节点注册一下了。

 

virtual void OnPreRender()
{  
  if (IsVisible)    
     SceneManager->registerNodeForRendering(this);

  ISceneNode::OnPreRender();
}

在render() 方法里面执行了一些有趣的东西:场景节点的渲染我们重写此方法画出四面体

virtual void render()
{  
  u16 indices[] = { 0,2,3, 2,1,3, 1,0,3, 2,0,1 };
  video::IVideoDriver* driver = SceneManager->getVideoDriver();
  driver->setMaterial(Material);
  driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
  driver->drawIndexedTriangleList(&Vertices[0], 4, &indices[0], 4);
}


至少,我们创建了三个小的额外方法。GetBoundingBox()返回这个场景节点的包围盒,GetMaterialCount()返回在这个场景节点的材质数(我们四面体只有一种材质),getMaterial()返回指定索引的材质。因为我们只有一个材质,我们可以返回只有一个,如果不只一个的话,我们可以通过索引来指定哪个。

virtual const core::aabbox3d<f32>& getBoundingBox() const  
{    
   return Box;  
}
  virtual u32 getMaterialCount()
  {
    return 1;
  }
  virtual video::SMaterial& getMaterial(u32 i)
  {
    return Material;
  } 
};

 


就是这样场景节点完成。现在我们只需启动引擎创建场景节点和一个摄像头看看结果

int main()
{
  IrrlichtDevice *device =
       createDevice(video::EDT_OPENGL, core::dimension2d<s32>(640, 480), 16, false);
  device->setWindowCaption(L"Custom Scene Node - Irrlicht Engine Demo");
  video::IVideoDriver* driver = device->getVideoDriver();
  scene::ISceneManager* smgr = device->getSceneManager();
  smgr->addCameraSceneNode(0, core::vector3df(0,-40,0), core::vector3df(0,0,0));



 

 

创建我们的场景节点。请注意,创建后不要立刻调用drop()函数。因为有可能场景管理器正在使用它。我们可以在程序执行完后在把它删除掉。


CSampleSceneNode *myNode =   new CSampleSceneNode(smgr->getRootSceneNode(), smgr, 666);
//**执行的程序**//
myNode->drop();


现在我们让这个四面体动下并显示出来现在可以像使用引擎的其他场景节点一样使用您自定义的场景节点,我们添加一个动画场景节点来让我们的四面体旋转

scene::ISceneNodeAnimator* anim =    smgr->createRotationAnimator(core::vector3df(0.8f, 0, 0.8f));

myNode->addAnimator(anim);
anim->drop();


现在画出所有东西,并完成

  while(device->run()) 
  {    
    driver->beginScene(true, true, video::SColor(0,100,100,100));

    smgr->drawAll();

    driver->endScene();
  }

device->drop();
return 0;
}

好了,编译并试下这个程序。

你可能感兴趣的:(vector,video,Class,扩展,引擎)