亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

VC中借助DirectDraw實現水波的模擬

2019-11-17 05:11:06
字體:
來源:轉載
供稿:網友
摘要:本文介紹了一種對水面波紋的擴散、衰減以及交疊的過程進行計算機模擬的一種實現算法,并對在實現該算法過程中所使用的DirectX系列技術中的DirectDraw技術做了簡要的說明。

  要害字:Microsoft SDK、DirectX、DirectDraw、水波

  一、 引言

   現在各種高性能的計算機以其強大的運算能力被廣泛應用于各種領域,也可以對許多自然界的物理現象和自然規律進行很好的仿真。但許多專業書籍往往對此類的仿真技術諱莫如深,使不少程序設計人員對此類程序的設計經常會感到無從下手。本文通過對真實水波的產生、擴散、衰減以及多個水波的交迭過程的計算機模擬來對此類程序的設計思路與方法做了簡要的描述。在程序的實現過程中為了使仿真的效果更加逼真、使處理數據顯示的速度更快使用了DirectX系列技術中的DirectDraw技術通過對硬件加速器的使用來對數據的顯示進行加速。本文下面就圍繞這些技術的應用展開討論。

  二、 水波模擬的算法設計

   要對某種自然現象進行模擬仿真,就必須對該現象的特性有很好的熟悉。比如對于本文所仿真的對象--水波,就要對水波的諸多特性如擴散性、衰減性、反射性以及水的折射等都要有所熟悉,并最終通過程序算法體現在程序中。這些關于波的特性屬于普通物理的研究范疇,

   本文在此不再贅述。根據以上的特性,再利用數學和幾何的有關知識就可以在計算機上模擬出真實的水波了。

   因為在模擬時需要的是實時的渲染,而每秒種至少要渲染15幀以上才能使水波得以平滑的顯示??紤]到普通微型計算機的運算速度,不能用乘、除法,更不可以使用正、余弦函數以精確的公式來構造水波,我們只能通過使用簡單而高速的加、減法的近似算法來實現。可以用兩個與水池圖象一樣大小的數組buf1和buf2來保存水面上每一個點(離散化的點,對應于每一個像素)的前、后兩時刻的波幅數據。在無外力干擾時的穩定狀態下水面是一個平面,水面各點的波幅都為0。當有外力干擾,如向水池投一顆石子會使水面泛起層層的漣漪。我們不能被現象所誤導,實際上并非水面上的點在向外擴散,而是仍停在原地上下移動,由于振動幅度的變化而引起視覺上的錯覺。而且水波上的任何一點在任何時候都是通過振幅的變化把能量以自己為圓心向四面擴散,我們可以近似認為一個點只會對相臨的前、后、左、右四個點有影響。這樣我們就可以用歸納法來根據任一點在某時刻四周四點的振幅來求出該點在下一時刻的震動幅度。假設表示該影響關系的公式為:

A0’=a×(A1+A2+A3+A4)+b×A0 (公式一)
   其中a、b為待定系數,A0’為0點下一時刻的振幅,A0、A1、A2、A3、A4均為為當前時刻的四周各點振幅。在不考慮衰減的情況下波的能量守恒,即各點振幅之和守恒(能量通過振幅來體現),可以用公式二表示:

A0’+A1’+...+An’ = A0+A1+...+An (公式二)
   將公式1代入公式2:

(4a+b)×A0+(4a+b)×A1+...(4a+b)×An = A0+A1+...+An
   化簡可得4a+b=1, 取a = 1/2、b = -1可以滿足條件。而且除2可以用運算速度很快的移位運算符">>"來進行。公式一代入系數可得到無阻尼狀態下的四周四點對中心點的影響關系式:

A0’=(A1+A2+A3+A4)/ 2- A0
   推廣到水面任一點:下一時刻任意一點的波幅等于與該點緊鄰的前、后、左、右四點的波幅之和的一半與該點在上一時刻的波幅之差。但水在實際中是存在阻尼的,水波會在擴散過程中逐漸衰減直至消失。所以還要對波幅數據進行衰減處理,讓每一個點在經過一次運算后,波幅按一定的比例衰減,衰減率經筆者的實驗,取1/32比較合適,同時它也可以通過移位運算很快的獲得。到此為止,已將水波的擴散和衰減等特型用數學模型表示了出來,下面是具體計算波幅數據的主要代碼:

