用Ogre画三角形

用Ogre画三角形

         成熟图像引擎往往对底层操作做了层层封装,用户或许能轻易地将复杂模型加入到游戏里,却在画一个三角形时摸不着头脑。本文阐述如何在Ogre里画三角形,如果有些许DirectX或者OpenGL的基础知识,理解起来会更加容易。

         Ogre用树结构来组织场景,所有希望被遍历到的实体都需要挂接在树节点下,此类有挂接能力的实体需要继承自MovableObject类;而如果实体想被赋予渲染的能力,则要继承Renderable类。如此一来,我们的三角形类如下:

class Triangle : public Ogre::MovableObject, public Ogre::Renderable

         接下来要做的基本上就是填充两个父类中的十多个纯虚方法,这里我们仅挑出最主要的几个进行说明。

         1. 来自MovableObject的_updateRenderQueue()函数。它在场景遍历到本实体时被调用,你可以选择此时将待渲染的对象加入到渲染队列中,由于我们的三角形本身即继承自Renderable,所以我们将自己加入到队列里:

void Triangle::_updateRenderQueue(Ogre::RenderQueue* queue)
{
	queue->addRenderable(this);
}

         2. 接着是来自Renderable的getRenderOperation()函数。它在渲染队列稍后遍历每一个待渲单位时被调用,你需要选择这个时刻把渲染相关的数据(顶点数据、组织方式、数目、索引等等)以RenderOperation数据结构的形式提交给引擎。可见RenderOperation决定了你将渲染出何种东西,其实本文展示的核心即是对RenderOperation的定制。

         我们在初始化三角形时构建RenderOperation相关数据:

void Triangle::_createBuffers()
{
	// 三角形的三个顶点位置数据
	float vertices[3][3] = {
		-1.0f, 1.0f, 0.0f,	// 0 position
		1.0f, 1.0f, 0.0f,	// 1 position
		0.0f, -1.0f, 0.0f,	// 2 position
	};

	// 顶点颜色
	Ogre::RenderSystem* rs = Ogre::Root::getSingleton().getRenderSystem();
	Ogre::RGBA colours[3];
	rs->convertColourValue(Ogre::ColourValue(1.0f, 0.0f, 0.0f), &colours[0]);	// 0 colour
	rs->convertColourValue(Ogre::ColourValue(0.0f, 1.0f, 0.0f), &colours[1]);	// 1 colour
	rs->convertColourValue(Ogre::ColourValue(0.0f, 0.0f, 1.0f), &colours[2]);	// 2 colour

	// 顶点索引
	Ogre::ushort faces[3] = {
		0, 1, 2,	// 0 face
	};

	// 创建VertexData对象管理顶点数据
	mVertexData = new Ogre::VertexData();
	mVertexData->vertexStart = 0;
	mVertexData->vertexCount = 3;

	Ogre::VertexDeclaration* decl = mVertexData->vertexDeclaration;
	Ogre::VertexBufferBinding* binding = mVertexData->vertexBufferBinding;

	// 设置顶点声明,我们的顶点声明仅有一个数据流且只包含位置、颜色
	size_t offset = 0;
	decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
	offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
	decl->addElement(0, offset, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE);
	offset += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR);

	// 创建顶点缓存并将顶点数据填充进去
	Ogre::HardwareVertexBufferSharedPtr vertexBuffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
		decl->getVertexSize(0), 3,
		Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
	float* lockPtr = static_cast<float*>(vertexBuffer->lock(0, vertexBuffer->getSizeInBytes(), Ogre::HardwareBuffer::HBL_DISCARD));
	Ogre::RGBA* pCol;
	for (int i = 0; i < 3; ++i)
	{
		*lockPtr++ = vertices[i][0];
		*lockPtr++ = vertices[i][1];
		*lockPtr++ = vertices[i][2];
		pCol = static_cast<Ogre::RGBA*>(static_cast<void*>(lockPtr));
		*pCol++ = colours[i];
		lockPtr = static_cast<float*>(static_cast<void*>(pCol));
	}
	vertexBuffer->unlock();

	// 将顶点缓存绑定到0号数据流
	binding->setBinding(0, vertexBuffer);

	// 创建IndexData对象管理顶点索引
	mIndexData = new Ogre::IndexData();
	mIndexData->indexStart = 0;
	mIndexData->indexCount = 3;
	
	// 创建顶点索引缓存并填充数据
	mIndexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
		Ogre::HardwareIndexBuffer::IT_16BIT,
		mIndexData->indexCount,
		Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
	mIndexData->indexBuffer->writeData(0, mIndexData->indexBuffer->getSizeInBytes(), faces, true);

	// 设置包围盒
	mAABB.merge(Ogre::Vector3(vertices[0][1], vertices[0][2], vertices[0][3]));
	mAABB.merge(Ogre::Vector3(vertices[1][1], vertices[1][2], vertices[1][3]));
	mAABB.merge(Ogre::Vector3(vertices[2][1], vertices[2][2], vertices[2][3]));
	mBoundingRadius = Ogre::Math::boundingRadiusFromAABB(mAABB);
}

         然后在getRenderOperation()函数中将其提交上去:

void Triangle::getRenderOperation(Ogre::RenderOperation& op)
{
	op.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;
	op.useIndexes = true;
	op.vertexData = mVertexData;
	op.indexData = mIndexData;
}

         3. 最后还需要提一下来自Renderable的getMaterial()函数,顾名思义,引擎籍此获知待渲物体的材质,这里我们创建一个只使用物体顶点色的材质:

	Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create("TriangleMaterial", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
	material->getTechnique(0)->getPass(0)->setLightingEnabled(false);
	material->getTechnique(0)->getPass(0)->setCullingMode(Ogre::CULL_NONE);

         之后这个材质将通过setMaterialName()函数赋给三角形以供其渲染时刻提交。

         完成了以上步骤,在主构建函数里进行如下调用:

	Ogre::SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode("TriangleNode");
	mTriangle = new Triangle();
	mTriangle->setMaterialName("TriangleMaterial");
	node->attachObject(mTriangle);

         运行程序,你将看到一枚彩色的三角形。

 Ogre Triangle

         某种程度上,在3D世界里,学会了画三角形,你就学会了画任何东西。

         文章配套工程源码可移步此处下载:http://download.csdn.net/source/3562886,开发环境为VS2008+ Ogre1.7.3。

 

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值