OgreDecal: A mesh-based decal generator

A place to show off your latest screenshots and for people to comment on them. Only start a new thread here if you have some nice images to show off!
User avatar
nevarim
Gnoll
Posts: 675
Joined: Mon Jul 05, 2010 6:16 pm
Location: Pavia Italy
x 4
Contact:

Re: OgreDecal

Post by nevarim »

for to create ray there is no problem, there is also ogre collision that help :)

my problem is no create a decal that is adaptive on terrain as you made in video (i use heightmaps for to create as in terrain tutorial )
i'm a noob until proven otherwise :D
used in my project ;) and thanks to everyone :D
Ogre 3d
Mygui
Skyx
Hydrax
MOC
CCS
fd9_
Halfling
Posts: 64
Joined: Wed Aug 20, 2008 9:20 pm
x 22

Re: OgreDecal

Post by fd9_ »

nevarim wrote:for to create ray there is no problem, there is also ogre collision that help :)

my problem is no create a decal that is adaptive on terrain as you made in video (i use heightmaps for to create as in terrain tutorial )
You just need to call the CreateDecal() function as shown in the wiki, and it will generate the decal for you. The only caveat is that you'll need to find a way to access the triangles in your heightmap, or at least determine which triangles intersect the AABB. If your heightmap/terrain not a standard mesh object, then you'll need to derive from the OgreDecal::TriangleMesh class as shown in the wiki.
User avatar
duststorm
Minaton
Posts: 921
Joined: Sat Jul 31, 2010 6:29 pm
Location: Belgium
x 80
Contact:

Re: OgreDecal

Post by duststorm »

Nice demo.
If I understood correctly you test each triangle in the scene against the bounding box of your decal, correct?
An obvious optimization, that would also make it work with scenes consisting of multiple entities, is to test the bounding box of the decal against bounding boxes of scene entities (ideally in a hierarchic way, eg. with an OC tree). Then you would only need to test trianlge intersections with a few entities.
Developer @ MakeHuman.org
fd9_
Halfling
Posts: 64
Joined: Wed Aug 20, 2008 9:20 pm
x 22

Re: OgreDecal

Post by fd9_ »

duststorm wrote:Nice demo.
If I understood correctly you test each triangle in the scene against the bounding box of your decal, correct?
An obvious optimization, that would also make it work with scenes consisting of multiple entities, is to test the bounding box of the decal against bounding boxes of scene entities (ideally in a hierarchic way, eg. with an OC tree). Then you would only need to test trianlge intersections with a few entities.
When using the OgreDecal::OgreMesh class that is provided, each triangle in the mesh is tested against the bounding box of the decal. This is the "default" brute-force option. However if you don't use OgreMesh, then the way that you detect triangles is entirely up to you (by implementing findTrianglesInABBB()). For example, you can implement this function by looping through each entity in your scene and checking it's bounding box against the decal's bounding box before testing individual triangles. You can even use an Octree for that if you wish, but that is up to you. Or you can simply use whichever method is provided by your physics engine, assuming there are optimizations being done under the hood (if applicable - see the wiki for simple example that uses a single Bullet mesh). Note that I have provided two helper functions in DecalUtility for these doing these tests - collide_triangle_bounding_box() and collide_triangle_exact().

With that said, It's important to realize two things if you plan to test against multiple entities:

1) [s]Testing against non-static entities will not work, because the decal you get back will not get updated with the entity.[/s] You should be able to test against non-static entities in your scene as long as you don't use the OgreMesh class, because it doesn't currently support it (unless you edit the source). Then you would attach the decal as a child node so it gets updated relative to the entity, assuming were not talking about animated entities.

2) Limitation #2 described in the wiki still applies here. For example, let's say you have a simple plane/quad with a standard cube mesh sitting on top of it. The decal projection algorithm will try to project on all triangles you give it - including the bottom side of the cube. So the projection will not be correct, unless you explicitly remove the bottom cube triangles in your implementation of findTrianglesInAABB(). But typically you would model the world so that those triangles would be backfacing, in which case the decal projection would be correct.

Does that make sense, or did I just make things more confusing?

