ogre manualObject 手动创建mesh

 

以下是ogre中的注释:

Building one-off geometry objects manually usually requires getting down and dirty with the vertex buffer and vertex declaration API, which some people find a steep learning curve. This class gives you a simpler interface specifically for the purpose of building a 3D object simply and quickly. Note that if you intend to instance your object you will still need to become familiar with the  class.
手动建立一次性的几何体对象经常会需要麻烦地用到顶点缓冲和顶点声明API,有些人会感觉遇到急剧上升的学习曲线。这个类给你一个更加简单的界面标准来创建简单快速地创建3D对象。注意如果你尝试实例化你的对象你也需要熟悉 Mesh类。

This class draws heavily on the interface for OpenGL immediate-mode (glBegin, glVertex, glNormal etc), since this is generally well-liked by people. There are a couple of differences in the results though - internally this class still builds hardware buffers which can be re-used, so you can render the resulting object multiple times without re-issuing all the same commands again. Secondly, the rendering is not immediate, it is still queued just like all OGRE objects. This makes this object more efficient than the equivalent GL immediate-mode commands, so it's feasible to use it for large objects if you really want to.
这个类着重实用OpenGL立即模式的界面来绘制(glBegin,glVertexkglNormal,之类),因为它在一般人中间非常流行。然而他们之间还有2个区别-这个类内部建立了可重用的硬件缓冲,因此你可以反复渲染这个对象而不必重复实用构建对象的立即模式指令。再有,渲染不是立即执行的,它也会像其他所有的OGRE对象一样进入渲染队列。这使得这个对象比相应的GL立即模式更加有效。因此,如果你想要用它一个大型的对象也是可行的。

To construct some geometry with this object:
要使用这个对象构建一些几何体:
If you know roughly how many vertices (and indices, if you use them) you're going to submit, call estimateVertexCount and estimateIndexCount. This is not essential but will make the process more efficient by saving memory reallocations.如果你大概知道你将提交多少顶点(和所引,如果你使用的话),调用estimateVertexCount和extimateIndexCount.这不是必要的但是将会通过节约内存分配来使得这个过程更有效率。
Call  to begin entering data 调用begin开始输入数据
For each vertex, call , , ,  to define your vertex data. Note that each time you call  you start a new vertex. Note that the first vertex defines the components of the vertex - you can't add more after that. For example if you didn't call  in the first vertex, you cannot call it in any others. You ought to call the same combination of methods per vertex. 对每个顶点,调用position(),normal(),textureCoord(),colour()来定义你的顶点数据。注意每次你调用position()你就开启了一个新顶点。注意第一组顶点定义指令定义了顶点的结构-你不能再之后的顶点再改变。比如如果你没有在第一个顶点调用normal(),你就不能在其他任何一个顶点上调用它了。你应对每个顶点调用同样的方法组合。
If you want to define triangles (or lines/points) by indexing into the vertex list, you can call  as many times as you need to define them. If you don't do this, the class will assume you want triangles drawn directly as defined by the vertex list, i.e. non-indexed geometry. Note that stencil shadows are only supported on indexed geometry, and that indexed geometry is a little faster; so you should try to use it. 如你你想要通过索引定义三角形(或者线/点),你可以调用index,用多少次调用多少次。如果你你没有调用,这个类就会假定你想要三角形直接按照顶点定义的顺序来绘制,也就是说,非索引的顶点的几何体。注意模板阴影只在所引顶点的几何体上有效,而且所引顶点的几何体要略微快一点;因此你应该尽量使用它。
Call  to finish entering data.调用end()来结束输入数据。
Optionally repeat the begin-end cycle if you want more geometry using different rendering operation types, or different materials After calling , the class will organise the data for that section internally and make it ready to render with. Like any other  you should attach the object to a  to make it visible. Other aspects like the relative render order can be controlled using standard  methods like setRenderQueueGroup.如果你想要更多实用不懂渲染操作类型或者不懂材质的的几何体,也可以反复实用begin-end循环。在调用end()之后,类会为那个段组织数据并且使他准备好被渲染。就像其他MovableObject一样,你应该把这个物体attach到一个SceneNode来使它可见。其他方面像渲染相对顺序可以可以实用标准MovableObject方法一样,诸如setRenderQueueGroup.

