2012年7月20日 星期五

Triangle Base Projection Texture

緣起於因為Add Frustum Pass無法解決投射超過二個Texture的問題,於是開啟了Triangle Base Projection Texture之路…
Frustum Pass的問題:
  1. 增加不必要的三角形數(因為MultiPass的關係,尤其是Polygon數多的物件…)
  2. 有機會投射超個二個以上的Texture,常發在生上下有疊層的場景中…
但Triangle Base也有一些需要犧牲的問題:
  1. 需做動態碰撞處理(AABB to Triangle),以取得投射範圍的Triangles
  2. 需做動態LockBuffer(含Vertex及Texture Coordinate Buffer)
PS:以上僅要重設位置時需執行,不重設位置則不用

如何做:
  1. 執行AABB to Triangles碰撞,以取得交集的三角形集合
  2. Lock and fill Vertex and Texture Coordinate Buffer
重算UV的公式如下:
TranslateMatrix*ScaleMatrix*RotMatrix*DestUVW(三角形的點)

相關的範例程式:

bool FillHardwareBuffers(const std::vector& NewVertexBuffer)
{
   if(!NewVertexBuffer.size())
      return false;

   Ogre::HardwareVertexBufferSharedPtr spVertexBuffer = mRenderOp.vertexData->vertexBufferBinding->getBuffer(VERTEX_DECLARATION_POSITION);  
   Ogre::Real* pRealPos = static_cast(spVertexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD));
   if(pRealPos)
   {  
      memcpy(pRealPos, &(NewVertexBuffer)[0], mRenderOp.vertexData->vertexCount*3*sizeof(Ogre::Real));
      spVertexBuffer->unlock();
   }
   Ogre::HardwareVertexBufferSharedPtr spTexcoordsVertexBuffer = mRenderOp.vertexData->vertexBufferBinding->getBuffer(
      VERTEX_DECLARATION_TEXTURE_COORDINATES);
   Ogre::Real* pRealUV = static_cast(spTexcoordsVertexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD));
   if(pRealUV)
   {  
      Ogre::Matrix4 RotMat = Ogre::Matrix4::IDENTITY;
      RotMat.makeTransform(Ogre::Vector3::ZERO, Ogre::Vector3::UNIT_SCALE,
         Ogre::Quaternion(Ogre::Degree(-90.0f), Ogre::Vector3::UNIT_X));

      Ogre::Matrix4 TransMat = Ogre::Matrix4::IDENTITY;
      TransMat.setTrans(Ogre::Vector3(0.5f, 0.5f, 0.0f));
      Ogre::Vector3 Size = mBox.getHalfSize();           
      Ogre::Vector3 ScaleFactor;
      ScaleFactor.x = -0.5f / Size.x;
      ScaleFactor.y = -0.5f / Size.z;
      ScaleFactor.z = 1.0f /(1000.0f+10.0f);
      Ogre::Matrix4 ScaleMat = Ogre::Matrix4::IDENTITY;
      ScaleMat.setScale(ScaleFactor);
           
      std::vector::const_iterator it = NewVertexBuffer.begin();
      Ogre::Vector3 DestUVW;
      while(it != NewVertexBuffer.end())
      {  
         DestUVW.x = (*it);
         DestUVW.y = (*(it+1));
         DestUVW.z = (*(it+2));
         DestUVW = TransMat*ScaleMat*RotMat*DestUVW;
         *pRealUV++ = DestUVW.x;
         *pRealUV++ = DestUVW.y;
         it += 3;
      }
      spTexcoordsVertexBuffer->unlock();
   }
   return true;
}
相關影片:



夢想還在持續中…

沒有留言:

張貼留言