By the way, I also added an extra parameter to createDecal(), which allows you to pass in an existing decal object instead of creating a new one. This should make dynamic decals much more efficient (for example, as shown in the last video).
Last edited by fd9_ on Wed Oct 03, 2012 11:13 pm, edited 1 time in total.
User avatar
ekt
Gremlin
Posts: 150
Joined: Thu Apr 01, 2004 5:55 pm
x 4
Contact:

Re: OgreDecal

Post by ekt »

Hi fd9_
first, thanks for sharing your work - i've tried myself in the past but got stuck on the uv generation part.

one question: i always felt that the brute-force checking of all tringles was less than optimal - besided the good advice of using the physics engine - do you have ideas on other solutions?
(ive posted this question some time ago, but with scarce succes)
bstone
OGRE Expert User
OGRE Expert User
Posts: 1920
Joined: Sun Feb 19, 2012 9:24 pm
Location: Russia
x 201

Re: OgreDecal

Post by bstone »

You could optimize that with things like bounding volume hierarchies for static meshes. For animated meshes that won't work out-of-the-box - you'll have to animate/rebuild the BVH every frame.
fd9_
Halfling
Posts: 64
Joined: Wed Aug 20, 2008 9:20 pm
x 22

Re: OgreDecal

Post by fd9_ »

ekt wrote:Hi fd9_
first, thanks for sharing your work - i've tried myself in the past but got stuck on the uv generation part.

one question: i always felt that the brute-force checking of all tringles was less than optimal - besided the good advice of using the physics engine - do you have ideas on other solutions?
(ive posted this question some time ago, but with scarce succes)
As bstone mentioned, large static worlds should be optimized with some kind of spatial partitioning method. For example, I believe Bullet uses bounding volume hierarchies internally. Although the OgreMesh class is currently brute-force, there is no reason why it can't be updated to support these types of optimizations. However, I don't really have any interest in continuing development for this project, so that's why it's open source. :mrgreen:
User avatar
nevarim
Gnoll
Posts: 675
Joined: Mon Jul 05, 2010 6:16 pm
Location: Pavia Italy
x 4
Contact:

Re: OgreDecal: A mesh-based decal generator

Post by nevarim »

nice job ;)

i have 2 question that are not properly inherent to this project :

how can i create a material for an image?

for you there is a method to "rotate" image on terrain?


thanks

Nevarim
i'm a noob until proven otherwise :D
used in my project ;) and thanks to everyone :D
Ogre 3d
Mygui
Skyx
Hydrax
MOC
CCS
fd9_
Halfling
Posts: 64
Joined: Wed Aug 20, 2008 9:20 pm
x 22

Re: OgreDecal: A mesh-based decal generator

Post by fd9_ »

nevarim wrote:nice job ;)

i have 2 question that are not properly inherent to this project :

how can i create a material for an image?

for you there is a method to "rotate" image on terrain?
You can take a look at this post for an example of a material: http://ogre3d.org/forums/viewtopic.php? ... 83#p470782

Regarding your second question, there is no way to rotate the image using OgreDecal. However, there is an optional parameter to createDecal() which will automatically flip the texture in a random direction (horizontally and/or vertically). This is useful for blood splatters, explosion decals, etc where you might want to add some variation. But there is no way (as of yet) to rotate it by 25 degrees, for example.
User avatar
pinaster
Gnoblar
Posts: 24
Joined: Tue Oct 09, 2012 12:48 pm
Location: Italy
x 2
Contact:

Re: OgreDecal: A mesh-based decal generator

Post by pinaster »

Congrats, it's really interesting.

I have to include Terrain painting in my editor soon.
User avatar
nevarim
Gnoll
Posts: 675
Joined: Mon Jul 05, 2010 6:16 pm
Location: Pavia Italy
x 4
Contact:

Re: OgreDecal: A mesh-based decal generator

Post by nevarim »

must be nice to include a splat terrain painting ;)
i'm a noob until proven otherwise :D
used in my project ;) and thanks to everyone :D
Ogre 3d
Mygui
Skyx
Hydrax
MOC
CCS
drwbns
Orc Shaman
Posts: 788
Joined: Mon Jan 18, 2010 6:06 pm
Location: Costa Mesa, California
x 24

