Code: ETM Projective Decal

SongOfTheWeave

04-02-2008 05:24:54

New Version

This is the version found on page four. It is so much better than the original that I'm just going to replace the original with it.

Features:
  1. Draws a decal on your terrain that can be arbitrarily positioned. Suitable for following the mouse and indicating brush size for editing.[/*:m]
  2. Works with Shoggoth & Eihort (thanks to BloodyFanatic)[/*:m][/list:u]

    Screenshot:

    Please note, this code is just for the decal which is the blue circly thing in the above screenshot.

    How to Use:
    1. Create the following files and include them in your project[/*:m]
    2. Create transparent (no content, just blank/transparent) 2px by 2px png and name it decalBase.png - If you want to name it something else, edit the string literal in DecalCursor::init[/*:m]
    3. Create an instance of DecalCursor in your project.[/*:m]
    4. Call DecalCursor::show() to make it appear and hide to hide it.[/*:m]
    5. Call DecalCurstor::setPosition(Vector3) to move the decal around (for example, in your mouseMoved handler.)[/*:m][/list:u]

      /**
      * @file DecalCursor.h
      * @author Jesse Wright - www.cutthroatstudios.com
      * @note Modified from Brocan's example on the Ogre forums
      * @note Modifications by BloodyFanatic: Decal pass removing and Ogre Shoggoth fix added,
      parameter changed to reference, setPosition 'optimization' removed, proper initialization
      */

      #ifndef SANGUIS_DECALCURSOR_H
      #define SANGUIS_DECALCURSOR_H

      #include "OgreMaterial.h"
      #include "OgreVector3.h"
      #include "OgreVector2.h"

      // forward declaration
      namespace Ogre
      {
      class SceneManager;
      class SceneNode;
      class Frustum;
      class TextureUnitState;
      class Pass;
      }

      /**
      * @class DecalCursor
      * @author Jesse Wright - www.cutthroatstudios.com
      * @date Created on 12/25/2007
      * @date Last modified 5/19/2007
      */
      class DecalCursor
      {
      public:
      DecalCursor(Ogre::SceneManager* man,
      Ogre::MaterialPtr terrainMat,
      const Ogre::Vector2& size,
      const std::string& tex);
      ~DecalCursor();

      inline bool isVisible() const { return m_bVisible; }

      Ogre::Vector3 getPosition() const;

      void show();
      void hide();

      void setPosition(const Ogre::Vector3& pos);
      void setSize(const Ogre::Vector2& size);

      private:
      void init(const Ogre::Vector2& size, const std::string& tex);
      void showTerrainDecal();
      void hideTerrainDecal();

      Ogre::Vector2 m_size; /**< @brief size of decal */
      Ogre::Vector3 m_pos;

      std::string m_sTexName; /**< @brief texture to apply */

      Ogre::SceneNode* m_nodeProj; /**< @brief the projection node */
      Ogre::Frustum* m_frustProj; /**< @brief the projection frustum */
      Ogre::TextureUnitState* m_texState; /**< @brief pointer to the texture unit state in the pass */
      Ogre::Pass* m_pass; /**< @brief pointer to the decal pass */
      Ogre::MaterialPtr m_terrainMat; /**< @brief sharedptr to the terrain material */

      Ogre::SceneManager* m_sceneMgr; /**< @brief Pointer to the application's Ogre::SceneManager */

      bool m_bVisible; /**< @brief true if the decal visible, otherwise false */
      };

      #endif


      /**
      * @file DecalCursor.cpp
      * @author Jesse Wright - www.cutthroatstudios.com
      * @date Created on 12/25/2007
      * @date Last modified 5/19/2007
      * @note Modified from Brocan's example on the Ogre forums
      */

      #include "OgreSceneManager.h"
      #include "OgreTextureManager.h"
      #include "OgreSceneNode.h"
      #include "OgreFrustum.h"
      #include "OgreTextureUnitState.h"
      #include "OgrePass.h"

      #include "DecalCursor.h"

      /**
      * @brief The length of one meter in ogre units
      * @todo Set this to something meaningful for your project!
      */
      static const float METER_SCALE = 1.0f;

      DecalCursor::DecalCursor(Ogre::SceneManager* man, Ogre::MaterialPtr terrainMat, const Ogre::Vector2& size,
      const std::string& tex)

      : m_bVisible ( false ), m_nodeProj(0), m_pass(0), m_frustProj(0), m_texState(0), m_sceneMgr(man),
      m_terrainMat( terrainMat ), m_pos ( Ogre::Vector3::ZERO ), m_size ( Ogre::Vector2::ZERO )
      {
      init(size, tex);
      }

      DecalCursor::~DecalCursor()
      {
      hide();

      // remove the decal pass
      if ( m_pass )
      {
      m_terrainMat->getTechnique(0)->removePass( m_pass->getIndex() );
      m_pass = 0;
      }

      // delete frustum
      m_nodeProj->detachAllObjects();
      delete m_frustProj;

      // destroy node
      m_nodeProj->getParentSceneNode()->removeAndDestroyChild(m_nodeProj->getName());
      }

      void DecalCursor::init(const Ogre::Vector2& size, const std::string& tex )
      {
      // create a new pass in the material to render the decal
      m_pass = m_terrainMat->getTechnique(0)->getPass("Decal");
      if (!m_pass)
      {
      Ogre::Technique* techPref = m_terrainMat->getTechnique(0);
      m_pass = techPref->createPass();
      m_pass->setName("Decal");
      m_pass->setLightingEnabled(false);
      m_pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
      m_pass->setDepthBias(2.5, 2.5);
      m_pass->setFog(true);
      m_pass->createTextureUnitState("decalBase.png");
      }

      // init projective decal
      // set up the main decal projection frustum
      m_frustProj = new Ogre::Frustum();
      m_nodeProj = m_sceneMgr->getRootSceneNode()->createChildSceneNode();
      m_nodeProj->attachObject(m_frustProj);
      m_frustProj->setProjectionType(Ogre::PT_ORTHOGRAPHIC);
      m_nodeProj->setOrientation(Ogre::Quaternion(Ogre::Degree(90), Ogre::Vector3::UNIT_X));

      /* Commented out for general use. If you are using mouse picking in your scene, set this to an unselectable flag otherwise you may find the frustum in your ray queries. */
      //m_frustProj->setQueryFlags(Sanguis::UNSELECTABLE);

      // set given values
      setSize(size);
      m_sTexName = tex; // texture to apply

      // load the images for the decal and the filter
      Ogre::TextureManager::getSingleton().load(m_sTexName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, 1);

      m_bVisible = false;
      }

      Ogre::Vector3 DecalCursor::getPosition() const
      {
      return m_pos;
      }

      void DecalCursor::show()
      {
      if(!m_bVisible)
      {
      m_bVisible = true;
      showTerrainDecal();
      setPosition(m_pos);
      }
      }

      void DecalCursor::hide()
      {
      if (m_bVisible)
      {
      m_bVisible = false;
      hideTerrainDecal();
      }
      }

      void DecalCursor::setPosition(const Ogre::Vector3& pos)
      {
      m_pos = pos;

      // Set the projection coming from some distance above the current position.
      m_nodeProj->setPosition(pos.x, pos.y + (10.0 * METER_SCALE), pos.z);
      }

      void DecalCursor::setSize(const Ogre::Vector2& size)
      {
      if (m_size != size)
      {
      m_size = size;

      // update aspect ratio
      #if OGRE_VERSION_MAJOR == 1 && OGRE_VERSION_MINOR <= 4
      m_frustProj->setAspectRatio(m_size.x / m_size.y);
      #else
      m_frustProj->setOrthoWindow ( m_size.x, m_size.y );
      #endif

      // set fovy so that tan = 1, so 45 degrees
      m_frustProj->setFOVy(Ogre::Degree(45));

      // set near clip plane according to fovy:
      m_frustProj->setNearClipDistance(m_size.y);
      }
      }

      // Protected

      void DecalCursor::showTerrainDecal()
      {
      if (!m_texState)
      {
      // set up the decal's texture unit
      m_texState = m_pass->createTextureUnitState(m_sTexName);
      m_texState->setProjectiveTexturing(true, m_frustProj);
      m_texState->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
      m_texState->setTextureFiltering(Ogre::FO_POINT, Ogre::FO_LINEAR, Ogre::FO_NONE);
      m_texState->setAlphaOperation(Ogre::LBX_ADD);
      }
      }

      void DecalCursor::hideTerrainDecal()
      {
      if (m_texState)
      {
      m_pass->removeTextureUnitState(m_pass->getTextureUnitStateIndex(m_texState));
      m_texState = 0;
      }
      }

Nauk

04-02-2008 11:10:00

Thanks for linking, just what I was looking for. My decal code (copy-paste-hack from the wiki) only works for standart 6 textures and the decal doesn't show with 9 for some odd reasons, looking forward to try that one out :)

Nauk

06-02-2008 10:07:48

I tried it and it works fine with 6 textures 2 coverage maps standard setup, but the decal doesn't want to show whatsoever with my 3 maps / 9 texture setup:

ETTerrain.material:

material ETTerrainMaterial
{
technique
{
// primary splatting technique, requires PS 2.0
// has issues with OpenGL rendering, though...

pass
{
// splatting pass

lighting off

vertex_program_ref ET/Programs/VSLodMorph2
{
}

fragment_program_ref ET/Programs/PSSplat2
{
param_named splatScaleX float 192
param_named splatScaleZ float 192
}

texture_unit
{
// first coverage map, dynamically managed
texture ETSplatting0
}
texture_unit
{
// second coverage map, dynamically managed
texture ETSplatting1
}
texture_unit
{
// third coverage map, dynamically managed
texture ETSplatting2
}

// splatting textures
texture_unit
{
texture splatting0.png
}
texture_unit
{
texture splatting1.png
}
texture_unit
{
texture splatting2.png
}
texture_unit
{
texture splatting3.png
}
texture_unit
{
texture splatting4.png
}
texture_unit
{
texture splatting5.png
}
texture_unit
{
texture splatting6.png
}
texture_unit
{
texture splatting7.png
}
texture_unit
{
texture splatting8.png
}
}


PSSplat2.cg:

void main
(
float2 iTexCoord0 : TEXCOORD0,

out float4 oColor : COLOR,

uniform sampler2D covMap1,
uniform sampler2D covMap2,
uniform sampler2D covMap3,
uniform sampler2D splat1,
uniform sampler2D splat2,
uniform sampler2D splat3,
uniform sampler2D splat4,
uniform sampler2D splat5,
uniform sampler2D splat6,
uniform sampler2D splat7,
uniform sampler2D splat8,
uniform sampler2D splat9,

uniform float splatScaleX,
uniform float splatScaleZ
)
{
float3 cov1 = tex2D(covMap1, iTexCoord0).rgb;
float3 cov2 = tex2D(covMap2, iTexCoord0).rgb;
float3 cov3 = tex2D(covMap3, iTexCoord0).rgb;

iTexCoord0.x *= splatScaleX;
iTexCoord0.y *= splatScaleZ;

oColor = tex2D(splat1, iTexCoord0) * cov1.x
+ tex2D(splat2, iTexCoord0) * cov1.y
+ tex2D(splat3, iTexCoord0) * cov1.z
+ tex2D(splat4, iTexCoord0) * cov2.x
+ tex2D(splat5, iTexCoord0) * cov2.y
+ tex2D(splat6, iTexCoord0) * cov2.z
+ tex2D(splat7, iTexCoord0) * cov3.x
+ tex2D(splat8, iTexCoord0) * cov3.y
+ tex2D(splat9, iTexCoord0) * cov3.z;

}



mSplatMgr = new ET::SplattingManager("ETSplatting", "ET", 1024, 1024, 3);
mSplatMgr->setNumTextures(9);


If anyone got a remote idea why, please let me know, I would very much appreciate it :)

SongOfTheWeave

12-02-2008 04:44:50

Well, it could be a number of things... you only posted the first pass of your material file, is the decal pass pass 2 (the third pass in the technique)?

The DecalCursor class as it appears in the OP assumes that the decal pass is technique 0, pass 2.

If you put the decal pass as pass 1 (after the splatting pass and before the lighting pass) it won't work (see DecalCursor::init() )

Either rearrange your passes, or better yet, rewrite the DecalCursor::init() to create a new decal pass in whatever material you give it rather than making assumptions about the state of the material.

Nauk

13-02-2008 02:26:25

Found why it doesn't show at all, something is faulty with my material setup since the 2.0 technique is being skipped with my 9 texture setup..., so i can add passes all day long to it :P. But a nvidia 6800+latest drivers should be able to handle it.

@SongoftheWeave: The lightmap pass (pass 1 / tech.0) is the default one and I had added the extra decal pass after it, just copy and paste.

SongOfTheWeave

13-02-2008 02:58:28

Found why it doesn't show at all, something is faulty with my material setup since the 2.0 technique is being skipped with my 9 texture setup...

Have you determined what was causing it to skip the first technique?

Nauk

13-02-2008 09:08:43

Not really, I don't get any error messages in the log files / or console, my guess (shot in the dark) is it is something with the cg file, I also looked into the code of ETM and see if I discover anything that wouldn't support the 3rd map. So far I haven't found anything and in the cg are my knowledge is still very very basic and limited.

CABAListic

13-02-2008 09:27:38

You don't need to look at the ETM code for this; ETM has absolutely nothing to do with the terrain material. I assume you have a recent Ogre version? Otherwise, there might still be an 8 texture limit on passes in it.

Nauk

13-02-2008 11:25:14

Running 1.41 right now, that should support more than 8? If it definatly is a material / cg problem and you look at the above posted code excerpts, do you recognize anything that strikes you as capitally faulty on a first glance?

Thanks for your time! :)

/Nauk

CABAListic

13-02-2008 12:55:14

I'm not sure about 1.4.1, I wouldn't bet on it. The (wrong) limit on 8 textures was removed somewhere within the Eihort branch, so it's very possible that 1.4.1 still has it. Try upgrading.

Nauk

13-02-2008 15:04:11

Yay, you are da man CABAListic! Upgrading Ogre indeed did the trick: 2.0 technique working plus I got a decal showing shiny on my terrain.

Thanks a lot! :)

