Ogre的WeaponTrail

转载自:http://blog.sina.com.cn/s/blog_67b708440100ifa4.html

就是刀光拖尾效果,这个挺有意思,Ogre竟然单写了一个类来实现这个功能。名字叫做RibbonTrail。
不过这个类似乎并不太好用,实现的效果是从手握武器的位置沿相对衬的两个方向延伸出片,这样的话,如果手里是把剑,那么效果就不对了。如果手里的武器是长枪,因为手握得位置也不是正中间,所以也不对。。。。

于是又有人写了一个WeaponTrial类来解决这个问题。但是他没有处理缩放问题,所以在连接点从父节点带来的缩放矩阵影响下,刀光的宽度就会有问题,除非你的人物的骨骼完全没有缩放。

另外这个WeaponTrial的计算方法确实是相当费。需要重新更新整个的骨骼动画。

Ogre的一些周边代码的水平大抵都是如此,基本的意思有了,不过照工业标准总是差着一些。拿回来需要好好的修改才行。但用来玩玩还是足够的。

下面是修改后的截图和代码。
这里写图片描述

//.h
#pragma once
#include<list>
#include "Ogre.h"
using namespace Ogre;

class WeaponTrail
{
public:
    WeaponTrail(Ogre::String  name, SceneManager* s );
    virtual ~WeaponTrail();

    /// Set the weapon entity to which the trail is attached
    void setWeaponEntity(Entity* p_WeaponEntity);
    /// update the weapon trail
    void onUpdate(float p_DeltaT);
    /// Set the name of the material to use for the trail
    void setMaterialName(const String& p_MaterialName);
    /// set the initial color of the start of segments
    void setSegmentStartInitialColor(const Ogre::ColourValue& p_Color);
    /// get the initial color of the start of segments
    const Ogre::ColourValue& getSegmentStartInitialColor() const;
    /// set the initial color of the end of segments
    void setSegmentEndInitialColor(const Ogre::ColourValue& p_Color);
    /// get the initial color of the end of segments
    const Ogre::ColourValue& getSegmentEndInitialColor() const;
    /// set how the color of the start of segments will change over time
    void setSegmentStartColorChange(const Ogre::ColourValue& p_ColorChange);
    /// get how the color of the start of segments will change over time
    const Ogre::ColourValue& getSegmentStartColorChange() const;
    /// set how the color of the start of segments will change over time
    void setSegmentEndColorChange(const Ogre::ColourValue& p_ColorChange);
    /// get how the color of the start of segments will change over time
    const Ogre::ColourValue& getSegmentEndColorChange() const;
    /// Return the max vertex count of the trail
    inline int getMaxSegmentCount() const {return m_MaxSegmentCount;}
    /// set the width
    void setWidth(float p_Width) {m_Width = p_Width;}
    /// get the width
    float getWidth() const {return m_Width;}
    /// Set whether new segments are added
    void setActive(bool p_Active = true);
    /// Get whether new segments are added
    bool isActive() const;
    /// Get whether there are currently segments in the list
    bool isVisible() const;

protected:
    /// a trail segment
    struct TrailSegment
    {
        /// start position
        Vector3 segmentStart;
        /// end position
        Vector3 segmentEnd;
        /// current segment start color
        Ogre::ColourValue segmentStartColor;
        /// current segment end color
        Ogre::ColourValue segmentEndColor;
    }; // end TrailSegment struct declaration

    /// typedef for a list of trail segments
    typedef std::list<TrailSegment> TrailSegmentList;
    /// the list of currently active trail segments
    TrailSegmentList m_SegmentList;
    /// Initializes the manual object
    void init();
    /// Uninitializes the manual object
    void uninit();

    ManualObject* m_TrailObject;    //!< the dynamically changed mesh representing the trail
    Entity* m_WeaponEntity;         //!< the entity representing the weapon;
    Node* m_WeaponNode;             //!< the node the tracked entity is attached to
    SceneNode* m_TrailNode;         //!< the node the manual object is attached to
    String m_MaterialName;          //!< the name of the material to use
    const int m_MaxSegmentCount;    //!< the maximum number of segments the trail will consist of
    Ogre::ColourValue m_SegmentStartInitialColor; //!< the initial color of start segments
    Ogre::ColourValue m_SegmentEndInitialColor;   //!< the initial color of end segments
    Ogre::ColourValue m_SegmentStartColorChange;  //!< how the color of start segments will change over time
    Ogre::ColourValue m_SegmentEndColorChange;    //!< how the color of end segments will change over time
    float m_Width;                      //!< the width of the trail
    bool m_IsActive;                    //!< flag indicating whether new segments are generated
    SceneManager* mSceneMgr;
    Ogre::String  mName;
}; // end of WeaponTrail class declaration


