OGRE
1.12.13
Object-Oriented Graphics Rendering Engine
|
There are two ways to create your own mesh. The first way is to create a Ogre::Mesh instance and provide it with the vertex and index buffers directly.
The second way is the high level Ogre::ManualObject interface. Instead of filling position and color buffers, you simply call the "position" and "colour" functions.
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 Mesh class.
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.
To construct some geometry with this object:
You can also use beginUpdate() to alter the geometry later on if you wish. If you do this, you should call setDynamic(true) before your first call to begin(), and also consider using estimateVertexCount() / estimateIndexCount() if your geometry is going to be growing, to avoid buffer recreation during growth.
We will use the ManualObject to create a single textured plane. After creating the object, we start a new geometry block that will use the given material
Next we specify the vertices of the plane
Now we can define the face. Ogre will split the quad into triangles for us.
Calling end()
creates the actual Hardware Buffers to be used for rendering and we can attach the Object to a Ogre::SceneNode.
In case you need multiple Ogre::Entities of the plane, you should call Ogre::ManualObject::convertToMesh first and then use Ogre::SceneManager::createEntity as usual.
This time we are going to create a plane using the lower level Ogre::HardwareBuffer primitives.
We start by creating a Mesh object. As this is a manual Mesh, we have to set the bounds of it explicitly.
Next we define what should end up in our vertex and index buffer. We will store all data interleaved in one buffer. This typically has some advantages due to cache coherency and also is what ManualObject does automatically for us.
However we could also split the data into multiple buffers with lower precision to save some bytes on texture coordinates and normals.
To describe the vertex sources, we have to create a Ogre::VertexData object. Notably it stores how many vertices we have.
The actual description of our vertex buffer however is stored inside the Ogre::VertexDeclaration.
Now we can continue to create the Hardware Buffers and upload our data.
Note how we used the symbolical constant 0
to link the Ogre::HardwareVertexBuffer to the Ogre::VertexDeclaration. This allows the underlying RenderSystem to swap VertexBuffers without changing the VertexDeclaration. i.e. render different Meshes that share the same vertex layout, without changing the state.
Finally we create the Ogre::SubMesh that will be ultimately rendered.
Note that while our VertexBuffer is shared, the IndexBuffer is not. This allows rendering different faces of the same object using different Materials. Here, each SubMesh links the faces (IndexBuffer) to the according material.
Finally, we have to update the loading state of the mesh as
If you have registered a Ogre::ManualResourceLoader, the resource loading would only happen now.