kungfoomasta

05-03-2008 20:03:19

Using decals for unit selection, and assuming there will be units of various size (large/small radius), wouldn't the texture stretch for the bigger units? Imagine the decal appears as a green ring that is 2 pixels thick around small units. Wouldn't it be skewed to look like a ring that is 5 pixels thick around a large unit? (for example)

I basically want a ring that can have variable radius, but constant thickness. Are decals appropriate for this?

CABAListic

05-03-2008 20:32:38

You're right, it would stretch. Though arguably in a certain range of sizes it would be unnoticable, so you could probably just create a distinct set of textures (for example one for large units, one for medium sized and one for small units) to counter this.

Another method would be to use a manual object and create your circle as a line list. That line would always have the same width no matter how many points you're using (though I'm not quite certain if you can influence the line thickness that way, unless you construct your circle of triangles).

kungfoomasta

05-03-2008 21:09:11

That thought occurred to me also, if I could create a class that would use a manual object to create a ring. The main difference with this approach is that the number of vertices/polygons rendered are significantly increased, for example if you have 15 units selected. I'll have to look into seeing if you can increase line thickness, that would be very convenient, and wouldn't require a lot of vertices. Maybe shaders can be used somehow? (I'm a total noob with shaders)

jjp

06-03-2008 20:50:43

I think in practice the approach of using a texture works quite well (Warcraft 3 is doing it this way for example). A 512^2 texture probably is more than enough, unless you have very large units. Simple and has a predictable cost :)

