History: OgreDecal
Source of version: 9
Copy to clipboard
{img fileId="2148" thumb="y" alt="" width="322" imalign="right" rel="box[g]"}
__Current Maintainer__: fd9_
__Project__: External OGRE Project
__Type__: OGRE Library
__License__: MIT
__Supported Platforms__: Windows / Linux / Mac OS X
__Sources__:
__Status and bug reports__:
__Description:__ OgreDecal is a mesh decal generator which should support any triangle mesh and/or scene manager. Unlike the [http://www.ogre3d.org/tikiwiki/Intermediate+Tutorial+6|Projective Decal Tutorial], the decals are mesh-based and hence do not require any extra passes to render them, reducing the run-time cost considerably.
!!How To Use
Generation of a decal requires four parameters:
*The mesh to project onto (pointer to a TriangleMesh object)
*The center position of the projection box
*The width and height of the projected decal
*The material to use for the decal
The first and most important parameter to understand is the mesh object. Typically this will be your world object and can therefore be very large, probably consisting of a large number of triangles. The algorithm will need to collect all of the triangles within the bounding box area you wish to project a decal onto. Because of this, any object you pass in must derive from TriangleMesh, which is an abstract class with a single virtual function called ''findTrianglesInAABB()''. By default, you can use the OgreMesh object, which uses a brute-force test to check each triangle against the AABB. Below is a complete example using OgreMesh (in the example, it is assumed that the decal is projected onto the mesh by means of casting a ray from the camera into the scene).
{CODE(colors="c++")}/// This is the mesh object that we will pass to the decal generator.
/// Do not create any more than one OgreMesh per mesh, even if you have multiple instances of the same mesh in your scene.
OgreDecal::OgreMesh worldMesh;
/// This method will extract all of the triangles from the mesh to be used later. Only should be called once.
/// If you scale your mesh at all, pass it in here.
worldMesh.initialize( entity->getMesh(), 1.0 );
/// Get the DecalGenerator singleton
OgreDecal::DecalGenerator& generator = OgreDecal::DecalGenerator::getSingleton();
/// Set Decal parameters:
Ogre::Vector3 pos = getRaycastPoint(); /// Send a ray into the mesh
float width = 10;
float height = 10;
std::string textureName = "MyTexture"; /// Make sure your texture has a depth_bias greater than 0
/// We have everything ready to go. Now it's time to actually generate the decal:
OgreDecal::Decal decal = generator.createDecal( &worldMesh, pos, width, height, textureName );
/// Render the decal object. Always verify the returned object - it will be NULL if no decal could be created.
if (decal.object)
{
sceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject( decal.object );
}{CODE}
However, you can also derive your own class from TriangleMesh and implement findTrianglesInAABB() yourself. This gives you several advantages over using the OgreMesh object. For example, your world may consist of more than one mesh. If so, you can derive your own class to lookup triangles within each one. In addition, you may be using a physics engine that has optimizations which allows you to find triangles quicker. I have provided below an example using the Bullet physics engine:
{CODE(caption="Example class using the Bullet physics engine",colors="c++")}class BulletMesh : public OgreDecal::TriangleMesh, public btTriangleCallback
{
public:
BulletMesh()
{
mMesh = 0;
mTriangles = 0;
}
BulletMesh( btConcaveShape* mesh )
{
setMesh( mesh );
mTriangles = 0;
}
void setMesh( btConcaveShape* mesh )
{
mMesh = mesh;
}
void processTriangle( btVector3* triangle, int partId, int triangleIndex)
{
/// Convert Bullet vectors to Ogre vectors
Ogre::Vector3 v1( triangle[0].getX(), triangle[0].getY(), triangle[0].getZ() );
Ogre::Vector3 v2( triangle[1].getX(), triangle[1].getY(), triangle[1].getZ() );
Ogre::Vector3 v3( triangle[2].getX(), triangle[2].getY(), triangle[2].getZ() );
OgreDecal::Triangle t( v1, v2, v3 );
if (OgreDecal::collide_triangle_exact( mAABBMin, mAABBMax, t ))
mTriangles->push_back( t );
}
void findTrianglesInAABB( const Ogre::Vector3& aabbMin, const Ogre::Vector3& aabbMax, std::vector< OgreDecal::Triangle >& triangles )
{
mTriangles = &triangles;
mTriangles->clear();
mAABBMin = aabbMin;
mAABBMax = aabbMax;
mMesh->processAllTriangles( this, OgreToBullet(aabbMin), OgreToBullet(aabbMax) );
mTriangles = 0;
}
private:
Ogre::Vector3 mAABBMin, mAABBMax;
std::vector< OgreDecal::Triangle >* mTriangles;
btConcaveShape* mMesh;
};{CODE}
!!Debug Drawing
{img fileId="2149" thumb="y" width="360" imalign="right" rel="box[g]"}
Debug drawing will render the vertices and triangles of each decal. To enable it, set DEBUG_ENABLED to ''true'' at the top of OgreDecal.cpp. Then call ''turnDebugOn():''
{CODE(colors="c++")}
/// At the top of OgreDecal.cpp, this is required:
const bool DEBUG_ENABLED = true;
OgreDecal::DecalGenerator::getSingleton().turnDebugOn();
/// Alternatively, you can flip the debug state on/off:
OgreDecal::DecalGenerator::getSingleton().flipDebug();{CODE}
!!Limitations
__1)__ Decal projection is an approximation and will not always produce desired results. Stretching and cropping will sometimes occur, depending on the geometry. Any contributions to make the algorithm more robust is welcomed.
__2)__ Currently does not properly support disjointed triangles, back facing triangles, or types of geometry which is smaller than the projection box. For example, consider thin surfaces which have opposite facing triangles. The algorithm makes no effort to distinguish one side from the other, so it will simply attempt to project onto both faces. In other words, it uses all triangles found within the projection box. One idea is to provide an optional parameter that specifies a normal (could possibly be the ray vector negated, or the normal of the triangle closest to the center position) and/or a rotational deviation limit which would ignore any triangles that are "facing away", as determined by the rotational limit.
__3)__ Currently only supports static meshes ''with their default orientation and position unchanged.''