Ogre的WeaponTrail (刀光)

就是刀光拖尾效果,这个挺有意思,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、付费专栏及课程。

余额充值