You can also use  to alter the geometry later on if you wish. If you do this, you should call setDynamic(true) before your first call to , and also consider using estimateVertexCount / estimateIndexCount if your geometry is going to be growing, to avoid buffer recreation during growth.如果你希望的话 你也可以使用beginUpdate()在之后修改几何体。如果你这么做了,你应该在第一次调用begin之前调用setDynamic(true),并且考虑实用estimateVertexCount/estimateIndexCount如果你的几何体将会增长的话,就可以避免缓冲重建。

Note that like all OGRE geometry, triangles should be specified in anti-clockwise winding order (whether you're doing it with just vertices, or using indexes too). That is to say that the front of the face is the one where the vertices are listed in anti-clockwise order.注意就像所有OGRE几何体一样,三角形应该按照逆时针顺序来制定(不论你是打算只是实用vertices,或者还是实用所引)。也就是说定义唯一的三角形正面的顺序是按照顶点逆时针排列的顺序列出的。

 

程序中创建一个manualObject

在一个可以正常运行的ogre程序里边,找到createscene函数,添加如下代码:

 

//定义对象并设置材质名称与绘制模式

ManualObject* manual = mSceneMgr->createManualObject("manual");

manual->begin("BaseWhiteNoLighting", nderOperation::OT_LINE_STRIP);

       bool test = false;

       if(test)

       {     

           //平面

           //指定定点位置

           manual->position(-100.0, -100.0, 0.0);

           manual->position( 100.0, -100.0, 0.0);

           manual->position( 100.0,  100.0, 0.0);

           manual->position(-100.0,  100.0, 0.0);

           manual->position(0,200.0,0);

//指定索引顺序,就是绘制定点的顺序,如果不指定就一句定点列出的顺序依次绘制        

           manual->index(0);

           manual->index(1);

           manual->index(2);

           manual->index(4);

           manual->index(3);   

           manual->index(0);

          

       }

       else

       {

           //立方体

           //指定定点位置

           manual->position(-100.0, -100.0, 100.0);

           manual->position( 100.0, -100.0, 100.0);

           manual->position( 100.0,  -100.0, -100.0);

           manual->position(-100.0,  -100.0, -100.0);

           manual->position(-100.0,   100.0,100.0);

           manual->position( 100.0,  100.0, 100.0);

           manual->position(100.0,  100.0, -100.0);

           manual->position(-100,100.0,-100);

   //指定索引顺序,就是绘制定点的顺序,如果不指定就一句定点列出的顺序依次绘制

           manual->index(0);

           manual->index(1);

           manual->index(2);

           manual->index(3);

           manual->index(0);   

           manual->index(4);

           manual->index(5);

           manual->index(6);

           manual->index(7);

           manual->index(4);

           manual->index(7);

           manual->index(3);

           manual->index(2);

           manual->index(6);

           manual->index(5);

           manual->index(1);

       }

 

       manual->end(); //结束定点设置。这里的begin和end对应于d3d中读写定点缓存时的loack 与 unlock !

       //将手动对象创建为mesh

       manual->convertToMesh("testMesh");

       Entity * tempEntity = SceneMgr->createEntity("cube","testMesh");

mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(tempEntity);

 

//也可以不创建mesh,直接将对象挂在节点也是可以显示的
mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(manual)

 

绘制模式参数设置参看参看

 

http://www.ogre3d.org/wiki/index.php/ManualObject

 

Ogre手动创建mesh(N个submesh)

 

Mesh与submesh以及创建submesh中数据项之间的关系如下:

 

 

下面是代码示例:

 

在程序中加入如下2个函数:

 

//为mesh创建2个submesh,并填充submesh的数据。

void createColourCube()

    {

       /// 从mesh管理器中创建mesh

    Ogre::MeshPtr msh = MeshManager::getSingleton().createManual("ColourCube", "General");

 

       //mesh包含2个子实体

       SubMesh * sub1 = msh->createSubMesh("2");

       SubMesh * sub2 = msh->createSubMesh("1");

       //分别为个子实体填充数据

        fillSubMesh(sub1,1); //fill函数在后边定义

         fillSubMesh(sub2,2);

 

 

       /// Set bounding information (for culling)

       msh->_setBounds(AxisAlignedBox(-100,-100,-100,100,100,100));

       msh->_setBoundingSphereRadius(Math::Sqrt(3*100*100));

       /// Notify Mesh object that it has been loaded

       msh->load();

    }

    //填充顶点的所需要的信息,并写入缓存

    void fillSubMesh(SubMesh * submeshPtr, int i)

    {

       //填充子实体所需的数据项

       //法线

       const float sqrt13 = 0.577350269f; /* sqrt(1/3) */

           /// Define the vertices (8 vertices, each consisting of 2 groups of 3 floats

       const size_t nVertices = 8;

       const size_t vbufCount = 3*2*nVertices;

       float vertices[vbufCount] = {

           -100.0,100.0,-100.0,        //0 position

           -sqrt13,sqrt13,-sqrt13,     //0 normal

           100.0,100.0,-100.0,         //1 position

           sqrt13,sqrt13,-sqrt13,      //1 normal

           100.0,-100.0,-100.0,        //2 position

           sqrt13,-sqrt13,-sqrt13,     //2 normal

           -100.0,-100.0,-100.0,       //3 position

           -sqrt13,-sqrt13,-sqrt13,    //3 normal

           -100.0,100.0,100.0,         //4 position

           -sqrt13,sqrt13,sqrt13,      //4 normal

           100.0,100.0,100.0,          //5 position

           sqrt13,sqrt13,sqrt13,       //5 normal

           100.0,-100.0,100.0,         //6 position

           sqrt13,-sqrt13,sqrt13,      //6 normal

           -100.0,-100.0,100.0,        //7 position

           -sqrt13,-sqrt13,sqrt13,     //7 normal

       };

 

       float vertices2[vbufCount] = {

           200.0,100.0,-100.0,        //0 position

           -sqrt13,sqrt13,-sqrt13,     //0 normal

           400.0,100.0,-100.0,         //1 position

           sqrt13,sqrt13,-sqrt13,      //1 normal

           400.0,-100.0,-100.0,        //2 position

           sqrt13,-sqrt13,-sqrt13,     //2 normal

           200.0,-100.0,-100.0,       //3 position

           -sqrt13,-sqrt13,-sqrt13,    //3 normal

           200.0,100.0,100.0,         //4 position

           -sqrt13,sqrt13,sqrt13,      //4 normal

           400.0,100.0,100.0,          //5 position

           sqrt13,sqrt13,sqrt13,       //5 normal

           400.0,-100.0,100.0,         //6 position

           sqrt13,-sqrt13,sqrt13,      //6 normal

           200.0,-100.0,100.0,        //7 position

           -sqrt13,-sqrt13,sqrt13,     //7 normal

       };

 

       //给每个点点设置颜色

       RenderSystem* rs = Root::getSingleton().getRenderSystem();

       RGBA colours[nVertices];

       RGBA *pColour = colours;

       // Use render system to convert colour value since colour packing varies

rs->convertColourValue(ColourValue(1.0,0.0,0.0), pColour++); //0 colour

           rs->convertColourValue(ColourValue(1.0,1.0,0.0), pColour++); //1 colour

       rs->convertColourValue(ColourValue(0.0,1.0,0.0), pColour++); //2 colour

       rs->convertColourValue(ColourValue(0.0,0.0,0.0), pColour++); //3 colour

       rs->convertColourValue(ColourValue(1.0,0.0,1.0), pColour++); //4 colour

       rs->convertColourValue(ColourValue(1.0,1.0,1.0), pColour++); //5 colour

       rs->convertColourValue(ColourValue(0.0,1.0,1.0), pColour++); //6 colour

       rs->convertColourValue(ColourValue(0.0,0.0,1.0), pColour++); //7 colour

 

       /// 定义个面所需要的个三角形的索引顺序

       const size_t ibufCount = 36;

       unsigned short faces[ibufCount] = {

           0,2,3,

           0,1,2,

           1,6,2,

           1,5,6,

           4,6,5,

           4,7,6,

           0,7,4,

           0,3,7,

           0,5,1,

           0,4,5,

           2,7,3,

           2,6,7

       };

 

      

      

      

      

      

         /// 为子实体创建存储定点数据的空间以及指定顶点的数量

           submeshPtr->vertexData = new VertexData();

           submeshPtr->vertexData->vertexCount = nVertices;

 

           // Create declaration (memory format) of vertex data

           //指定顶点使用的格式    

 VertexDeclaration*    decl = submeshPtr->vertexData->vertexDeclaration;

           size_t offset = 0;

           // 1st buffer

           //写入顶点坐标数据信息

           decl->addElement(0, offset, VET_FLOAT3, VES_POSITION);

           offset += VertexElement::getTypeSize(VET_FLOAT3);

           decl->addElement(0, offset, VET_FLOAT3, VES_NORMAL);

           offset += VertexElement::getTypeSize(VET_FLOAT3);

              /// Allocate vertex buffer of the requested number of vertices (vertexCount)

           /// and bytes per vertex (offset) 

           //分配顶点所需要的硬件缓冲 

           HardwareVertexBufferSharedPtr vbuf =

              HardwareBufferManager::getSingleton().createVertexBuffer(

                    offset, submeshPtr->vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY);

           /// Upload the vertex data to the card

           //将数据写入缓存

 

       if(i == 1)

       {

           vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true);     //将顶点信息写入缓存

       }

       if(i == 2)

       {

           vbuf->writeData(0, vbuf->getSizeInBytes(), vertices2, true);     //将顶点信息写入缓存

 

       }

      

 

       /// Set vertex buffer binding so buffer 0 is bound to our vertex buffer

        VertexBufferBinding* bind = submeshPtr->vertexData->vertexBufferBinding;

        bind->setBinding(0, vbuf);

 

      

 

 

       //顶点颜色缓存创建

       offset = 0;

   

    decl->addElement(1, offset, VET_COLOUR, VES_DIFFUSE);

       offset += VertexElement::getTypeSize(VET_COLOUR);

       /// Allocate vertex buffer of the requested number of vertices (vertexCount)

       /// and bytes per vertex (offset)

       vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(

           offset, submeshPtr->vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY);

       /// Upload the vertex data to the card

       vbuf->writeData(0, vbuf->getSizeInBytes(), colours, true);

       /// Set vertex buffer binding so buffer 1 is bound to our colour buffer

       bind->setBinding(1, vbuf);

 

       //创建索引缓存并写入

       /// Allocate index buffer of the requested number of vertices (ibufCount)

       HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().createIndexBuffer(                                 HardwareIndexBuffer::IT_16BIT,                                        ibufCount,                                          

                  HardwareBuffer::HBU_STATIC_WRITE_ONLY);

// Upload the index data to the card     

ibuf->writeData(0, ibuf->getSizeInBytes(), faces, true);

// Set parameters of the submesh      

       submeshPtr->useSharedVertices = false;

       submeshPtr->indexData->indexBuffer = ibuf;

       submeshPtr->indexData->indexCount = ibufCount;

       submeshPtr->indexData->indexStart = 0;

   

}

 

 

 

