水波动画

qyxqyxqyx 2013-04-11 06:18:59
http://wenku.baidu.com/view/debd152fb4daa58da0114a9b.html
这个方法。我用C++,在window下GDI+重新实现了一下,然后试验了,发现效果不太好为啥?

#ifndef MYMATRIX_H
#define MYMATRIX_H

#include <iostream>

template<typename T>
class MyMatrix{
public:


private:
T * buffer;
unsigned int width;
unsigned int height;

public:
MyMatrix(unsigned int w , unsigned int h ):width(w),height(h){
buffer = new T[width*height];
}
~MyMatrix(){
delete []buffer;
}
inline bool Get(unsigned int i,unsigned int j,T * value = NULL)const{
if(width == 0 || height == 0)return false;
if(i>=width || j>=height)return false;
if(value!=NULL){
*value = buffer[ i * width + j ];
return true;
}
return false;
}
inline bool Set(unsigned int i,unsigned int j,const T & value = T()){
if(width == 0 || height == 0)return false;
if(i>=width || j>=height)return false;
buffer[i*width+j] = value;
return true;
}
inline void Init(const T & value = T()){
for(unsigned int i = 0;i<width*height;++i){
buffer[i] = value;
}
}
inline const unsigned int & GetWidth()const{
return width;
}
inline const unsigned int & GetHeight()const{
return height;
}
void print(){
T temp;
for(unsigned int i = 0 ;i<height ; ++i){
for(unsigned int j=0;j<width;++j){
this->Get(i,j,&temp);
std::cout<<temp<<"\t";
}
std::cout<<std::endl;
}
}
};

#endif


#ifndef RIPPLE_H
#define RIPPLE_H

#include "MyMatrix.h"
#include <utility>
#define delta 0.1

//扔石头,能量值为32-128
void DropStone(MyMatrix<float> * matrix,unsigned int i,unsigned int j,unsigned int size,float energy){
unsigned int left = std::max<unsigned int>(i-size,(unsigned int)0);
unsigned int top = std::max<unsigned int>(j-size,(unsigned int)0);
unsigned int right = std::min<unsigned int>(i+size,matrix->GetWidth());
unsigned int bottom = std::min<unsigned int>(j+size,matrix->GetHeight());

unsigned int center_x = i,center_y = j;

for(unsigned int i=top;i<bottom;++i){
for (unsigned int j=left;j<right;++j)
{
if(sqrt((i-center_x)*(i-center_x)+(j-center_y)*(j-center_y))<size){
matrix->Set(i,j,-energy);
}
}
}
}

void RippleSpread(MyMatrix<float> * matrix,bool * isEnd = NULL){
int nWidth = matrix->GetWidth();
int nHeight = matrix->GetHeight();
float temp,up,down,left,right;
bool end = true;

if(nWidth>=3 && nHeight>=3){
for(int i = 1;i<nHeight-1;++i){
for (int j = 1;j<nWidth-1;++j)
{
matrix->Get(i-1,j,&up);
matrix->Get(i+1,j,&down);
matrix->Get(i,j-1,&left);
matrix->Get(i,j+1,&right);

if( abs(up)<delta )
up=0;
if( abs(down)<delta )
down=0;
if( abs(left)<delta )
left=0;
if( abs(right)<delta )
right=0;

if(up!=0 || down!=0 || left!=0 || right!=0)end = false;
matrix->Get(i,j,&temp);
temp = (up+down+left+right)/2-temp;
temp -= temp/32;
if( abs(temp)<delta )temp=0;
matrix->Set(i,j,temp);
}
}
}

if (isEnd!=NULL)
{
*isEnd = end;
}
}

#endif



CPaintDC dc(this); // 用于绘制的设备上下文

// TODO: 在此处添加消息处理程序代码
CRect rect;
GetClientRect( &rect );
int x = rect.CenterPoint().x;
int y = rect.CenterPoint().y;
int nWidth = rect.Width();
int nHeight = rect.Height();

HDC screenHdc = ::GetDC(NULL);

Graphics graph(dc.m_hDC); // 创建图形对象
//Graphics graph(screenHdc);

using Gdiplus::Font;FontFamily fontFamily( L"宋体" );Font font( &fontFamily , 20);
Image img(L"C:\\Users\\qianyuxiang\\Desktop\\米老鼠和唐老鸭.bmp");

Bitmap bitmap( L"C:\\Users\\qianyuxiang\\Desktop\\米老鼠和唐老鸭.bmp" );
Color oldColor,newColor;BYTE a,r,g,b;
int w = bitmap.GetWidth(),h = bitmap.GetHeight();

Color whiteTransparent = Color::MakeARGB(100,255,255,255);

if(!matrix){
matrix = new MyMatrix<float>(w,h);
DropStone(matrix,h/2,w/2,30,128);
}

Bitmap * bitmap_done = bitmap.Clone(0,0,w,h,PixelFormat32bppARGB);

static bool isEnd = false;

#ifdef _D
int delta_x,delta_y,position_x,position_y;
float left,right,up,down;

RippleSpread(matrix,&isEnd);

for(int i=0;i<w;++i)
{
for (int j=0;j<h;++j)
{
if (i!=0 && i!=w-1 && j!=0 && j!=h-1)
{
matrix->Get(j,i+1,&right);
matrix->Get(j,i-1,&left);
matrix->Get(j-1,i,&up);
matrix->Get(j+1,i,&down);
delta_x=right-left;
delta_y=up-down;
position_x=std::max<unsigned int>(0,std::min<unsigned int>(w-1,i+delta_x));
position_y=std::max<unsigned int>(0,std::min<unsigned int>(h-1,j+delta_y));
bitmap_done->GetPixel(i,j,&oldColor);
bitmap_done->SetPixel(position_x,position_y,oldColor);
}
}
}
#endif


实现了之后发现就是杂乱无章的乱窜,没有水纹的效果。
原理的倒数第二步,根据波能数据缓冲区对离屏页面进行渲染,意思是将左右点的插值和上下点的差值,作为该点处像素的平移向量吗?
...全文
86 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

64,651

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