You could also use a shader to draw a circle analytically :twisted: But I guess that would come at an unacceptable cost.

snorr

14-03-2008 12:24:02

Hmm, I'm thinking about using this method (with the projective decal) for projecting larger parts of map-files onto terrain.
Anyone think this could be a problem? Perhaps due to too large textures, or should I just go ahead and try it?

SongOfTheWeave

15-03-2008 22:14:53

Hmm, I'm thinking about using this method (with the projective decal) for projecting larger parts of map-files onto terrain.
Anyone think this could be a problem? Perhaps due to too large textures, or should I just go ahead and try it?


What do you mean "larger parts of map files"?

If you mean the terrain material, then it's a bad idea because well... there's simply no reason to project the material as a decal when you can just write it directly on the terrain mesh as per normal. Also you'll get all sorts of weird looking things, it'll be slower and... well, I can't think of any reason this is a good idea.

Maybe you meant something else...

NoodlesOnMyBack

27-04-2008 03:34:57

Im having a problem trying to add the decals, when the application first start, i see the decal image streached all over the map and no textures, just the decal image, then if i click the screen the decal appears, but the terrain is black, i see this:



This is my material, i put it in the third pass of the first technique as you said.


material ETTerrainMaterial
{
technique
{
// primary splatting technique, requires PS 2.0
// has issues with OpenGL rendering, though...


pass
{
// splatting pass

lighting off

vertex_program_ref ET/Programs/VSLodMorph2
{
}

fragment_program_ref ET/Programs/PSSplat2
{
param_named splatScaleX float 20
param_named splatScaleZ float 20
}

texture_unit
{
// first coverage map, dynamically managed
texture ETSplatting0
}
texture_unit
{
// second coverage map, dynamically managed
texture ETSplatting1
}

// splatting textures
texture_unit
{
texture splatting0.png
}
texture_unit
{
texture splatting1.png
}
texture_unit
{
texture splatting2.png
}
texture_unit
{
texture splatting3.png
}
texture_unit
{
texture splatting4.png
}
texture_unit
{
texture splatting5.png
}
}


pass
{
// lightmap texture pass

scene_blend modulate

vertex_program_ref ET/Programs/VSLodMorph2
{
}

fragment_program_ref ET/Programs/PSLighting
{
}

texture_unit
{
// dynamically created
texture ETLightmap
}

}

//****************************************************
pass
{
//Decals' pass
scene_blend alpha_blend
lighting off
depth_bias 1
depth_check off

texture_unit
{
texture brush.png
}
}
//****************************************************

}

SongOfTheWeave

27-04-2008 08:52:42

Im having a problem trying to add the decals, when the application first start, i see the decal image streached all over the map and no textures, just the decal image, then if i click the screen the decal appears, but the terrain is black, i see this:

Reread the OP, espcially:
"Where decal base is a alpha texture of 2x2 pixels."

I'm not sure what your Brush.png is or what you're expecting to see.

Look at the decal class and note how it shows and hides the decal, it adds a new texture unit to the decal pass that is the REAL image you want to see. decal base should be a blank transparent image so that when the real texture unit is absent, your material appears unaffected.

----

No idea why clicking does anything for you. You'd have to look at your code for the answer to that. What are you doing on clicks? When are you showing/hiding the decal?

----

[edit]

The reason you're seeing what you're seeing, assuming brush.png is the brush.png supplied in the ETM package, is that brush.png is a white gradient that turns to black at the edges. With the texture mode set to clamp, the colour at the edges of the texture is continued out for the rest of the material.

What you're seeing is exactly correct, the image you're using as your decal simply has no transparency, and that's the problem.

NoodlesOnMyBack

27-04-2008 19:50:21

oops, sorry for that i assumed that it was a problem with the material, now its working fine :oops:

MOROHEUZ

30-04-2008 11:14:36

Hi all,

What is ?? "mPincelDecal "

i have a blackout to use the code

mPincelDecal = new ETDecal(mSceneMgr, mTerrainMgr, Vector2(50,50), "decal.png"); //Create decal
mPincelDecal->updatePosition( "where decal is positioned by you" );
mPincelDecal->show();


the declaration is not mPointer ??

??* mPincelDecal

sorry for the noob question.. but dont ask .. will be silly :-)

SongOfTheWeave

30-04-2008 12:01:09

Hi all,

What is ?? "mPincelDecal "

i have a blackout to use the code

mPincelDecal = new ETDecal(mSceneMgr, mTerrainMgr, Vector2(50,50), "decal.png"); //Create decal
mPincelDecal->updatePosition( "where decal is positioned by you" );
mPincelDecal->show();


the declaration is not mPointer ??

??* mPincelDecal

sorry for the noob question.. but dont ask .. will be silly :-)


The section of pseudocode you quoted is a "how your client code should use the decal class" example.

It is not intended to be in the class file (note the plain text above the quoted passage.)

Pincel means pointer in some language that I do not know, I believe. You can call your instance of the Decal class whatever you like. You can rename the class whatever you like for that matter.

MOROHEUZ

30-04-2008 12:06:32

I compile the DemoETSM..

but



ETDecal* mPincelDecal = new ETDecal(mSceneMgr, mTerrainMgr, Vector2(50,50), "decal.png"); //Create decal
mPincelDecal->updatePosition( ?? );
mPincelDecal->show();


is this right ??