然后在createscene函数中加入如下代码:

createColourCube();//创建数据

 

Entity* thisEntity = mSceneMgr->createEntity("cc", "ColourCube");

        thisEntity->getSubEntity("1")->setMaterialName("Test/ColourTest");

 

thisEntity->getSubEntity("2")->setMaterialName("Test/ColourTest");

SceneNode* thisSceneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();

       thisSceneNode->setPosition(-35, 0, 0);

       thisSceneNode->attachObject(thisEntity);

 

然后再将下面的材质脚本加入到ogre的General资源组中:

 

material Test/ColourTest

{

    technique

    {

        pass

        {

            ambient vertexcolour

        }

    }

}

之后编译运行,你可以看到有2个彩色的立方体在摄像机前面。下面给出过程总结:

1.  从mesh创建submesh。

2.  为submesh的各个数据结构分配空间并设置。

主要有如下几项:vertexdata,indexdata.

3.  为vertexdata指定顶点格式以及为其分配硬件缓存并与之绑定。

4.  分配indexdata的硬件空间和colorvalue的硬件空间。

5.  分别将对应的vertexdata,indexdata,colorvalue写入对应的缓存。

6.  之后做一些设置。如果没有使用mesh的共享缓存,则要关闭submesh的使用共享缓存设置。

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值