void SPRead()
{
  ……
  for (int i=BACKWIDTH; i  {
   //能量的擴散
   buf2[i] = ((buf1[i-1]+buf1[i+1]+buf1[i-BACKWIDTH]+buf1[i+BACKWIDTH])>>1)- buf2[i];
   //能量的衰減
   buf2[i] -= buf2[i]>>5;
  }
  //交換前后兩時刻的能量緩沖區
  short *ptmp =buf1;
  buf1 = buf2;
  buf2 = ptmp;
  ……
}

   雖然模擬了對波的傳播過程,但如不考慮水面起伏的水波引起的對光的折射也是不逼真的,也正是由于水面上部的光線反射,才使我們感覺到水波的起伏。根據光學有關知識,我們所看到的水下的景物并非在觀察點的正下方,而是存在一定的偏移。偏移的程度同水波的斜率,水的折射率和水的深度都有關系,出于對處理速度的考慮同樣也不能對其進行精確的模擬。只能做線性的近似處理。因為水面越傾斜,所看到的水下景物偏移量就越大,所以,我們可以近似的用水面上某點的前后、左右兩點的波幅之差來代表所看到水底景物的偏移量:

void Render()
{
  ……
  int xoff, yoff;
  int k = BACKWIDTH;
  for (int i=1; i  {
   for (int j=0; j   {
    //計算偏移量
    xoff = buf1[k-1]-buf1[k+1];
    yoff = buf1[k-BACKWIDTH]-buf1[k+BACKWIDTH];
    //判定坐標是否在窗口范圍內
    if ((i+yoff )< 0 ) {k++; continue;}
   if ((i+yoff )>BACKHEIGHT) {k++; continue;}
   if ((j+xoff )< 0 ) {k++; continue;}
   if ((j+xoff )>BACKWIDTH ) {k++; continue;}
   //計算出偏移象素和原始象素的內存地址偏移量
   int pos1, pos2;
   pos1=ddsd1.lPitch*(i+yoff)+ depth*(j+xoff);
   pos2=ddsd2.lPitch*i+ depth*j;
   //復制象素
   for (int d=0; d    Bitmap2[pos2++]=Bitmap1[pos1++];
    k++;
   }
  }
  ……
}

   在無外力影響的情況下,是不會自發產生水波的,必須對水面施加某種激勵才能引起波源的擴散。而且擴散的速度與范圍也是同激勵的能量大小與受力范圍有關的,我們可以通過在程序中人為的修改振幅緩沖區buf,來模擬外界的激勵比如雨點入水等。可以在雨點落水的地點來一個負的"尖脈沖",即讓buf[x,y]=-n。經過多次實驗,n的范圍取值在(32~128)之間比較合適。受力半徑的控制也好辦,只須以入水中心點為圓心,畫一個以雨點半徑為半徑的圓,讓這個圓里所有的點都來這么一個負的"尖脈沖"就可以了,顯然這里也是做的近似處理:

void DropStone(int x,/*x坐標 */ int y,/*y坐標*/int stonesize,/*半徑*/int stoneweight/*能量*/)
{
  ……
  //判定坐標是否在屏幕范圍內
  if ((x+stonesize)>BACKWIDTH (y+stonesize)>BACKHEIGHT(x-stonesize)<0(y-stonesize)<0)
   return;
  ……
  for (int posx=x-stonesize; posx   for (int posy=y-stonesize; posy    if ((posx-x)*(posx-x) + (posy-y)*(posy-y) < stonesize*stonesize)
     buf1[BACKWIDTH*posy+posx] = -stoneweight;
     ……
}


   雖然在前面的推導中多處采用了看似過分的非常近似的處理,但是完全不必擔心,事實證實,用這種方法,在速度和圖象上都可以獲得非常好的效果。下邊就是從其中截取的一幀畫面,很逼真的再現了水波的產生過程。


VC中借助DirectDraw實現水波的模擬(圖一)

   這種用數據緩沖區對圖象進行處理的方法的最大的好處就是:程序運算和顯示的速度與水波的復雜程度是無關的,用類似的方法完全可以對其他一些物理、自然現象如煙霧、云彩、陽光等進行逼真的模擬。 三、 利用DirectDraw完成對圖形的加速

   從前面可以看出,我們一直在處理速度上比較嚴格。竭盡所能來提高數據的處理速度,不僅在算法上如此,在顯示上更是如此。普通的GDI函數的處理速度在這里是無法容忍的,對此采用了DirectX系列技術中的DirectDraw技術來對圖形進行加速處理。

   DirectDraw是DirectX SDK系列中的一員,也是其中最主要的一個部件。它答應程序員直接的操作顯存、硬件位圖映射以及硬件覆蓋和換頁技術。它在提供直接訪問顯示設備的同時,與GDI相兼容,它只是一個軟件接口,提供了一種與設備無關的途徑,以獲得訪問特定的顯示設備的某些高級特性的能力。大體上DirectDraw可以提供了以下幾個功能,而這些功能以前只有那些專為特定顯示設備所寫的軟件中才能使用:

   ·支持雙緩沖和換頁圖形

   ·訪問、控制顯示卡的位圖映射

   ·支持3D z-buffers (z緩存)

   ·支持z方向(z-ordering)硬件輔助覆蓋。

   ·訪問圖形縮放硬件

   ·仿真訪問標準的和增強的顯示設備內存空間

   下面就對DirectDraw的在圖形加速方面中的具體應用結合本程序的具體實例來進行介紹,為方便起見,本工程采用Microsoft SDK編碼,先要對DirectDraw環境進行初始化,完成設置并在其中對主頁面和各離屏頁面進行創建并初始化之:

BOOL InitDDraw(void)
{
  DDSURFACEDESC ddsd;
  HRESULT ddrval;
  ……
  //創建DirectDraw對象
  ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
  ……
  //取得全屏獨占模式
  ddrval = lpDD->SetCoOperativeLevel(hwndful, DDSCL_EXCLUSIVE DSCL_FULLSCREEN );
  ……
  //設置顯示器顯示模式
  ddrval = lpDD->SetDisplayMode( DISPLAYMODEWIDTH,DISPLAYMODEHEIGHT, 24);
  ……
  //填充主頁面信息
  ddsd.dwSize = sizeof( ddsd );
  ddsd.dwFlags = DDSD_CAPS ;
  ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  //創建主頁面對象
  ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );
  ……
  ddsd.dwFlags = DDSD_CAPS DDSD_HEIGHT DDSD_WIDTH;
  ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN DDSCAPS_SYSTEMMEMORY ;
  ……
  lpDD->CreateSurface(&ddsd, &lpDDSPic1, NULL) ;
  ……
  lpDD->CreateSurface(&ddsd, &lpDDSPic2, NULL);
  ……
  lpDD->CreateClipper(0, &lpClipper, NULL);
  lpClipper->SetHWnd(0, hwndful);
  lpDDSPrimary->SetClipper(lpClipper);
  ……
  //初始化頁面圖像
  DDReLoadBitmap(lpDDSPic1, MAKEINTRESOURCE(IDB_BITMAP1));
  DDReLoadBitmap(lpDDSPrimary,MAKEINTRESOURCE(IDB_BITMAP2));
  ……
  ZeroMemory(buf1, BACKWIDTH*BACKHEIGHT*sizeof(short));
  ZeroMemory(buf2, BACKWIDTH*BACKHEIGHT*sizeof(short));
  ……
  return TRUE;
}

   另外,必須在應用程序活躍時不斷的進行更新,方可完成對整個過程的模擬,在更新幀的函數中負責完成對數據的實時處理及對頁面的渲染,最重要的環節--將離屏頁面2裝載到主頁面的工作也將在這里完成:

……
DropStone((int)(BACKWIDTH*((short)rand()/32767.0)),
(int)(BACKHEIGHT*((short)rand()/32767.0)),
2,64);//激勵點為隨機產生,模擬雨點落在水面的情形
Spread();//計算振幅數據緩沖區
Render();//頁面渲染
//在window內顯示頁面2
lpDDSPrimary->Blt(&Window, lpDDSPic2, NULL, DDBLT_WAIT, NULL);
……

   在前面的處理光的折射的Rander()函數中也應增添對頁面的渲染部分的編碼,可以用一個頁面來裝載原始的圖象,用另外一個頁面來進行渲染。
先用Lock函數鎖定兩個頁面,取得指向頁面內存區的指針,然后根據偏移量將原始圖象上的每一個象素復制到渲染頁面上:

……
//鎖定兩個離屏頁面
DDSURFACEDESC ddsd1, ddsd2;
ddsd1.dwSize = sizeof (DDSURFACEDESC);
ddsd2.dwSize = sizeof(DDSURFACEDESC);
lpDDSPic1->Lock(NULL, &ddsd1, DDLOCK_WAIT, NULL);
lpDDSPic2->Lock(NULL, &ddsd2, DDLOCK_WAIT, NULL);
//取得頁面象素位深度,和頁面內存指針
int depth=ddsd1.ddpfPixelFormat.dwRGBBitCount/8;
BYTE *Bitmap1 = (BYTE*)ddsd1.lpSurface;
BYTE *Bitmap2 = (BYTE*)ddsd2.lpSurface;
……
//中間為對光的折射模擬過程的代碼
……
//解鎖頁面
lpDDSPic1->Unlock(&ddsd1);
lpDDSPic2->Unlock(&ddsd2);

   最后,為了養成良好的編程習慣,應在程序退出之前釋放掉所使用過的資源,在這里主要為對各個頁面的釋放以及對DirectDraw對象lpDD的釋放:

……
lpDDSPrimary->Release();
lpDDSPic1->Release();
lpDDSPic2->Release();
lpClipper->Release();
lpDD->Release();
……

   經過上述幾步,已基本完成了對水波的模擬工作。通過對DirectDraw技術的應用,在取得了對圖形的硬件加速支持后可以在計算機上很流暢地完成對水波自產生、擴散到消失的全部過程的仿真模擬。

  小結:

   通過本文所述的對自然事物的計算機模擬的實現過程,可以對仿真模擬類程序的一般實現過程有基本的熟悉,在理解本程序的設計思路與方法的前提下也可以用類似的方法設計出對其他事物的模擬算法。本程序結合具體程序設計要求合理和有效的利用DirectDraw的圖形硬件加速等特性很好的實現了對水波模擬的過程顯示,對于其他仿真程序的設計也可以根據實際靈活的選用諸如OpenGL、Direct3D等不同的軟件接口。本文所述程序在windows 2000下,在DirectX 9.0的支持下,由Microsoft Visual C++ 6.0編譯調試通過。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美电影院免费观看| 日韩av中文字幕在线免费观看| 亚洲一区二区免费| 97在线看福利| 日韩中文字幕久久| 日韩中文字幕在线播放| 综合国产在线观看| 国产精品永久免费观看| 91精品国产综合久久久久久蜜臀| 国产亚洲欧美日韩美女| 一区二区国产精品视频| 色婷婷av一区二区三区在线观看| 26uuu亚洲伊人春色| 亚洲xxxx妇黄裸体| 91在线观看免费高清| 欧美壮男野外gaytube| 国产精品久久av| 国产亚洲精品久久久| 国产mv免费观看入口亚洲| 欧美老肥婆性猛交视频| 国产欧美一区二区三区久久| 久久久精品在线| 欧美性xxxxx| 亚洲精品国产精品国自产观看浪潮| 精品无人区太爽高潮在线播放| 国产精品成av人在线视午夜片| 久久综合色影院| 久久精品国产精品亚洲| 国产精品免费视频久久久| 国产婷婷成人久久av免费高清| 欧美激情视频免费观看| 国产一区二区av| 国产精品高清在线| 日本高清视频精品| 亚洲精品v欧美精品v日韩精品| 欧美理论片在线观看| 亚洲最大的网站| 日韩理论片久久| 91久久精品在线| 亚洲国产欧美在线成人app| 97国产精品视频人人做人人爱| 日本亚洲欧洲色α| 97视频免费观看| 欧美一级视频免费在线观看| 国产欧美va欧美va香蕉在线| 国产91精品高潮白浆喷水| 亚洲国产欧美自拍| 性欧美视频videos6一9| 一本色道久久88亚洲综合88| 91免费看片网站| 久久久电影免费观看完整版| 久久手机精品视频| 国产欧美一区二区三区久久| 欧美极品少妇全裸体| 久久久精品久久久久| 精品亚洲一区二区三区在线播放| 久久精品国产亚洲一区二区| 欧美日韩在线观看视频小说| 日韩美女在线观看一区| 国产精品一久久香蕉国产线看观看| 欧美激情一二区| 不用播放器成人网| 亚洲三级黄色在线观看| 久久久女女女女999久久| 亚洲男人天堂2019| 日韩精品福利网站| 国产欧美日韩高清| 亚洲自拍欧美另类| 不卡伊人av在线播放| 久久成人一区二区| 97国产精品久久| 国产精品成av人在线视午夜片| 91精品久久久久久久久久另类| 亚洲自拍偷拍视频| 美女av一区二区三区| 成人黄色av播放免费| 欧美成人免费视频| 欧美激情视频网址| 欧美视频在线视频| 欧美国产日韩中文字幕在线| 2021国产精品视频| 国产日韩精品综合网站| 欧美性极品xxxx娇小| 日韩欧美在线观看| 亚洲第一免费播放区| 日韩欧美国产成人| 亚洲精品日韩久久久| 久久久久久久久久久网站| 欧美激情视频在线免费观看 欧美视频免费一| 国产在线播放不卡| 欧美日韩精品在线播放| 久久久久日韩精品久久久男男| 欧美又大粗又爽又黄大片视频| 久久精品国产视频| 国产97色在线|日韩| 日本国产一区二区三区| 在线观看精品国产视频| 亚洲第一福利网| 亚洲桃花岛网站| 国产精品免费久久久| 亚洲国产精品福利| 26uuu另类亚洲欧美日本老年| 国产美女直播视频一区| 亚洲视频精品在线| 国产欧美一区二区三区在线| 91精品国产色综合久久不卡98口| 久久夜精品香蕉| 国产精品综合久久久| 欧美亚洲成人网| 欧美成人精品一区二区三区| 久久成人这里只有精品| 日韩欧美在线免费观看| 亚洲精品成a人在线观看| 国产精品一区二区三区免费视频| 欧洲一区二区视频| 久久精品视频在线| 久久精品久久久久电影| 欧美日本啪啪无遮挡网站| 欧美午夜精品久久久久久浪潮| 久热精品视频在线观看一区| 亚洲精品网站在线播放gif| 欧美成人精品三级在线观看| 成人黄色在线观看| 91香蕉嫩草神马影院在线观看| 亚洲xxxx妇黄裸体| 国产精品久久久久aaaa九色| 一区二区三区在线播放欧美| 欧美电影在线观看高清| 午夜精品视频网站| 91精品国产综合久久久久久久久| 国产精品热视频| 久久69精品久久久久久久电影好| 亚洲精品国产拍免费91在线| 91高清视频在线免费观看| 亚洲黄色av网站| 日韩中文在线中文网在线观看| 美女少妇精品视频| 亚洲女成人图区| 日韩av色综合| 国产一区二区三区网站| 欧美亚洲另类激情另类| 欧美亚洲另类在线| 一色桃子一区二区| 日本一欧美一欧美一亚洲视频| 久久久久久久久久久网站| 日本不卡高字幕在线2019| 久久九九国产精品怡红院| 黑人巨大精品欧美一区二区三区| 日韩av在线免费播放| 日韩国产在线播放| 日韩网站免费观看| 久久乐国产精品| 国产一区二中文字幕在线看| 亚洲最大的成人网| www.欧美精品| 国产精品偷伦视频免费观看国产| 欧美日韩视频免费播放| 91精品国产91久久久久| 国产日产欧美a一级在线| 91极品女神在线| 精品在线欧美视频| 久久伊人91精品综合网站| 亚洲精品99久久久久中文字幕| 国产精品高潮呻吟视频|