日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

fft ocean注解

發布時間:2025/3/20 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 fft ocean注解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

針對這兩篇教程:

http://www.keithlantz.net/2011/10/ocean-simulation-part-one-using-the-discrete-fourier-transform/

http://www.keithlantz.net/2011/11/ocean-simulation-part-two-using-the-fast-fourier-transform/

的一些注解:

一,

原文下面一段

框起部分不通順,似乎應該是 "by letting Lx=N and Lz=M. then becomes,"

從這段之后教程中本應是Lx,Lz的地方就都變成M,N了。

由此看來,作者為了方便使用fft計算heightmap,強制使Lx,Lz等于M,N了。

而在教程的非fft的版本中是沒有Lx,Lz必須等于N,M的限制的,甚至Lx,Lz可以不是整數。

即對于非fft版本,ocean的構造函數

cOcean::cOcean(const int N, const float A, const vector2 w, const float length, const bool geometry)

中N和length可以傳不同的值,但對于fft版本,N和length必須傳相同整數值才正確(N須為2的冪)。

補充:坑爹,原來我用的瀏覽器有問題,導致教程中插在句子中的數學符號顯示不出來,剛才用另一個瀏覽器看,發現紅框中那句確實是:

整篇教程中類似情況不勝枚舉,我居然一直都是在缺符號的情況下看的。。。

?

二,

教程中h_tilde為NxN,vertices為(N+1)x(N+1)。

vertices的初始化代碼為:

for (int m_prime = 0; m_prime < Nplus1; m_prime++) {
?? ??? ?for (int n_prime = 0; n_prime < Nplus1; n_prime++) {
?? ??? ??? ?index = m_prime * Nplus1 + n_prime;
?? ??? ??? ?htilde0??????? = hTilde_0( n_prime,? m_prime);
?? ??? ???? ...
?? ??? ??? ?vertices[index].ox = vertices[index].x =? (n_prime - N / 2.0f) * length / N;
?? ??? ??? ?vertices[index].oy = vertices[index].y =? 0.0f;
?? ??? ??? ?vertices[index].oz = vertices[index].z =? (m_prime - N / 2.0f) * length / N;
    ...
?? ??? ?}
?? ?}

從中可以看出h'(x,z,t)的x和z的初始表達式為:

