資料來源:http://www.cpp3d.com/articles/show.asp?aid=12

圖像扭曲是平面圖形變化的一種,它可用于許多場合,如在以前介紹的火焰特效中加入扭曲效果,會使火焰更逼真(當然代碼要有更高的的效率才行),如果在字幕當中加入扭曲效果,會給人一種怪異的感覺。  圖象扭曲的算法並不複雜,但要解釋清楚卻不是一件容易的事,為了說明問題只好借用圖片了,網路慢的朋友多多包涵了。算法例程源碼編譯需VC++、DXSDK、DXGuide。圖一 圖二 圖三  首先我們來看圖一,大家可看出在圖中有一些網格線,這里假定這些網格線是一些有彈性的細繩,在圖一中假定網格線是與底層分離的,接下來我們要在網格線的結點處施加外力,網格線受外力后就會變成象圖二的形狀,大家要仔細看圖一和圖二的底圖,變化的僅僅是網格線,而底圖目前為止還沒改變。  再下來就是關鍵的地方了,到目前為止,我們還是假定網格線是與底圖分離開的,接下來我們要把圖二中網格線附著在底圖上,然后撤消外力,記住網格線是有彈性的,這時底圖在網格線的帶動下發生變形,直到網格線回複到原樣,如圖三。大家再仔細看看圖三的底圖,是不是已被扭曲?是不是恍然大悟?接下來就好解釋了,我們再來看看圖二到圖三中某個固定的網格是如何形變的,
// 單元塊扭曲算法
inline void CFeedBackApp::TextureBlock(int xo, int yo)
{
// 投影平面
float fLeftOffX, fLeftOffY; // 各行左端點相對于上一行左端點的偏移
float fRightOffY, fRightOffX; // 各行右端點相對于上一行右端點的偏移
float TX1, TY1, TX2, TY2; // 當前行左、右端點的坐標
float HDx, Hdy; // 當前行各點間的平均偏移量
float tx, ty; // 當前投影點坐標
// 渲染平面
int x, y; // 當前渲染點坐標

WORD *Tptr;

Tptr = &(m_awBuf1[xi + m_nMul640[yi]]);
fLeftOffX = (m_offset[xo] [yo+1].xint - m_offset[xo] [yo].xint) /16; // 計算平均偏移
fLeftOffY = (m_offset[xo] [yo+1].yint - m_offset[xo] [yo].yint) /16;
fRightOffX = (m_offset[xo+1][yo+1].xint - m_offset[xo+1][yo].xint) /16;
fRightOffY = (m_offset[xo+1][yo+1].yint - m_offset[xo+1][yo].yint) /16; // 計算平均偏移
TX1 = m_offset[xo] [yo].xint; // 取投影圖塊第一行左端點坐標
TY1 = m_offset[xo] [yo].yint;
TX2 = m_offset[xo+1][yo].xint; // 取投影圖塊第一行右端點坐標
TY2 = m_offset[xo+1][yo].yint;
for (y=yi; y < (yi+16); y++)
{
HDx = (TX2-TX1) / 16; // 計算投影圖塊當前行各點的平均偏移
Hdy = ((TY2-TY1) / 16);
tx = TX1; // 投影平面當前行左端點坐標
ty = TY1;
for (x=xi; x < (xi+16); x++)
{
*Tptr++ = m_awBuf2[int(tx) + m_nMul640[int(ty)] ];
tx += HDx; // 下一點
ty += Hdy;
}
Tptr += (SCRWIDTH-16); // 下一行
TX1 += fLeftOffX; // 計算投影平面中下一行左、右端點的坐標
TY1 += fLeftOffY;
TX2 += fRightOffX;
TY2 += fRightOffY;
}
}

創作者介紹
創作者 王小雀 的頭像
王小雀

黃臉婆--冠上夫姓了 哈

王小雀 發表在 痞客邦 留言(0) 人氣()