投影贴花

Draws a decal on your terrain that can be arbitrarily positioned. Suitable for following the mouse and indicating brush size for editing.

How to Use:


Create the following files and include them in your project
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
Create an instance of DecalCursor in your project.
Call DecalCursor::show() to make it appear and hide to hide it.
Call DecalCurstor::setPosition(Vector3) to move the decal around (for example, in your mouseMoved handler.)
======================================================================

 

#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
{
   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

==========================================================================

 

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

#include "DecalCursor.h"


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;
   }
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值