Error @ updatePosition :-( error C2660

*?? what musst be here written in

ETSample.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: void __thiscall ETDecal::updatePosition(class Ogre::Vector3)" (?updatePosition@ETDecal@@QAEXVVector3@Ogre@@@Z)".
ETSample.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: void __thiscall ETDecal::show(void)" (?show@ETDecal@@QAEXXZ)".
ETSample.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: __thiscall ETDecal::ETDecal(class Ogre::SceneManager *,class ET::TerrainManager *,class Ogre::Vector2,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (??0ETDecal@@QAE@PAVSceneManager@Ogre@@PAVTerrainManager@ET@@VVector2@2@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)".


new Problem @ this code ;-(



Ogre::Vector3 mPos;


ETDecal* mPointer = new ETDecal(mSceneMgr, mTerrainMgr, Vector2(50,50), "decal.png"); //Create decal
mPointer->updatePosition( mPos );
mPointer->show();


I WILL BE CRAZY like this problem ....

I have installed CEGUI with showing Files (*.mesh) in Folder .. but this Problem make me CRAZY :-(

SongOfTheWeave

01-05-2008 02:57:17

I compile the DemoETSM..

but



ETDecal* mPincelDecal = new ETDecal(mSceneMgr, mTerrainMgr, Vector2(50,50), "decal.png"); //Create decal
mPincelDecal->updatePosition( ?? );
mPincelDecal->show();


is this right ??

Error @ updatePosition :-( error C2660

*?? what musst be here written in


Read the class. The parameters for a function are declared clearly in the function declaration.


ETSample.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: void __thiscall ETDecal::updatePosition(class Ogre::Vector3)" (?updatePosition@ETDecal@@QAEXVVector3@Ogre@@@Z)".
ETSample.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: void __thiscall ETDecal::show(void)" (?show@ETDecal@@QAEXXZ)".
ETSample.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: __thiscall ETDecal::ETDecal(class Ogre::SceneManager *,class ET::TerrainManager *,class Ogre::Vector2,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (??0ETDecal@@QAE@PAVSceneManager@Ogre@@PAVTerrainManager@ET@@VVector2@2@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)".


new Problem @ this code ;-(


It looks like you are missing the .cpp file or it failed to compile.

MOROHEUZ

01-05-2008 10:49:45

I admit it ...
I've tried, either it's VC2008 or I'm too stupid.

it is clearly in the class ... if it is ever made, we know that ..

But there is an error somewhere I do not think ...

I think I write my own thing ... lasts longer, but then I know it fits to my code.

Here the Codesnipe with the Mpointer & MpencilDecal..


// Create RaySceneQuery
mRaySceneQuery = mSceneMgr->createRayQuery( Ray() );

// Create a "pointer" for use on the terrain
Entity* pointer = mSceneMgr->createEntity("Pointer", "sphere.mesh");
mPointer = mSceneMgr->getRootSceneNode()->createChildSceneNode();
mPointer->attachObject(pointer);
mPointer->scale( 0.1 , 0.1 , 0.1 );

//create Decal on the terrain
ETDecal* mPencilDecal = new ETDecal(mSceneMgr, mTerrainMgr, Vector2(50,50), "brush2.png"); //Create decal
mPencilDecal->ETDecal::updatePosition( "what comes here??" );
mPencilDecal->ETDecal::show();





perhaps one knows the solution ... I start my own code to write

SongOfTheWeave

01-05-2008 10:56:31

void updatePosition( Ogre::Vector3 pos );

This is what I meant by read the class.

updatePosition takes a vector. The code you keep posting clearly doesn't work because you have been passing nonsense to this function that expects a vector.

MOROHEUZ

01-05-2008 11:31:28

No... when i use the Vektor3 some Error code follow


ETSample.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: void __thiscall ETDecal::updatePosition(class Ogre::Vector3)" (?updatePosition@ETDecal@@QAEXVVector3@Ogre@@@Z)".
ETSample.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: void __thiscall ETDecal::show(void)" (?show@ETDecal@@QAEXXZ)".
ETSample.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: __thiscall ETDecal::ETDecal(class Ogre::SceneManager *,class ET::TerrainManager *,class Ogre::Vector2,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (??0ETDecal@@QAE@PAVSceneManager@Ogre@@PAVTerrainManager@ET@@VVector2@2@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)".
..\bin\Release\Demo_ETSM.exe : fatal error LNK1120: 3 nicht aufgelöste externe Verweise.


but i have link the ETDecal.h

i have the Materialfile configurated...

I have do anythink....... IT DONT WORKS ON MY PC

CABAListic

01-05-2008 12:43:31

Quite obviously you have not added the ETDecal.cpp to your project. It complains about missing function *implementations*, all of which are contained in the cpp file. You must add it to your project so that it gets compiled.

MOROHEUZ

03-05-2008 14:24:36

Sorry ... @ my Notebook i have a Bug...
Other applications dont work too :-(

I Try it Later @ a other maschine...

i think malware or other problems :-(

BloodyFanatic

16-05-2008 22:21:44

@MOROHEUZ

if you've added those files to the etm project, you've to place _TManagerExport between class and ETDecal like this:

...

#include <Ogre.h>
#include "ETTerrainManager.h"

class _ETManagerExport ETDecal
{
public:

...



can someone post a link to a working decal? i tried to create one myself (it has huge alpha borders), but that is turning my terrain completely red :(

MOROHEUZ

17-05-2008 08:40:57

Oh sorry ...
it works now ... I had a problem with my notebook ...


Windows Vista and SP (vista) for VS2005 are incombatibel ... Left lots of problems for all projects.

vc2008 now I have it and everything is super ...
But thank you for the help ..

Dalon

17-05-2008 22:13:50

Well i have just one problem left - my decal is always black (just the decal, the terrain is rendered just fine). What's wrong?

My application:


My decal.png: (note: it's a white gradient with transparent borders)


An my decalBase.png (2*2 transparent 32 bit png):


I also added the material pass to ETTerrainMaterial:


pass
{
//Decals' pass
scene_blend alpha_blend
lighting off
depth_bias 1
depth_check off

texture_unit
{
texture decalBase.png
}
}


What do i wrong? :cry:

SongOfTheWeave

18-05-2008 05:28:03

Well i have just one problem left - my decal is always black (just the decal, the terrain is rendered just fine). What's wrong?

My application:

My decal.png: (note: it's a white gradient with transparent borders)

An my decalBase.png (2*2 transparent 32 bit png):

I also added the material pass to ETTerrainMaterial:


pass
{
//Decals' pass
scene_blend alpha_blend
lighting off
depth_bias 1
depth_check off

texture_unit
{
texture decalBase.png
}
}


What do i wrong? :cry:


Well.. it looks like it's working. The decal follows the mouse and all that?

The only problem is that it's black not white?

Sounds like a "multiplying rather than adding" mistake... but I'm not sure where that could crop up in this situation.

You don't need to turn the depth check off, but I don't think that will fix your problem.

Hmm, have you checked stupid mistakes yet? Like... you accidentally have a black one and a white one in your directory and you forgot to change your path back to the white one?

What does the rest of your terrain material look like? Have you made any other changes that might somehow impact this? Is your Decal pass last?

BloodyFanatic

18-05-2008 11:40:41

I just tested Dalon's decal and I got the same error: the decal is black instead of white...

But that doesn't solve my other problem with the decal: it is turning the terrain almost completely black.

In the first screen shot the cursor is placed in the top left corner and in the second it is placed in the bottom right corner. It seams to me that the decal size is way to big, but i tested a size of 50,50 and 5,5 with exactly the same result.

the code for decal is copy&pasted in my app and the material is modified as needed for the decal.

If this helps: I use Ogre SVN r7486, windows xp, directx and a nVidia 8800 GTS 512.

Any ideas? this is driving me crazy :?

Edit: removed images, problem solved

Dalon

18-05-2008 20:31:57

Yes, the decal works fine (follow the mouse etc.)

No I just have 1 decal.png there which is now red (but it's displayed black in my editor). Well, I've looked into the wiki and I found this line in ETDecal.cpp:

texState->setAlphaOperation(Ogre::LBX_ADD);

I've played around with the Alpha Op but it's the same (or the decal is invisble in some cases).


EDIT: Ah i got it ^^ decalBase.png was completely alpha 0. Now, that i've set it to ARGB (255, 255, 255, 255) it's coloured just fine ;) But thanx for your replay SongOfTheWeave :)

MOROHEUZ

18-05-2008 20:53:07

hello Dalan,

have you write this in 3rd pass of Materialfile ??

pass
{
//Decals' pass
scene_blend alpha_blend
lighting off
depth_bias 1
depth_check off

texture_unit
{
texture decalBase.png
}
}


in 2nd pass it is black ... in 3rd it is with colour.. (in my code)

Dalon

18-05-2008 20:54:36

Yes it's in the 3rd pass.

MOROHEUZ

18-05-2008 20:57:34

can you post code ??

or send it to me as email (only the dcal when you have more an you dont like to send it to public ??)

Dalon

19-05-2008 00:07:04

I just use the code posted by SongOfTheWeave on page 1 for my ETDecal.cpp and .h (I modified nothing).

On mouseMoved in my FrameListener I call:
mPincelDecal->updatePosition(...);

And in EditorApplication::createScene() I call:
mPincelDecal = new ETDecal(mSceneMgr, mTerrainMgr, Vector2(256, 256), "decal.png");
mPincelDecal->updatePosition(Ogre::Vector3(0, 0, 0));
mPincelDecal->show();


And here is the result:


In my ETTerrainMaterial, I just don't use the lightmap because I just don't want to use it. I also added the decal's pass (it's the 3rd pass) as said (nothing special).

SongOfTheWeave

19-05-2008 01:23:14

I just tested Dalon's decal and I got the same error: the decal is black instead of white...

But that doesn't solve my other problem with the decal: it is turning the terrain almost completely black.

In the first screen shot the cursor is placed in the top left corner and in the second it is placed in the bottom right corner. It seams to me that the decal size is way to big, but i tested a size of 50,50 and 5,5 with exactly the same result.

the code for decal is copy&pasted in my app and the material is modified as needed for the decal.

If this helps: I use Ogre SVN r7486, windows xp, directx and a nVidia 8800 GTS 512.

Any ideas? this is driving me crazy :?


First of all, make a decal image that you can actually tell where it is on the terrain. Your black splotch is pretty useless for testing.

Second of all, for everyone who is having trouble with this piece of code, the decal base image needs to be a 2x2 TRANSPARENT IMAGE. That means ALPHA CHANNEL ON.

I'll stress this again, you need to create a decal base image that is 2px by 2px and TRANSPARENT. The decal image itself can be whatever you like. It should be transparent around all the edges, otherwise you'll get clamp streaking.

100% of the problems so far have been due to people not setting up the material properly or not including the source in their project properly.

As for sizing issues, you need to scale your size in a way that matches your world scale.

----

In conclusion, I use this (though I've modified mine by now) and a bunch of other people have used this. If it doesn't work, you're doing something wrong. Recheck your images and your materials first of all.

BloodyFanatic

19-05-2008 02:58:00

First of all, make a decal image that you can actually tell where it is on the terrain. Your black splotch is pretty useless for testing.

that black splotch IS the problem...


Second of all, for everyone who is having trouble with this piece of code, the decal base image needs to be a 2x2 TRANSPARENT IMAGE. That means ALPHA CHANNEL ON.

I'll stress this again, you need to create a decal base image that is 2px by 2px and TRANSPARENT. The decal image itself can be whatever you like. It should be transparent around all the edges, otherwise you'll get clamp streaking.


the decalbase is a 2x2 alpha enabled image and the decalbase has also a alpha border...

with dalon's white gradient decal, i get the beforehand posted results (now in white because of the correct decalBase.png). take a close look on the two images in my last post.
as i already said, in the first screen shot the cursor is placed in the top left corner and in the second it is placed in the bottom right corner.
you will notice a difference depending on the cursor position, which means the decal code is working.
it seams, that the scaling doesn't work, since i tested 50, 5 and .5. the result was in each case identical.

Edit: images removed, problem solved

SongOfTheWeave

19-05-2008 04:13:56

How big is your terrain in ogre units? (as opposed to # of verticies)

BloodyFanatic

19-05-2008 10:01:04

How big is your terrain in ogre units? (as opposed to # of verticies)

the terrain in the screenshots is in ogre units 129x129 big with a scale of 1.

your question gave me an idea: i created a completely new one: 129x129 with a scale of 10. here's the result:

the decal image and placement works as expected, but the sizing doesn't work at all. i tested it with:

switch ( evt.GetKeyCode() )
{
case 'U': if ( mDecal ) mDecal->updateSize( Ogre::Vector2( 50, 50 ) ); break;
case 'I': if ( mDecal ) mDecal->updateSize( Ogre::Vector2(.01f, 0.01f ) ); break;
}


but both give the same result :?

btw: if i understand the decal 'sizing' code correctly, there isn't any sizing??

void ETDecal::updateSize(Ogre::Vector2 size)
{
if( mSize != size )
{
// save param
mSize = size;

// update aspect ratio
mFrustum->setAspectRatio(mSize.x/mSize.y);

// set fovy so that tan = 1, so 45 degree
mFrustum->setFOVy(Ogre::Degree(45));

// set near clip plane according to fovy:
// distance = halfsize.y / tan(fovy)
mFrustum->setNearClipDistance(mSize.y);
}
}


Edit: removed image, problems solved

SongOfTheWeave

19-05-2008 12:16:09

btw: if i understand the decal 'sizing' code correctly, there isn't any sizing??

Huh. Well I looked back through my code and it looks like I may have encountered the same problem a long time ago because I delete and recreate the decal every time it needs to be resized (which isn't that often.)

First try hiding it, resizing it, then showing it. I don't expect that to work but if it does, the result would be diagnostic.

Then try deleting and recreating it with the new size. This will probably work, though, to be honest, I'm not entirely sure why it works, if calling updateSize doesn't.

If THAT doesn't work, I'll post my current version of the class because I know it works.

SongOfTheWeave

19-05-2008 12:42:04

New Version

  1. Creates it's own pass in the terrain material as needed.[/*:m]
  2. Is not restricted to being the 3rd pass.[/*:m]
  3. Still only handles 1 technique.[/*:m]
  4. Usage is the same as the old version. decalBase.png must be a 2px x 2px transparent image. You pass whatever image you want to use as the decal to the ctor. If you need decalBase.png to be named something else, modify the string literal in DecalCursor::init[/*:m][/list:u]

    /**
    * @file DecalCursor.h
    * @author Jesse Wright - www.cutthroatstudios.com
    * @note Modified from Brocan's example on the Ogre forums
    */

    #ifndef SANGUIS_DECALCURSOR_H
    #define SANGUIS_DECALCURSOR_H

    #include "OgreMaterial.h"
    #include "OgreVector3.h"
    #include "OgreVector2.h"

    // Declare these classes, don't have to include them until the .cpp
    namespace Ogre
    {
    class SceneManager;
    class SceneNode;
    class Frustum;
    class TextureUnitState;
    class Pass;
    }

    /**
    * @class DecalCursor
    * @author Jesse Wright - www.cutthroatstudios.com
    * @date Created on 12/25/2007
    * @date Last modified 4/25/2007
    */
    class DecalCursor
    {
    public:
    DecalCursor(Ogre::SceneManager* man,
    Ogre::MaterialPtr terrainMat,
    Ogre::Vector2 size,
    std::string tex);
    ~DecalCursor();

    inline bool isVisible() const { return m_bVisible; }
    Ogre::Vector3 getPosition() const;

    void show();
    void hide();

    void setPosition(Ogre::Vector3 pos);
    void setSize(Ogre::Vector2 size);

    private:
    void init(Ogre::Vector2 size, std::string tex);
    void showTerrainDecal();
    void hideTerrainDecal();


    Ogre::Vector3 m_pos; /**< @brief position of the center of the decal */
    Ogre::Vector2 m_size; /**< @brief size of decal */

    std::string m_sTexName; /**< @brief texture to apply */

    Ogre::SceneNode* m_nodeProj; /**< @brief the projection node */
    Ogre::Frustum* m_frustProj; /**< @brief the projection frustum */
    Ogre::TextureUnitState* m_texState; /**< @brief pointer to the texture unit state in the pass */
    Ogre::Pass* m_pass; /**< @brief pointer to the decal pass */
    Ogre::MaterialPtr m_terrainMat; /**< @brief sharedptr to the terrain material */

    Ogre::SceneManager* m_sceneMgr; /**< @brief Pointer to the application's Ogre::SceneManager */

    bool m_bVisible; /**< @brief true if the decal visible, otherwise false */
    };

    #endif


    /**
    * @file DecalCursor.cpp
    * @author Jesse Wright - www.cutthroatstudios.com
    * @date Created on 12/25/2007
    * @date Last modified 4/25/2007
    * @note Modified from Brocan's example on the Ogre forums
    */

    #include "SanguisPrerequisites.h"

    #include "OgreSceneManager.h"
    #include "OgreTextureManager.h"
    #include "OgreSceneNode.h"
    #include "OgreFrustum.h"
    #include "OgreTextureUnitState.h"
    #include "OgrePass.h"

    #include "DecalCursor.h"

    /**
    * @brief The length of one meter in ogre units
    * @todo Set this to something meaningful for your project!
    */
    static const float METER_SCALE = 1.0f;

    DecalCursor::DecalCursor(Ogre::SceneManager* man,
    Ogre::MaterialPtr terrainMat,
    Ogre::Vector2 size,
    std::string tex)
    {
    m_bVisible = false;
    m_nodeProj = 0;
    m_pass = 0;
    m_frustProj = 0;
    m_texState = 0;
    m_sceneMgr = man;
    m_terrainMat = terrainMat;

    init(size, tex);
    }

    DecalCursor::~DecalCursor()
    {
    hide();

    // delete frustum
    m_nodeProj->detachAllObjects();
    delete m_frustProj;

    // destroy node
    m_nodeProj->getParentSceneNode()->removeAndDestroyChild(m_nodeProj->getName());
    }

    void DecalCursor::init(Ogre::Vector2 size, std::string tex )
    {
    // create a new pass in the material to render the decal
    m_pass = m_terrainMat->getTechnique(0)->getPass("Decal");
    if (!m_pass)
    {
    Ogre::Technique* techPref = m_terrainMat->getTechnique(0);
    m_pass = techPref->createPass();
    m_pass->setName("Decal");
    m_pass->setLightingEnabled(false);
    m_pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
    m_pass->setDepthBias(2.5, 2.5);
    m_pass->setFog(true);
    m_pass->createTextureUnitState("decalBase.png");
    }

    // init projective decal
    // set up the main decal projection frustum
    m_frustProj = new Ogre::Frustum();
    m_nodeProj = m_sceneMgr->getRootSceneNode()->createChildSceneNode();
    m_nodeProj->attachObject(m_frustProj);
    m_frustProj->setProjectionType(Ogre::PT_ORTHOGRAPHIC);
    m_nodeProj->setOrientation(Ogre::Quaternion(Ogre::Degree(90), Ogre::Vector3::UNIT_X));

    /* Commented out for general use. If you are using mouse picking in your scene, set this to an unselectable flag otherwise you may find the frustum in your ray queries. */
    //m_frustProj->setQueryFlags(Sanguis::UNSELECTABLE);

    // set given values
    setSize(size);
    m_sTexName = tex; // texture to apply

    // load the images for the decal and the filter
    Ogre::TextureManager::getSingleton().load(m_sTexName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, 1);

    m_bVisible = false;
    }

    Ogre::Vector3 DecalCursor::getPosition() const
    {
    return m_pos;
    }

    void DecalCursor::show()
    {
    if(!m_bVisible)
    {
    m_bVisible = true;
    showTerrainDecal();
    setPosition(m_pos);
    }
    }

    void DecalCursor::hide()
    {
    if (m_bVisible)
    {
    m_bVisible = false;
    hideTerrainDecal();
    }
    }

    void DecalCursor::setPosition(Ogre::Vector3 pos)
    {
    // don`t do anything if pos didn`t change
    if (m_pos != pos)
    {
    m_pos = pos; // save the new position
    // Set the projection coming from some distance above the current position.
    m_nodeProj->setPosition(pos.x, pos.y + (10.0 * METER_SCALE), pos.z);
    }
    }

    void DecalCursor::setSize(Ogre::Vector2 size)
    {
    if (m_size != size)
    {
    m_size = size;

    // update aspect ratio
    m_frustProj->setAspectRatio(m_size.x / m_size.y);

    // set fovy so that tan = 1, so 45 degrees
    m_frustProj->setFOVy(Ogre::Degree(45));

    // set near clip plane according to fovy:
    // distance = halfsize.y / tan(fovy)
    m_frustProj->setNearClipDistance(m_size.y);
    }
    }

    // Protected

    void DecalCursor::showTerrainDecal()
    {
    if (!m_texState)
    {
    // set up the decal's texture unit
    m_texState = m_pass->createTextureUnitState(m_sTexName);
    m_texState->setProjectiveTexturing(true, m_frustProj);
    m_texState->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
    m_texState->setTextureFiltering(Ogre::FO_POINT, Ogre::FO_LINEAR, Ogre::FO_NONE);
    m_texState->setAlphaOperation(Ogre::LBX_ADD);
    }
    }

    void DecalCursor::hideTerrainDecal()
    {
    if (m_texState)
    {
    m_pass->removeTextureUnitState(m_pass->getTextureUnitStateIndex(m_texState));
    m_texState = 0;
    }
    }

BloodyFanatic

19-05-2008 14:38:57

First try hiding it, resizing it, then showing it. I don't expect that to work but if it does, the result would be diagnostic.

does not work

Then try deleting and recreating it with the new size. This will probably work, though, to be honest, I'm not entirely sure why it works, if calling updateSize doesn't.

does not work either :(

If THAT doesn't work, I'll post my current version of the class because I know it works.

thanks, i tested both the old version and your modification, but neither worked in any case.

which ogre version do you use? maybe it's because my ogre version is too new... i use SVN trunk r7486 which tags itself as "Version 1.7.0 (Cthugha)"

i will try the decal code with the etm sample and the 1.4.8 version of ogre to see if that's causes the failure :roll:


btw: if you're creating a pass, you should remove it when it isn't needed anymore (dtor) ;)

BloodyFanatic

19-05-2008 16:08:28

ok, i think the new ogre version is causing the failure.
everything works perfectly under ogre 1.4.7 ( well, at least in the sample )

i'll report here if i find out more. stay tuned ;)

Edit:
Yay, got it after a close look in the shoggoth changelog:
Orthographic projection now allows explicit setting of orthographic window size


only one little code change is needed (in updateSize / setSize )

#if OGRE_VERSION_MAJOR == 1 && OGRE_VERSION_MINOR <= 4
m_frustProj->setAspectRatio(m_size.x / m_size.y);
#else
m_frustProj->setOrthoWindow ( m_size.x, m_size.y );
#endif


Add this to the posted code, SongOfTheWeave, for shoggoth compatibility. This, and the pass removing at decal destruction and your code is perfect for now ;)

I'd also like to say thank you for your help, i really appreciate it.

Edit2:

dtor addition:

// remove the decal pass
if ( m_pass )
{
m_terrainMat->getTechnique(0)->removePass( m_pass->getIndex() );
m_pass = 0;
}

BloodyFanatic

19-05-2008 18:06:20

New Version

changes/additions:
  1. decal pass removing at dtor[/*:m]
  2. Ogre Shoggoth fix added[/*:m]
  3. parameter changed to reference[/*:m]
  4. setPosition 'optimization' removed[/*:m]
  5. proper initialization[/*:m][/list:u]

    @SongOfTheWeave: if you have any problems with what i've done, just say so and i removed it immediately ;)

    Edit: removed code since SongOfTheWeave put it in the first post of this thread

Squirell

19-05-2008 21:51:44

One comment at BloodyFanatic


only one little code change is needed (in updateSize / setSize )


#if OGRE_VERSION_MAJOR == 1 && OGRE_VERSION_MINOR < 4
m_frustProj->setAspectRatio(m_size.x / m_size.y);
#else
m_frustProj->setOrthoWindow ( m_size.x, m_size.y );
#endif


Add this to the posted code, SongOfTheWeave, for shoggoth compatibility. This, and the pass removing at decal destruction and your code is perfect for now


It should be OGRE_VERSION_MINOR <=4.

Other than that it seems good to me.

BloodyFanatic

19-05-2008 22:57:02

It should be OGRE_VERSION_MINOR <=4.

thanks for discovering a minor mistake, is fixed ;)

SongOfTheWeave

20-05-2008 04:16:33

I like you, you're opinionated.

I have no problem with what you've done. I've replaced the code in the OP with your last posted version.



btw, I used to be a violent proponent of "proper" initialisation but I find as time goes by, I'm more and more a proponent or readability (except in inheritance cases where you need things to be built in strict order.)

BloodyFanatic

20-05-2008 09:34:43

I like you, you're opinionated.

I have no problem with what you've done. I've replaced the code in the OP with your last posted version.


hehe, ok ;)

btw, I used to be a violent proponent of "proper" initialisation but I find as time goes by, I'm more and more a proponent or readability (except in inheritance cases where you need things to be built in strict order.)

well, i find it readable enough ;) everyone has it's own style of coding.
PS: i don't like your m_foo member variable prefix ;)

BloodyFanatic

23-05-2008 16:49:38

I just wanna post some tips and advices for the decal, because I had some problems while editing my terrain. With terrain scaling it had the wrong size and it haven't represented the real editing position with the code from the ETM sample. I spend some time on fixing this behaviour and these are my results:
  1. feed the x and z vertices into the terraininfo in order to get the correct terrain position, this will "snap" the decal to the vertices ( see vertexToPosX/Z)
    [/*:m]
  2. if you've scaled your terrain, you'll need to apply the same scale to size of the decal (not the brush!)[/*:m][/list:u]with this you should be able to edit your decal as exact as possible ;)

brainless

16-07-2008 21:19:06

A quick question, I cannot get the colors to work correctly and I'm not sure what's wrong (my decals are always black), could anyone upload their working coloured image files?

Also, since it's on the forum it's public domain, but what license is on it (if any)?

pra

17-07-2008 01:26:36

that's mine:

you need an alpha channel. or maybe it's the decalBase.png causing the problems.

and, if i'm alerady posting here, how do you calculate the decal's size from the heightmap resolution, terrain extends and the brush's size?

brainless

17-07-2008 12:56:13

Ok, so that's all black for me too... I guess it's in decalBase.png then :(

edit:
Alright, I found the problem (or actually, someone else did :D). In case others need this in the future, here's my decalBase.png:



And because it's so incredibly small, here's a link ;)
http://img229.imageshack.us/img229/8036/decalbasekh8.png

pra

18-07-2008 02:27:57

so, i'm not really sure if i should post it here, but since it has something to do with the decal:
Ok, the problem is: after succesfully implementing the decal, I noticed that the decal and the actual manipulation are not synchronous:




this is 513x513 terrain. with 129x129, it is even worse.
It is also always shifted in the same direction, no matter how i rotate my camera.

I execute the following code on mouseMoved:
Real mouseX = 0.5;
Real mouseY = 0.5;

Level *lvl = app->currentLevel;

CEGUI::Point pt = CEGUI::MouseCursor::getSingletonPtr()->getPosition();
mouseX = pt.d_x/app->getRenderWindow()->getWidth();
mouseY = pt.d_y/app->getRenderWindow()->getHeight();


Ray mouseRay = lvl->getMainCam()->getCameraToViewportRay(mouseX,mouseY);



// since ETM is no longer a scene manager, we don't use a ray scene query,
// but instead query the terrain info directly
std::pair<bool, Vector3> result = lvl->getTerrainInfo()->rayIntersects(mouseRay);

if(result.first)
{
deformPosition = result.second;
}

and then, in frameStarted, the Vector3 deformPosition is used to get the deformation coordinates:
int x = lvl->getTerrainInfo()->posToVertexX(deformPosition.x);
int z = lvl->getTerrainInfo()->posToVertexZ(deformPosition.z);

and to position the decal:
decal->setPosition(deformPosition);
haven't found anything here, so, what have I done wrong?

CABAListic

18-07-2008 08:44:52

Nothing really. The deformation and painting are done on a fixed grid (obviously you can only modify a texture at pixel step) while your decal moves freely. So when you translate the decal coordinates to the editing position, it gets cut off to fit the grid size.
The nicest way to deal with this is to lock the decal position to the grid, too. From your mouse position you can get the decal display position by vertexToPosX(posToVertexX(deformPosition.x)) etc.. You'll probably also need to apply a fixed offset to this, but once you have that, the decal will move in fixed steps and therefore always align with the edit position.

ETL v3 accepts the real Ogre coordinates directly as the edit positions and uses interpolation to somewhat hide the fixed grid underneath. This will make editing seem smoother than it really is.

BloodyFanatic

18-07-2008 10:57:22

my posts seem to be invisible? i had also troubles with that and posted a solution already ^^ scroll up or click here.
I could explain it better if someone doesn't understand what I wrote...

pra

18-07-2008 14:23:06

my posts seem to be invisible? i had also troubles with that and posted a solution already ^^ scroll up or click here.
I could explain it better if someone doesn't understand what I wrote...

:doh:
ok, now, I'm officially blind^^

thanks you two

brainless

19-07-2008 10:35:46

I would like to use these decals for a form of unit selection (like the Warcraft 3 example on page 1 of this thread). No matter what I do though, when I add a second decal both end up black. I've tried to make both use the same pass (with 2 texture states... no luck) and to just create a second decalCursor, but both methods end up looking the same. Any idea how to do this?

CABAListic

19-07-2008 10:45:00

You don't really want to do that. Each projective decal is going to be a separate pass over the terrain, so it's quite expensive performance-wise. If you're even thinking of having more than 2-3, I wouldn't even bother any further. To be able to scale such a thing, you really need a separate mesh based solution.

brainless

19-07-2008 10:54:17

Alright, I'll dive into that instead. Thanks :)

brainless

19-07-2008 22:58:16

Alright, it took all day, but I've got mesh decals working properly! I'll see if I can release the code some time soon (though I'll be out for a few days, so please hang on). Here's a little teaser:



The green circle on the right is a projective decal. The other 3 are all mesh decals. The mesh follows the terrain exactly. I haven't tried moving the mesh yet (by mouse for example), I'm probably up for a few problems there... the mesh has to be regenerated for that to work. I'm not sure what the performance is like yet either, so that may need to be tackled too.

SongOfTheWeave

23-07-2008 22:47:18

Also, since it's on the forum it's public domain, but what license is on it (if any)?

Public domain means no liscence. Anyone can use it for anything without any obligation.

However, claiming that it is your own work is still plagiarism.

SongOfTheWeave

23-07-2008 23:02:56

It is also always shifted in the same direction, no matter how i rotate my camera.

If you don't want to clamp the decal to verticies as BloodyFanatic suggests (I don't like how that approach looks and feels) you can add 0.5 * TERRAIN_SCALE to the x and z components of the cursor location before passing it into the ETM function to get the vertex. IIRC the ETM function always rounds down, adding .5 * terrain scale will result in a more natural feel.

where TERRAIN_SCALE is the distance in ogre units between terrain verticies.

pra

24-07-2008 01:28:49

If you don't want to clamp the decal to verticies as BloodyFanatic suggests (I don't like how that approach looks and feels) you can add 0.5 * TERRAIN_SCALE to the x and z components of the cursor location before passing it into the ETM function to get the vertex. IIRC the ETM function always rounds down, adding .5 * terrain scale will result in a more natural feel.

where TERRAIN_SCALE is the distance in ogre units between terrain verticies.

Hmm, how exactly do you get TERRAIN_SCALE?
I did box.getSize()/hmSize, where box is terrainInfo->getExtends() and hmSize is the size of the heightmap

it seems to be slightly better, but still not perfect

edit: just tried the other solution. it is exactly like yours: it works fine for texture painting, but there is still a little offset when editing terrain:

it seems to be better compared to previous, though.
I do the following:
deformPosition = result.second;
terrainExtends = mTerrainInfo->getTerrainExtends();
Vector3 hmSize(hmWidth,1,hmHeight);//heightmap dimensions
Vector3 tScale = terrainExtends.getSize()/hmSize;
deformPosition.x = mTerrainInfo->posToVertexX(deformPosition.x);
deformPosition.z = mTerrainInfo->posToVertexZ(deformPosition.z);
deformPosition *= tScale;
deformPosition += terrainExtends .getMinimum();

SongOfTheWeave

24-07-2008 02:54:05

where TERRAIN_SCALE is the distance in ogre units between terrain verticies.

It is whatever you set the x,z extents to divided by the number of verticies - 1. Just think about it.

[edit]
Actually you got that bit right but I'm not sure what exactly you're doing with it after that point.

do this:

deformPos += Ogre::Vector3(0.5 * TERRAIN_SCALE, 0, 0.5 * TERRAIN_SCALE);


I'm not sure why the snippet you posted above is working at all...

[edit2]
You need to do the deformPos modification to the OGRE SPACE POSITION. That means BEFORE CALLING positionToVertex!

It makes no sense to be modifying a vertex space value (in which only integer values are relevant) by a value calculated in ogre space.

pra

24-07-2008 20:09:55

what I did was converting the Ogre position to vertex position, and then back, in order to get it aligned to the tiles

edit: it was the -1 while calculating the terrain scale. deforming works fine now, but now there is a little offset while painting textures o_O

CABAListic

24-07-2008 21:13:42

Yes, that's because the pixels of the coverage maps don't usually align with the terrain vertices, therefore you must apply different offsets to each. That's also why I improved editing features in ETL v3 to make this all a lot more accessible ;)

dudeabot

03-08-2008 15:16:19

the decal doesnt seem to be placed properly whenever im deforming the terrain:



is there a way to 'fix' this?

it looks correct when im moving the mouse

SongOfTheWeave

04-08-2008 06:14:59

the decal doesnt seem to be placed properly whenever im deforming the terrain:

is there a way to 'fix' this?

it looks correct when im moving the mouse


Please read a thread before you post in it.

This exact question has been covered extensively. Read the previous posts to find the answer.

dudeabot

04-08-2008 15:26:07

humm this is how i did it (im not sure if it is 100% correct)


Vector3 deformPos = terrain->getDecalCursor()->getPosition();
Vector3 tScale = terrain->getTerrainInfo()->getScaling();
deformPos += Ogre::Vector3(tScale.x, 0, tScale.z);
int x = terrain->getTerrainInfo()->posToVertexX(deformPos.x);
int z = terrain->getTerrainInfo()->posToVertexZ(deformPos.z);
// now tell the ETM to deform the terrain
terrain->getTerrainManager()->deform(x, z, terrain->getBrush(), brushIntensity);

SongOfTheWeave

05-08-2008 06:38:59

humm this is how i did it (im not sure if it is 100% correct)

If it makes your cursor behave the way you want it to, then it's right :)

The snippet you posted looks about like what I did in my project (it's been a while since i worked with that part of it.) I liked that solution better than snapping the cursor to verticies, which made it feel like the mouse was handling funny.

dudeabot

11-08-2008 20:11:30

hello, i have one doubt, i wanted to use the brush as the decal, but it doesnt work quite well.

my terrain gets darkened, as the brush had no alpha. If i enable the alpha in the brush the deformation doesnt work.

SongOfTheWeave

14-08-2008 22:24:58

hello, i have one doubt, i wanted to use the brush as the decal, but it doesnt work quite well.

my terrain gets darkened, as the brush had no alpha. If i enable the alpha in the brush the deformation doesnt work.


yeah... I think it would be best to use separate images for the decal image and the brush. Using the same one is probably an unneccessary over-complication.

kungfoomasta

30-10-2008 20:00:18

brainless, you never responded with your mesh decals? I think for wc3 style units I'll end up writing some kind of ring class, where you can configure radius, color, number of segments, and align with ground. When repositioned you would have to regenerate the ring, in my case I would use physx and raycast down while using collision filtering to determine positions. That way you can walk over bridges or meshes that are deemed ground. But I wonder how expensive this will be..

zhucde

25-11-2008 02:41:34

Projective Decal once call will redraw the terrain once, so , if you create lots of decal in the terrain, the FPS will decrease qukckly.

so if you have lots of decals to draw, the best way is use MeshDecal, like PLSM2, but i don't know how to use it in ETM,

who knows?

SongOfTheWeave

05-12-2008 19:55:04

Projective Decal once call will redraw the terrain once, so , if you create lots of decal in the terrain, the FPS will decrease qukckly.

so if you have lots of decals to draw, the best way is use MeshDecal, like PLSM2, but i don't know how to use it in ETM,

who knows?


You'll probably have to build your own. The best approach would probably be to use a manual object and either turn the depth check off or modify the geometry dynamically so that it wraps over the contours of the terrain as you move it around. The second looks better but I suppose that depends on what you want it to look like.

LaGhoule

19-03-2009 17:13:16

Hi,
i got a wierd problem with the DecalCursor class.

Everything work find exept the decal color is affected by the current material color.

There is the "floor" material
material VERTEX_terrain01
{
technique
{
pass
{
specular 1 1 1 1 0
emissive 1 1 1 1

vertex_program_ref VERTEX_terrain01_light1_vs
{
param_named_auto lightPosition light_position 0
param_named_auto world transpose_world_matrix
param_named_auto worldI inverse_transpose_world_matrix
param_named_auto wvp transpose_worldviewproj_matrix
}

fragment_program_ref VERTEX_terrain01_light1_ps
{
param_named_auto lightColor light_diffuse_colour 0
}

texture_unit
{
texture VERTEX_plainGrass.png
}

texture_unit
{
texture VERTEX_dirt03.png
}

texture_unit
{
texture VERTEX_rocks02.png
}
}

pass
{
specular 1 1 1 1 0
emissive 1 1 1 1
scene_blend add
depth_write off

vertex_program_ref VERTEX_terrain01_light1_vs
{
param_named_auto lightPosition light_position 1
param_named_auto world transpose_world_matrix
param_named_auto worldI inverse_transpose_world_matrix
param_named_auto wvp transpose_worldviewproj_matrix
}

fragment_program_ref VERTEX_terrain01_light1_ps
{
param_named_auto lightColor light_diffuse_colour 1
}

texture_unit
{
texture VERTEX_plainGrass.png
}

texture_unit
{
texture VERTEX_dirt03.png
}

texture_unit
{
texture VERTEX_rocks02.png
}
}

}

}


There is the exemple....both screen shot have been take on the same material, but the decal doesnt have the same color.



Any idea what i did wrong?

Tx a lot and sorry for my bad english writing!

Bruno

LaGhoule

28-03-2009 17:14:51

No one can help me?

SongOfTheWeave

31-03-2009 18:18:03

I don't have any insight into your problem as you've either changed or renamed all your shaders, and I'm not sure the scope of your changes. Perhaps you could try to describe what you've changed in your shaders.

I can't think of a reason why what you're seeing would happen if you haven't changed the shaders.

mrotakhi

16-08-2010 21:24:06

I tried to put a decal on the default terrain manager by following this code exactly.

I've fixed the black decal issue by setColourOpertionEx();

However, for the life of me, I am unable to re-position or re-size the decal by setting the aspectRation and orthoWindowHeight.

The decal doesn't seem to be affected by the position or size of the frustum.

The only way that has any effects on the decal is by scaling and scrolling the texture unit.

am I missing something, or is this code only applicable to ETM?

thanks

shenjoku

03-10-2011 22:22:17

Very nice, I had to make some tweaks to make this work with the latest Ogre but they were simple enough. Works perfectly and it's much better than the tutorial version which doesn't work at all. Thanks for this :)