History: ManualObject
Source of version: 28
Copy to clipboard
{img src=img/wiki_up/ManualObject.png imalign=center align=right stylebox=border max=400 rel=box}
Using a ManualObject you don't need to load ressources and it's nice to create dynamic objects or simple ones.
To do so, you define the needed points (((-Vertex|vertices))), rendering type (points, lines, surfaces) and assign a ((-Material|material)). To add it to the ((-Scene|scene)), it has to be attached to a ((-SceneNode|SceneNode)) (e.g. the ((-RootSceneNode|RootSceneNode))).
It's possible to add several code blocks {SUB()}''begin(), ...add content..., end()''{SUB} to the one ManualObject. So you can use different materials and rendering types. As a result you can get lines, surfaces or a combination of it. Transparency is also possible (by use of materials with transparency property).
If several instances (copies) of a ManualObject are needed, you have to create a ((-Mesh|Mesh)) from it by use of ''ManualObject::convertToMesh()''. When you load such a Mesh to your scene, it becomes an ((-Entity|Entity)). An other advantage of the ToMesh conversion is, that you can apply different materials to the same shape.
In some cases the ''identity projection'' can be interesting. With this the coordinates are in 2D screen space of the current camera. Useful for ((-Overlay|overlay)) rendering.
!!Examples
!!!Example 1
A very minimal example that creates a __line__ in 3D space.
{CODE(wrap="1", colors="c++")}
// create ManualObject
ManualObject* manual = mSceneMgr->createManualObject("manual");
// specify the material (by name) and rendering type
manual->begin("BaseWhiteNoLighting", RenderOperation::OT_LINE_LIST);
// define start and end point
manual->position(-100, -100, -100);
manual->position(100, 100, 100);
// tell Ogre, your definition has finished
manual->end();
// add ManualObject to the RootSceneNode (so it will be visible)
mSceneMgr->getRootSceneNode()->attachObject(manual);
{CODE}
%%%
!!!Example 2
This example gives an outlined __square__ (or quad):
{CODE(wrap="1", colors="c++")}
ManualObject* manual = mSceneMgr->createManualObject("manual");
manual->begin("BaseWhiteNoLighting", RenderOperation::OT_LINE_STRIP);
manual->position(-100.0, -100.0, 0.0); // start position
manual->position( 100.0, -100.0, 0.0); // draw first line
manual->position( 100.0, 100.0, 0.0);
manual->position(-100.0, 100.0, 0.0);
manual->position(-100.0, -100.0, 0.0); // draw fourth line
manual->end();
mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(manual);
{CODE}
%%%
!!!Example 3
This example is similar to the previous one, but uses __indexes__.
Differences:
* Vertex positions and the usage order are defined seperatly
* Vertex positions can be updated (changed) later without re-build of the whole ManualObject
* Index definitions are needed if you want to create a ((-Mesh|Mesh)) out of the ManualObject
{CODE(wrap="1", colors="c++")}
ManualObject* manual = mSceneMgr->createManualObject("manual");
manual->begin("BaseWhiteNoLighting", RenderOperation::OT_LINE_STRIP);
// define vertex position of index 0..3
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);
// define usage of vertices by refering to the indexes
manual->index(0);
manual->index(1);
manual->index(2);
manual->index(3);
manual->index(0);
manual->end();
mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(manual);{CODE}
%%%
!!!Advanced operations
When you want to __move, rotate, scale__ or make temporarily __invisible__ the ManualObject, attach it to a dedicated SceneNode.
Then you can apply the wanted operations to its SceneNode.
Here you see an example for moving:
{CODE(wrap="1", colors="c++")}
SceneNode mySceneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("mySceneNode");
// attach ManualObject
mySceneNode->attachObject(manual);
// move it
mySceneNode->setPosition(0, 10, 0);
{CODE}
If you want to clamp the ManualObject to a movable object (e.g. a vehicle), just attach the ManualObject (or its dedicated SceneNode) to the SceneNode of the movable object.
%%%
!!Rendering Types
enum Ogre::RenderOperation::OperationType
|| OT_POINT_LIST | A list of points | 1 vertex per point
OT_LINE_LIST | A list of lines | 2 vertices per line
OT_LINE_STRIP | A strip of connected lines | 1 start vertex and 1 vertex per line
OT_TRIANGLE_LIST | A list of triangles | 3 vertices per triangle
OT_TRIANGLE_STRIP | A strip of triangles | 3 vertices for the first triangle and 1 per triangle after that
OT_TRIANGLE_FAN | A fan of triangles | 3 vertices for the first triangle and 1 per triangle after that
||
%%%
{img fileId="1947" thumb="y" align="right" stylebox="border"}
__Triangle Strip:__
A triangle strip is a series of connected triangles, sharing vertices, allowing for faster rendering and more efficient memory usage. They are optimized on most graphics cards, making them the most efficient way of describing an object.
More details you find in this [http://en.wikipedia.org/wiki/Triangle_strip|Wikipedia page].
{img fileId="1948" thumb="y" align="right" stylebox="border"}
__Triangle Fan:__
A triangle fan describes a set of connected triangles that share one central vertex.
More details you find in this [http://en.wikipedia.org/wiki/Triangle_fan|Wikipedia page].
Using a ''triangle strip'' or ''triangle fan'' you need just N+2 vertices for describing N triangles (instead of 3N as for seperately defined triangles).
__Points:__
The size of one point is 1 pixel, independent of its distance to the camera. The point size can be changed by the ((-material|material)) settings. Use [http://www.ogre3d.org/docs/api/html/classOgre_1_1Material.html#a8c26b7ccb050d96cd031db31bf996b48|Material::setPointSize()] for the whole material or more differentiated [http://www.ogre3d.org/docs/api/html/classOgre_1_1Technique.html#a1b7d1d264b34c50b7606c646415a50e8|Technique::setPointSize()] or [http://www.ogre3d.org/docs/api/html/classOgre_1_1Pass.html#a2b0cfe1d55b1c03e59c4e3f546d2ec78|Pass::setPointSize()].
It's also possible to render the line thickness dependent to the distance. For details look to [http://www.ogre3d.org/docs/api/html/classOgre_1_1Pass.html#a0d44f9c4a2e69fd31a4687ffe2b8335d|setPointAttenuation], [http://www.ogre3d.org/docs/api/html/classOgre_1_1Pass.html#a75a3e18e0d2c3e7f51a47cedcec0246c|setPointMinSize], [http://www.ogre3d.org/docs/api/html/classOgre_1_1Pass.html#a463b59eaa324934370441a98b8b619b3|setPointMaxSize] and
[http://www.ogre3d.org/docs/api/html/classOgre_1_1Pass.html#a9683c2f40ed7c96b708eb2db5e02c842|setPointSpritesEnabled] of the ''Pass'' class.
%%%
!!Details
''This detailed description was copied from the Ogre 1.7.1 class reference of ManualObject.''
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:
* 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.
* Call __begin()__ to begin entering data
* For each vertex, call __position()__, __normal()__, __textureCoord()__, __colour()__ to define your vertex data. Note that each time you call __position()__ 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 __normal()__ in the first vertex, you cannot call it in any others. You ought to call the same combination of methods per vertex.
* If you want to define triangles (or lines/points) by indexing into the vertex list, you can call __index()__ 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.
* Call __end()__ to finish entering data.
* Optionally repeat the begin-end cycle if you want more geometry using different rendering operation types, or different materials After calling __end()__, the class will organise the data for that section internally and make it ready to render with. Like any other ((-MovableObject|MovableObject)) you should attach the object to a ((-SceneNode|SceneNode)) to make it visible. Other aspects like the relative render order can be controlled using standard MovableObject methods like __setRenderQueueGroup__.
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.
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.
!!Basics about 3D objects
!!!A Crash Course in 3D Objects
''This section was taken from the ((Intermediate Tutorial 4)).''
Before we start diving directly into making a mesh, it would probably be useful to talk about what a mesh is, and what it is made up of. Though this is a gross oversimplification, a mesh consists of roughly two parts: the ''vertex buffer'' and the ''index buffer''.
__Vertex buffers__ define points in 3D space. Each element in the vertex buffer is defined by several attributes you can set. The only attribute you ''must'' set is the position of the vertex. Aside from that, there are many optional properties you can set, such as the color of the vertex, the texture coordinates, and so on. Which ones you will actually need to use is dependent on what you are trying to do with the mesh.
__Index buffers__ "connect the dots" by selecting points from the vertex buffer. Every three indexes specified in the index buffer defines a single triangle to be drawn by the GPU. The order in which you select vertices in the index buffer tells the graphics card which way the triangle faces. A triangle which is drawn counter-clockwise is facing you, one drawn clockwise is facing away from you. Normally only the front of a triangle is rendered, so it is important to be sure that your triangles are setup properly.
Though all meshes have a vertex buffer, not all meshes will have an index buffer. For example, the mesh we are about to create will not have an index buffer since we want to create an empty rectangle (as opposed to a filled rectangle). Lastly, note that vertex and index buffers are usually stored in the video card's own memory, so your software can just send the card one simple, discrete set of commands to tell it to use those predefined buffers to render an entire 3D mesh in one go.
!!!How to create 3D objects (by code)
''This section was taken from the ((Intermediate Tutorial 4)).''
There are two ways to create your own mesh within Ogre. The first way is to subclass the __SimpleRenderable__ object and provide it with the vertex and index buffers directly. This is the most direct way to create one, but it's also the most cryptic. The ((Generating A Mesh)) code snippet shows an example of this.
To make things easier, Ogre provides a much nicer interface called __ManualObject__, which allows you to use some simple functions to define a mesh instead of writing raw data to the buffer objects. Instead of dropping the position, color, and so on into a buffer, you simply call the "position" and "colour" functions.
{TRANSCLUDE(page="seebox")}
* [http://www.ogre3d.org/docs/api/html/classOgre_1_1ManualObject.html|Class reference] for ManualObject
* Other ManualObject examples: ((Line 3D|Line3D)), ((DynamicLineDrawing)), ((Circle3D)), ((ManualObject 2D))
* MOGRE: ((MOGRE Line 3D|Line 3D)), ((Create Tetrahedron with MOGRE|Create Tetrahedron)), ((MOGRE GeneratingAGrid|Generating a grid))
* ((MadMarx Tutorial 3)) - ManualObject Quad
* ((MadMarx Tutorial 4)) - ManualObject to Mesh
* Important remarks are in its [http://www.ogre3d.org/docs/api/html/classOgre_1_1ManualObject.html#_details|API description] of ManualObject
* API description of ''[http://www.ogre3d.org/docs/api/html/classOgre_1_1ManualObject.html#657275e617d9558951a3037f02b07efe|convertToMesh()]''
* API description of [http://www.ogre3d.org/docs/api/html/classOgre_1_1SimpleRenderable.html|SimpleRenderable]
* API description of [http://www.ogre3d.org/docs/api/html/classOgre_1_1ManualObject.html#7f832d5605c489db7be396ec7cd20b85|identity projection]
* ((Ogre Procedural Geometry Library)) - A library to quickly create geometric primitives
* ((DynamicLineDrawing)) - create a line by the class ''SimpleRenderable'', which can be modified with better performance (e.g. change size of a circle)
* ((Debug Drawing Utility Class))
{TRANSCLUDE}