Irrlicht学习之载入irr文件和自定义场景节点
在上一篇文章中,我尝试载入了Irrlicht自定义的场景文件irr文件。这回我将尝试用代码将irr文件载入以及自定义场景节点绘制出坐标轴。
Irr文件实质上是一个XML文件,它里面包含了场景的各种资源,可以被引擎中的一个模块IrrXML进行读取,生成则主要由IrrEdit来完成。
演示程序和源代码下载地址:这里
首先是演示程序截图:
程序中载入了一个irr文件的场景、创建了XYZ轴,最后读取了sydney角色。整个场景中没有用到光照,所以场景中的颜色是其本原色。
载入irr场景非常简单。在获得了ISceneManager的指针后,可以通过调用
virtual bool irr::scene::ISceneManager::loadScene (const io::path& filename, ISceneUserDataSerializer* userDataSerializer = 0)
来载入irr场景。下面介绍一下如何自定义场景节点。
首先需要定义一个自定义类,继承于ISceneNode类,随后重载OnRegisterSceneNode()、render()、getBoundingBox()、getMaterialCount()、getMaterial()这几个虚函数。这里需要注意一下,哪怕场景节点是像坐标轴那样只有颜色,几乎没有什么材质纹理的,我们重载getMaterialCount()、getMaterial()时也要返回1和一个材质。否则会导致其颜色成为全局光的颜色以及深度值错乱等等现象。我在Irrlicht论坛上提问了,最后还是自己解决的。下面是自定义坐标轴类的源代码:
#ifndef _AXISNODE_H_
#define _AXISNODE_H_
#include <ISceneNode.h>
class AxisNode: public ISceneNode
{
public:
AxisNode( ISceneNode* pParent, ISceneManager* pMgr, s32 id ):
ISceneNode( pParent,pMgr, id )
{
const f32 length = 40.0f;
vertices[0] =S3DVertex(
0, 0, 0, // 位置
0, 1, 0, // 法线
SColor( 255, 255,0, 0 ), // 颜色
0, 0 ); // 纹理坐标
vertices[1] =S3DVertex(
length, 0, 0, // 位置
0, 1, 0, // 法线
SColor( 255, 255,0, 0 ), // 颜色
0, 0 ); // 纹理坐标
vertices[2] =S3DVertex(
0, 0, 0, // 位置
0, 1, 0, // 法线
SColor( 255, 0, 255,0 ), // 颜色
0, 0 ); // 纹理坐标
vertices[3] =S3DVertex(
0, length, 0, // 位置
0, 1, 0, // 法线
SColor( 255, 0,255, 0 ), // 颜色
0, 0 ); // 纹理坐标
vertices[4] =S3DVertex(
0, 0, 0, // 位置
0, 1, 0, // 法线
SColor( 255, 0, 0,255 ), // 颜色
0, 0 ); // 纹理坐标
vertices[5] =S3DVertex(
0, 0, length, // 位置
0, 1, 0, // 法线
SColor( 255, 0, 0,255 ), // 颜色
0, 0 ); // 纹理坐标
// 添加到碰撞盒中
box.reset(vertices[0].Pos );
for ( s32 i = 1; i < 6; ++i )box.addInternalPoint( vertices[i].Pos );
// 新添加坐标文字
SceneManager->addTextSceneNode(
SceneManager->getGUIEnvironment( )->getSkin( )->getFont( ), // 字体
L"x", // 文字
SColor( 255, 255, 0, 0 ), // 颜色
this, // 父节点
vector3df( length,0.0f, 0.0f ),// 相对位置
-1 ); //ID号
SceneManager->addTextSceneNode(
SceneManager->getGUIEnvironment( )->getSkin( )->getFont( ), // 字体
L"y", // 文字
SColor( 255, 0, 255, 0 ), // 颜色
this, // 父节点
vector3df( 0.0f,length, 0.0f ),// 相对位置
-1 ); //ID号
SceneManager->addTextSceneNode(
SceneManager->getGUIEnvironment( )->getSkin( )->getFont( ), // 字体
L"z", // 文字
SColor( 255, 0, 0,255 ), // 颜色
this, // 父节点
vector3df( 0.0f,0.0f, length ),// 相对位置
-1 ); //ID号
}
virtualvoid OnRegisterSceneNode()
{
if ( IsVisible )
SceneManager->registerNodeForRendering( this);
ISceneNode::OnRegisterSceneNode( );
}
virtualvoid render( void)
{
static u16 indices[ ] = { 0, 1, 2, 3, 4, 5 };
IVideoDriver* pDriver= SceneManager->getVideoDriver( );
pDriver->setMaterial( getMaterial( 0 ) );
pDriver->setTransform(video::ETS_WORLD, AbsoluteTransformation );// 设置矩阵变换
pDriver->drawVertexPrimitiveList(
&vertices[0], // 顶点数组的首地址
6, // 顶点数目
&indices[0], // 索引数组的首地址
3, // 图元数目
EVT_STANDARD, // 顶点的种类
EPT_LINES, // 图元形状
EIT_16BIT ); // 索引位大小
}
virtualconst core::aabbox3d<f32>&getBoundingBox( void ) const
{
return box;
}
virtualu32 getMaterialCount( void ) const
{
return 1;
}
virtualvideo::SMaterial& getMaterial( u32 i )
{
static SMaterial dummyMaterial;
return dummyMaterial;
}
private:
S3DVertex vertices[6];
core::aabbox3d<f32> box;
};
#endif