//.cpp
#include "WeaponTrail.h"

//---------------------------------------------------------------------------//
WeaponTrail::WeaponTrail(Ogre::String  name, SceneManager* s )
    :m_TrailObject(0),
    m_MaxSegmentCount(30),
    mSceneMgr(s),
    m_IsActive(true)
{
     m_SegmentStartColorChange = Ogre::ColourValue(1.0,1.0,1.0,1.0);
     m_SegmentEndColorChange = Ogre::ColourValue(1.0,1.0,1.0,1.0);
     m_SegmentStartInitialColor = Ogre::ColourValue(0.6,0.5,0.8,1);
     m_SegmentEndInitialColor = Ogre::ColourValue(1.0,0.2,1.0,1);
     m_SegmentStartColorChange *= 3.0;
     m_SegmentEndColorChange *= 3.0;
     m_Width = 30.0;
     setWeaponEntity(0);
     init();
}
//---------------------------------------------------------------------------//
WeaponTrail::~WeaponTrail()
{
     uninit();
}
//---------------------------------------------------------------------------//
void WeaponTrail::init()
{
     // create object
     m_TrailObject =mSceneMgr->createManualObject(mName);
     m_TrailObject->estimateVertexCount(m_MaxSegmentCount * 2);
     m_TrailObject->setDynamic(true);
     m_TrailObject->begin("mat_trail", Ogre::RenderOperation::OT_TRIANGLE_STRIP);

     // fill the object (the actual data does not matter here)
     for(int i=0; i<m_MaxSegmentCount; ++i)
     {
          m_TrailObject->position(0, 0, -i*20);
          m_TrailObject->textureCoord(0,0);
          m_TrailObject->colour(1,0,0,1);
          m_TrailObject->position(0, 30, -i*20);
          m_TrailObject->textureCoord(1,0);
          m_TrailObject->colour(1,0,0,1);
     }
     m_TrailObject->end();

     // create node and attach object
     m_TrailNode =mSceneMgr->getRootSceneNode()->createChildSceneNode();
     m_TrailNode->attachObject(m_TrailObject);
     m_TrailObject->setVisible(false);
}
//---------------------------------------------------------------------------//
void WeaponTrail::uninit()
{
     m_IsActive = false;

     // detach object and remove node
     m_TrailNode->detachObject(m_TrailObject);
     mSceneMgr->getRootSceneNode()->removeAndDestroyChild(m_TrailNode->getName());

     // remove object
     m_TrailObject->setVisible(false);
     mSceneMgr->destroyManualObject(m_TrailObject);
}
//---------------------------------------------------------------------------//
void WeaponTrail::setWeaponEntity(Entity* p_WeaponEntity)
{
     m_WeaponEntity = p_WeaponEntity;
     if (m_WeaponEntity)
     {   
          m_WeaponNode = m_WeaponEntity->getParentNode();
     }
     else
     {
          m_WeaponNode = 0;
     }
}
//---------------------------------------------------------------------------//
void WeaponTrail::onUpdate(float p_DeltaT)
{
     // early out
     if(!isActive() && !isVisible())
     {
          return;
     }
     if (!m_WeaponEntity || !m_WeaponNode)
     {
          return;
     }
     if (!m_TrailObject)
     {
          return;
     }

     m_TrailObject->setVisible(true);

     // iterate over the current segments, apply alpha change
     for(TrailSegmentList::iterator it = m_SegmentList.begin();it != m_SegmentList.end();)
     {
          (*it).segmentStartColor -= m_SegmentStartColorChange * p_DeltaT;
          (*it).segmentEndColor -= m_SegmentEndColorChange * p_DeltaT;
          (*it).segmentStartColor.saturate();
          (*it).segmentEndColor.saturate();

          if((*it).segmentStartColor == Ogre::ColourValue::ZERO &&(*it).segmentEndColor == Ogre::ColourValue::ZERO)
          {
               it = m_SegmentList.erase(it);
          }
          else
          {
               ++it;
          }
     }

     // throw away the last element if the maximum number of segments is used
     if(m_SegmentList.size() >= m_MaxSegmentCount)
     {
          m_SegmentList.pop_back();
     }

     // only add a new segment if active
     if(isActive())
     {
          // the segment to add to the trail
          TrailSegment newSegment;

          // initial the trail
          newSegment.segmentStartColor = getSegmentStartInitialColor();
          newSegment.segmentEndColor = getSegmentEndInitialColor();
          newSegment.segmentStart  = m_WeaponNode->_getDerivedPosition();
          Vector3 pos = m_WeaponNode->getPosition();

          // probably quite costly way to get the second position
          m_WeaponNode->translate(Vector3(0, m_Width, 0), SceneNode::TS_LOCAL);
          newSegment.segmentEnd = m_WeaponNode->_getDerivedPosition();
          m_WeaponNode->setPosition(pos);
          Vector3 _verDir = newSegment.segmentEnd - newSegment.segmentStart;
          _verDir.normalise();
          newSegment.segmentEnd = newSegment.segmentStart + _verDir *  m_Width;
          m_SegmentList.push_front(newSegment);
     }

     // update the manual object
     m_TrailObject->beginUpdate(0);
     int segmentCount = 0;
     for(TrailSegmentList::iterator it = m_SegmentList.begin();it != m_SegmentList.end(); ++it)
     {
          m_TrailObject->position((*it).segmentStart);
          m_TrailObject->textureCoord(0,0);
          m_TrailObject->colour((*it).segmentStartColor);
          m_TrailObject->position((*it).segmentEnd);
          m_TrailObject->textureCoord(1,0);
          m_TrailObject->colour((*it).segmentEndColor);
          ++segmentCount;
     }

     // use the last position to render the invisible part of the trail
     // as degenerate triangles
     Vector3 lastPos = Vector3::ZERO;
     if(!m_SegmentList.empty())
     {
          lastPos = m_SegmentList.back().segmentStart;
     }

     for(int i=segmentCount*2;i<m_MaxSegmentCount * 2;++i)
     {
          m_TrailObject->position(lastPos);
     }

     // end the update
     m_TrailObject->end();
}
//---------------------------------------------------------------------------//
void WeaponTrail::setMaterialName(const String& p_MaterialName)
{
     m_MaterialName = p_MaterialName;
     if(m_TrailObject)
     {
          m_TrailObject->setMaterialName(0, m_MaterialName);
     }
}
//---------------------------------------------------------------------------//
void WeaponTrail::setSegmentStartColorChange(const Ogre::ColourValue& p_ColorChange)
{
     m_SegmentStartColorChange = p_ColorChange;
}
//---------------------------------------------------------------------------//
const Ogre::ColourValue& WeaponTrail::getSegmentStartColorChange() const
{
     return m_SegmentStartColorChange;
}
//---------------------------------------------------------------------------//
void WeaponTrail::setSegmentEndColorChange(const Ogre::ColourValue& p_ColorChange)
{
     m_SegmentEndColorChange = p_ColorChange;
}
//---------------------------------------------------------------------------//
const Ogre::ColourValue& WeaponTrail::getSegmentEndColorChange() const
{
     return m_SegmentEndColorChange;
}
//---------------------------------------------------------------------------//
void WeaponTrail::setSegmentStartInitialColor(const Ogre::ColourValue& p_Color)
{
     m_SegmentStartInitialColor = p_Color;
}
//---------------------------------------------------------------------------//
const Ogre::ColourValue& WeaponTrail::getSegmentStartInitialColor() const
{
     return m_SegmentStartInitialColor;
}
//---------------------------------------------------------------------------//
void WeaponTrail::setSegmentEndInitialColor(const Ogre::ColourValue& p_Color)
{
     m_SegmentEndInitialColor = p_Color;
}
//---------------------------------------------------------------------------//
const Ogre::ColourValue& WeaponTrail::getSegmentEndInitialColor() const
{
     return m_SegmentEndInitialColor;
}
//---------------------------------------------------------------------------//
void WeaponTrail::setActive(bool p_Active)
{
     m_IsActive = p_Active;
}
//---------------------------------------------------------------------------//
bool WeaponTrail::isActive() const
{
     return m_IsActive;
}
//---------------------------------------------------------------------------//
bool WeaponTrail::isVisible() const
{
     return !m_SegmentList.empty();
}
//---------------------------------------------------------------------------//
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值