Re: OgreDecal

Post by drwbns »

bstone wrote:You could optimize that with things like bounding volume hierarchies for static meshes. For animated meshes that won't work out-of-the-box - you'll have to animate/rebuild the BVH every frame.
Sounds like an interesting Ogre expansion. Has nobody decided to tackle the problem yet?
technique
Halfling
Posts: 91
Joined: Fri Oct 22, 2010 10:46 pm
x 8

Re: OgreDecal: A mesh-based decal generator

Post by technique »

I wrote a small extension for OgreDecal to support the new Ogre-Terrain system. To use it - initialize the mesh with a pointer to the TerrainGroup of your terrain. Its not looking completly fine (seems to be something wrong with the texture mapping) but overall its working quite good.

[youtube]qgN-0bdFeFI[/youtube]

Code: Select all

	class OgreTerrain : public OgreMesh
	{
		public:

		OgreTerrain() {}

		void initialize(Ogre::TerrainGroup* terrainGroup)
		{
			mTerrainGroup = terrainGroup;
		}

		int round(float value)
		{
			return static_cast<int>(value + 0.5);
		}

		void findTrianglesInAABB( const Ogre::Vector3& aabbMin, const Ogre::Vector3& aabbMax, std::vector< Triangle >& triangles )
		{
			Ogre::TerrainGroup::TerrainList terrainList;
			Ogre::AxisAlignedBox box(aabbMin, aabbMax);
			mTerrainGroup->boxIntersects(box, &terrainList);
			for(unsigned int i = 0; i < terrainList.size(); i++)
			{
				Ogre::Terrain* terrain = terrainList.at(i);
				Ogre::Vector3 terrainSpace;
				terrain->getTerrainPosition(box.getCenter(), &terrainSpace);
				Ogre::Real terrainSize = (terrain->getSize() - 1);
				float sizeX = static_cast<float>(box.getSize().x) / static_cast<float>(terrain->getSize());
				float sizeY = static_cast<float>(box.getSize().y) / static_cast<float>(terrain->getSize());
				long startx = (terrainSpace.x - sizeX ) * terrainSize;
				long starty = (terrainSpace.y - sizeY) * terrainSize;
				long endx = (terrainSpace.x + sizeX) * terrainSize;
				long endy= (terrainSpace.y + sizeY) * terrainSize;
				startx = std::max(startx, 0L);
				starty = std::max(starty, 0L);
				endx = std::min(endx, (long)terrainSize);
				endy = std::min(endy, (long)terrainSize);
				Ogre::Vector3 pointSpace(static_cast<int>(terrainSpace.x * terrainSize + 0.5), static_cast<int>(terrainSpace.y * terrainSize + 0.5), 1);
				Ogre::Vector3 pos1, pos2, pos3, pos4;
				Triangle a, b;
				for (long y = starty; y < endy; ++y)
				{
					for (long x = startx; x < endx; ++x)
					{
						terrain->getPoint(x, y, &pos1);
						terrain->getPoint(x + 1, y, &pos2);
						terrain->getPoint(x, (y + 1), &pos3);
						terrain->getPoint(x + 1, (y + 1), &pos4);
						pos1 += terrain->getPosition();
						pos2 += terrain->getPosition();
						pos3 += terrain->getPosition();
						pos4 += terrain->getPosition();
						a = Triangle(pos1, pos2, pos4);
						b = Triangle(pos1, pos4, pos3);
						if(OgreDecal::collide_triangle_exact(aabbMin, aabbMax, a))
							triangles.push_back(a);
						if(OgreDecal::collide_triangle_exact(aabbMin, aabbMax, b))
							triangles.push_back(b);
					}
				}
			}
			// no terrain triangles inside the AABB - check your decal position
			assert(triangles.size() != 0);
		}

		private:
			Ogre::TerrainGroup* mTerrainGroup;
			Ogre::Vector3 mLastAABBMin, mLastAABBMax;
	};