x=(n'-N/2)*L/N

z=(m'-N/2)*L/N

對于fft版本,由于教程中強制令L=N,所以

x=n'-N/2

z=m'-N/2

(注,后面為了實現“卷浪”,x,z在此基礎上還會進行一定的偏移)。

三,

教程中fft版本的總體計算思路是將二維DFT:

拆成兩個一維DFT來進行計算

以N=4為例,計算過程如下:

其中DFT(4)代表(4)式所定義的DFT,DFT(3)代表(3)式所定義的DFT。

即先逐行dft,再逐列dft。

可見對于N=4的情況,完成heightmap的更新需要計算8個DFT,那么對于一般情況則需要計算2N個DFT。

每個DFT都可以使用FFT來計算,對應教程中如下代碼:

??? for (int m_prime = 0; m_prime < N; m_prime++) {
?? ??? ?fft->fft(h_tilde, h_tilde, 1, m_prime * N);
?? ??? ?…
?? ?}
?? ?for (int n_prime = 0; n_prime < N; n_prime++) {
?? ??? ?fft->fft(h_tilde, h_tilde, N, n_prime);
?? ??? ?…
?? ?}

四,

教程代碼中實現無縫循環(tiling)的代碼非常簡單,只是將第0行(列)的數據填充給第N+1行(列)即可:
?? ?for (int m_prime = 0; m_prime < N; m_prime++) {
?? ??? ?for (int n_prime = 0; n_prime < N; n_prime++) {
?? ??? ??? ?index? = m_prime * N + n_prime;?? ??? ?// index into h_tilde..
?? ??? ??? ?index1 = m_prime * Nplus1 + n_prime;?? ?// index into vertices
?? ??? ??? ?…
?? ??? ??? ?// height
?? ??? ??? ?vertices[index1].y = h_tilde[index].a;
?? ??? ??? ?…
?? ??? ??? ?// for tiling
?? ??? ??? ?if (n_prime == 0 && m_prime == 0) {
?? ??? ??? ??? ?vertices[index1 + N + Nplus1 * N].y = h_tilde[index].a;
?? ??? ??? ??? ?…
?? ??? ??? ?}
?? ??? ??? ?if (n_prime == 0) {
?? ??? ??? ??? ?vertices[index1 + N].y = h_tilde[index].a;
?? ??? ??? ??? ?…
?? ??? ??? ?}
?? ??? ??? ?if (m_prime == 0) {
?? ??? ??? ??? ?vertices[index1 + Nplus1 * N].y = h_tilde[index].a;
?? ??? ??? ??? ?…
?? ??? ??? ?}
?? ??? ?}
?? ?}

言外之意,h'(x,z,t)在x和z方向上均是以L為周期的周期函數,即:

h'(x+L,z,t)=h(x,z,t)

h'(x,z+L,t)=h(x,z,t)

事實確實如此,驗證如下:

因為N為偶數,所以

所以

h'(x+L,z,t)=h(x,z,t)

h'(x,z+L,t)=h(x,z,t)

五,

evaluateWavesFFT函數中如下代碼:

??? for (int m_prime = 0; m_prime < N; m_prime++) {
?? ??? ?fft->fft(h_tilde, h_tilde, 1, m_prime * N);
?? ??? ?…
?? ?}
?? ?for (int n_prime = 0; n_prime < N; n_prime++) {
?? ??? ?fft->fft(h_tilde, h_tilde, N, n_prime);
?? ??? ?…
?? ?}
??? int sign;
?? ?float signs[] = { 1.0f, -1.0f };
?? ?vector3 n;
?? ?for (int m_prime = 0; m_prime < N; m_prime++) {
?? ??? ?for (int n_prime = 0; n_prime < N; n_prime++) {
?? ??? ??? ?index? = m_prime * N + n_prime;?? ??? ?// index into h_tilde..
?? ??? ??? ?index1 = m_prime * Nplus1 + n_prime;?? ?// index into vertices
?? ??? ??? ?sign = signs[(n_prime + m_prime) & 1];//如果n+m為奇數,則sign=signs[1]=-1;如果n+m為偶數,則sign=signs[0]=1
?? ??? ??? ?h_tilde[index]???? = h_tilde[index] * sign;
?? ??? ??? ?…
?? ??? ?}
?? ?}

可見在計算完2N次FFT后,還有一個符號校正(乘以sign)的步驟。

為什么需要符號校正?

因為代碼中的第一個fft并不是完整計算了h''(x,m',t),而只是計算了下式中紅框內的部分(省略了一個(-1)^x因子):

同理,代碼中的第二個fft也并不是完整計算了h'(x,z,t),而只是計算了下式中紅框內的部分(省略了一個(-1)^z因子):

所以當fft計算全部執行完后,還需要乘以(-1)^(x+z)。

因為在fft版本中x=n'-N/2,z=m'-N/2,所以(-1)^(x+z)=(-1)^(n'+m'-N),因為N為偶數,所以(-1)^(n'+m'-N)=(-1)^(n'+m')。

六,

蝶形圖及T函數表實現

這一塊發現教程中有些錯誤,我們自己來推導一下N=4的蝶形圖。

在上式中令N=4,得:

因x=n'-N/2,n'=0,1,2,3,所以x=-2,-1,0,1,并適當利用變形,得:

據此可畫出蝶形圖:

對上面蝶形圖進行等價優化變形,得:

注:以上優化變形的原理是:因為,所以有T4^0=-T4^(-2),故可將T4^(-2)由支干移至主干,并將T4^0改為-1。同理,可將T4^(-1)由支干移至主干,并將T4^1改為-1。

容易看出變換后的蝶形圖與原蝶形圖等價。此優化思路源于:https://cnx.org/contents/zmcmahhR@7/Decimation-in-time-DIT-Radix-2,其中的Additional Simplification一節。

?

此即為N=4時的最終蝶形圖,可以驗證此蝶形圖與教程中給出的N=4蝶形圖是不等價的,即教程中蝶形圖有誤。

再看教程中生成T函數表的代碼:

cFFT::cFFT(unsigned int N) : N(N), reversed(0), T(0), pi2(2 * M_PI) {
?? ?…
?? ?int pow2 = 1;
?? ?T = new complex*[log_2_N];?? ??? ?// prep T
?? ?for (int i = 0; i < log_2_N; i++) {
?? ??? ?T[i] = new complex[pow2];
?? ??? ?for (int j = 0; j < pow2; j++) T[i][j] = t(j, pow2 * 2);
?? ??? ?pow2 *= 2;
?? ?}
?? ?…
}
complex cFFT::t(unsigned int x, unsigned int N) {
?? ?return complex(cos(pi2 * x / N), sin(pi2 * x / N));
}

顯然也是有錯誤的,其中

for (int j = 0; j < pow2; j++) T[i][j] = t(j, pow2 * 2);

一句,應改為:

for (int j = 0; j < pow2; j++) T[i][j] = t(j-N/2, pow2 * 2);

因為x=n'-N/2,而非x=n'。

此至,教程及代碼中的疑問基本上就都解決了,下面是移植到unity中的結果:

(為了確認無縫,在z軸方向平鋪了一次)

----補充:

一,

蝶形圖的含義:

首先我們知道蝶形圖右邊任何一個輸出都是左邊所有輸入的線性組合,所以假設我們想知道h'''(-1,m',t)的表達式,首先有

然后再根據蝶形圖讀出A,B,C,D的值。

求A的值,看紅色路徑,沒有經過任何值,所以A=1。

求B的值,看綠色路徑,經過T2^(-2)和-1,所以B=-T2^(-2)。

求C的值,看藍色路徑,經過T4^(-1),所以C=T4^(-1)。

求D的值,看黃色路徑,經過T2^(-2),-1,T4^(-1),所以D=-T2^(-2)*T4^(-1)。

所以得:

對比前面(六)中所得:

因為-T2^(-2)=T2^(-1),所以結果是一樣的。

二,

比特翻轉

根據蝶形圖實現fft,因為蝶形圖左邊N個輸入數據的是亂序(比如對于N=4而言是0,2,1,3;對于N=8而言是0,4,2,6,1,5,3,7),這個次序可由bit reverse來生成,以N=4為例:

0 (00)?? -- bit reverse --> (00) 0

1 (01)???-- bit reverse --> (10) 2

2 (10)???-- bit reverse --> (01) 1

3 (11)???-- bit reverse --> (11) 3

參考:http://www.dspguide.com/ch12/2.htm

代碼中實現bit reverse的部分為:

cFFT::cFFT(unsigned int N) : N(N), reversed(0), T(0), pi2(2 * M_PI) {
?? ?…
?? ?log_2_N = log(N)/log(2);

?? ?reversed = new unsigned int[N];?? ??? ?// prep bit reversals
?? ?for (int i = 0; i < N; i++) reversed[i] = reverse(i);
?? ?…
}
unsigned int cFFT::reverse(unsigned int i) {
?? ?unsigned int res = 0;
?? ?for (int j = 0; j < log_2_N; j++) {
?? ??? ?res = (res << 1) + (i & 1);
?? ??? ?i >>= 1;
?? ?}
?? ?return res;
}

?

----補充2

此教程為cpu實現fft ocean,且fft部分的實現方法用的是最直觀的方法,所以效率是比較不高的方法。

但即使cpu fft ocean再怎么優化,效果肯定也高不到哪兒去,所以此教程僅作為一個起點。接下來移植到gpu是必須的。等移植完我再另寫一篇日志。

2017-6-25更新:

基于gpu的實現已初步試驗成功,見下帖中的2017-6-25:http://www.cnblogs.com/wantnon/p/6985141.html

2017-6-30更新:

gpu fft海面動畫已實現,見下帖中的2017-6-30: http://www.cnblogs.com/wantnon/p/6985141.html

----

另附兩個重要參考:

http://graphics.ucsd.edu/courses/rendering/2005/jdewall/tessendorf.pdf

https://pdfs.semanticscholar.org/0047/8af7044a7f1350d5ec75ffc7c15b40057051.pdf


?

總結

以上是生活随笔為你收集整理的fft ocean注解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久久精品无码Av中文字幕 | 夫妻淫语绿帽对白 | 国产在线欧美日韩 | 欧洲xxxxx | 韩国一二三区 | 无码人妻精品一区二区蜜桃网站 | 麻豆系列 | 激情欧美一区二区免费视频 | 无码人妻精品一区二区三区蜜桃91 | 秘密爱大尺度做爰呻吟 | 亚洲国产欧美视频 | 黄色大全免费看 | 国产精品夜夜夜爽阿娇 | 正在播放超嫩在线播放 | 男男毛片 | 少女忠诚电影高清免费 | 悠悠色综合 | 中文幕无线码中文字夫妻 | 看个毛片 | 丰满熟妇人妻中文字幕 | 免费69视频 | 午夜精品无码一区二区三区 | 国产午夜精品久久久久久久 | 在线亚洲成人 | 99久视频| 女人裸体无遮挡 | 污污的视频网站在线观看 | 日本三级免费看 | 青青青在线视频免费观看 | 国产精品无码免费在线观看 | 久久久久久草 | 91美女视频 | 色老头av | 草草屁屁影院 | 黄色尤物视频 | 国产精品二区一区二区aⅴ 一卡二卡三卡在线观看 | 开心激情网站 | 国产精品久久不卡 | 欧美日韩五月天 | 日日夜夜草 | 亚洲小说网 | 亚洲三级在线免费观看 | 农村妇女一区二区 | 国产香蕉在线视频 | 伊人色区 | 亚洲另类欧美日韩 | 超碰超碰超碰超碰超碰 | 动漫精品一区一码二码三码四码 | 不卡久久| 久久精品福利 | 亚洲精品综合 | 欧美有码在线观看 | 国产ts在线视频 | 曰本毛片 | 国产尤物视频 | 杨幂国产精品一区二区 | 91欧美日韩麻豆精品 | 欧美极品jizzhd欧美仙踪林 | 亚洲性图一区二区 | 色涩视频在线观看 | 亚洲高清无码久久久 | 在线电影一区二区 | 欧美变态口味重另类在线视频 | 国产精品视频免费在线观看 | 午夜国产福利在线 | 性色一区二区三区 | 日韩欧美aⅴ综合网站发布 国产成人一区二区三区小说 | 国产午夜福利一区二区 | 热久久精品 | 在线观看欧美 | 3d动漫精品啪啪一区二区免费 | 国产成人在线观看免费网站 | 日本一区二区在线观看视频 | 国产免费高清视频 | 国产精品三级久久久久久电影 | 黄色永久网站 | 日韩黄色在线视频 | av首页在线观看 | 97色爱 | www国产免费 | 欧美videossex极品 | 欧美一区二区三区久久 | 一区二区三区视频在线观看 | 亚洲aa | 丰满人妻综合一区二区三区 | 在线观看免费视频一区二区 | 亚洲欧美乱综合图片区小说区 | 日本三级韩国三级美三级91 | 在线美女av | 91九色在线视频 | 可乐操亚洲| 天天射夜夜 | 久久观看最新视频 | 亚洲91久久 | 免费在线观看黄 | 国内性爱视频 | 欧美 日韩 国产 成人 在线观看 | 人人干人人草 | 天堂国产精品 |