I had to add a small hack in OgreDecal.cpp line 298 to fix a crash:

Code: Select all

   [...]
        for (int edge = 0; edge < NUM_EDGE_PLANES; ++edge)
        {
            /// Clip the polygon against the edge plane.
            /// Why is this function returning duplicate points?
			if(polygon_points.size() == 0)  // ADD THIS IF-STATEMENT
			{	
				continue;
			}
            int clipped_count = plane_clip_polygon( edgePlanes[ edge ], &(polygon_points[0]), polygon_points.size(), clippedPoints );
            
            polygon_points.clear();
   [...]
Image
Kingdoms Defender offers Tower Defense action with breathtaking 3-D graphics for your mobile Android device.

Give it a try:
Free-Version:
http://play.google.com/store/apps/detai ... ender_free

Full-Version:
http://play.google.com/store/apps/detai ... msdefender
fd9_
Halfling
Posts: 64
Joined: Wed Aug 20, 2008 9:20 pm
x 22

Re: OgreDecal: A mesh-based decal generator

Post by fd9_ »

Sweet! Thanks for sharing. It's nice to see examples of other people using it. :D
User avatar
nevarim
Gnoll
Posts: 675
Joined: Mon Jul 05, 2010 6:16 pm
Location: Pavia Italy
x 4
Contact:

Re: OgreDecal: A mesh-based decal generator

Post by nevarim »

great ;) i will use it ;)
i'm a noob until proven otherwise :D
used in my project ;) and thanks to everyone :D
Ogre 3d
Mygui
Skyx
Hydrax
MOC
CCS
User avatar
nevarim
Gnoll
Posts: 675
Joined: Mon Jul 05, 2010 6:16 pm
Location: Pavia Italy
x 4
Contact:

Re: OgreDecal: A mesh-based decal generator

Post by nevarim »

hi all i have a little problem with

worldMesh.initialize( entity->getMesh(), 1.0 );

that is different from inizialize header in terrain modify

void OgreMesh::initialize( const Ogre::MeshPtr& mesh, const Ogre::Vector3& scale )

what i can do with it?

:D

thanks

Neva
i'm a noob until proven otherwise :D
used in my project ;) and thanks to everyone :D
Ogre 3d
Mygui
Skyx
Hydrax
MOC
CCS
bstone
OGRE Expert User
OGRE Expert User
Posts: 1920
Joined: Sun Feb 19, 2012 9:24 pm
Location: Russia
x 201

Re: OgreDecal: A mesh-based decal generator

Post by bstone »

nevarim wrote: what i can do with it?

Code: Select all

worldMesh.initialize( entity->getMesh(), Ogre::Vector3( 1.0 ) );
User avatar
nevarim
Gnoll
Posts: 675
Joined: Mon Jul 05, 2010 6:16 pm
Location: Pavia Italy
x 4
Contact:

Re: OgreDecal: A mesh-based decal generator

Post by nevarim »

hi again :)

using wiki for decalgenerator i have these errors

tutorialaplications.h

Code: Select all

#ifndef __TutorialApplication_h_
#define __TutorialApplication_h_

#include "BaseApplication.h"
#include "OgreDecal.h"

class TutorialApplication : public BaseApplication
{
public:
    TutorialApplication(void);
    virtual ~TutorialApplication(void);

protected:
    virtual void createScene(void);
};

#endif

tutorialapplications.cpp

Code: Select all

#include "TutorialApplication.h"

//-------------------------------------------------------------------------------------
TutorialApplication::TutorialApplication(void)
{
}
//-------------------------------------------------------------------------------------
TutorialApplication::~TutorialApplication(void)
{
}

//-------------------------------------------------------------------------------------
void TutorialApplication::createScene(void)
{
    Ogre::Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh");
 
    // Create a SceneNode and attach the Entity to it
    Ogre::SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("HeadNode");
    headNode->attachObject(ogreHead);


	OgreDecal::OgreMesh worldMesh;
	worldMesh.initialize( ogreHead->getMesh(), 1.0 );
	OgreDecal::DecalGenerator& generator = OgreDecal::DecalGenerator::getSingleton();
	generator.initialize(mSceneMgr);
	Ogre::Vector3 pos = getRaycastPoint(); /// Send a ray into the mesh
	float width = 10;
	float height = 10;
	std::string textureName = "simbolo.png"; /// Make sure your texture has a depth_bias greater than 1 to avoid z-fighting
	OgreDecal::Decal decal = generator.createDecal( &worldMesh, pos, width, height, textureName );
	if (decal.object)
	{
		sceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject( decal.object );
	}



}



#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
    INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
    int main(int argc, char *argv[])
#endif
    {
        // Create application object
        TutorialApplication app;

        try {
            app.go();
        } catch( Ogre::Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
            MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
            std::cerr << "An exception has occured: " <<
                e.getFullDescription().c_str() << std::endl;
#endif
        }

        return 0;
    }

#ifdef __cplusplus
}
#endif

this is result

Code: Select all

1> ------ Start compilation: Project: DECALHandling, Configuration: Debug Win32 ------
1> TutorialApplication.cpp
1> g: \ development \ projects \ decalhandling \ decalhandling \ src \ tutorialapplication.cpp (23): error C2664: 'OgreDecal OgreMesh :: :: initialize': unable to convert parameter 2 from 'double' to 'const Ogre: : Vector3 & '
1> Reason: can not convert from 'double' to 'const Ogre :: Vector3'
1> The constructor of class 'Ogre :: Vector3' is declared as 'explicit'
1> g: \ development \ projects \ decalhandling \ decalhandling \ src \ tutorialapplication.cpp (26): error C3861: 'getRaycastPoint': identifier not found
1> g: \ development \ projects \ decalhandling \ decalhandling \ src \ tutorialapplication.cpp (33): error C2065: 'sceneMgr': undeclared identifier
1> g: \ development \ projects \ decalhandling \ decalhandling \ src \ tutorialapplication.cpp (33): error C2227: the element to the left of '-> getRootSceneNode' must point to class type, structure, union, or generic
1> type is'' unknown-type''
1> g: \ development \ projects \ decalhandling \ decalhandling \ src \ tutorialapplication.cpp (33): error C2227: the element to the left of '-> createChildSceneNode' must point to class type, structure, union, or generic
1> g: \ development \ projects \ decalhandling \ decalhandling \ src \ tutorialapplication.cpp (33): error C2227: the element to the left of '-> attachObject' must point to class type, structure, union, or generic
========== Build: 0 succeeded, 1 failed, 0 up to date, 0 skipped ==========
how can i solve?

thanks

Nevarim
i'm a noob until proven otherwise :D
used in my project ;) and thanks to everyone :D
Ogre 3d
Mygui
Skyx
Hydrax
MOC
CCS
User avatar
nevarim
Gnoll
Posts: 675
Joined: Mon Jul 05, 2010 6:16 pm
Location: Pavia Italy
x 4
Contact:

Re: OgreDecal: A mesh-based decal generator

Post by nevarim »

hi all

solved all

but hafter inizialized how can i set decal on terrain?
i'm a noob until proven otherwise :D
used in my project ;) and thanks to everyone :D
Ogre 3d
Mygui
Skyx
Hydrax
MOC
CCS
User avatar
Thyrion
Goblin
Posts: 224
Joined: Wed Jul 31, 2013 1:58 pm
Location: germany
x 8

Re: OgreDecal: A mesh-based decal generator

Post by Thyrion »

Someone using this Decal generator?

I'm getting bad performance with more detailed mesh (and dynamic decal).
I'm using the BulletMesh class from wiki.

mDecal = createDecal(&mWorldMesh, pos, width, height, textureName, false, mDecal.object);

Would the "projective Decal" be better for large (detailed)meshes?
Just for targeting, so it would be one Decal.
kowinis
Gnoblar
Posts: 7
Joined: Fri Mar 20, 2015 10:39 pm

Re: OgreDecal: A mesh-based decal generator

Post by kowinis »

hi,

i was wondering is it somehow possible to apply decal to geometry wich is smaller than projection box?(i have geometry and i need to wrap it with texture)
Post Reply