Tag: des OS using the For SP data on Problem code
The wave has the following characteristics:
Diffusion: When you cast a stone into the water, you will see a circle of water waves formed by the point of the stone into the center, where you may be misled by the phenomenon that every point on the water waves is spread out in the direction of the point of the stone, which is wrong. In fact, any point on the water is spread around at all times by itself, and the reason for the formation of a circular wave is that the interior of the water waves is offset by the symmetry of the diffusion.
Attenuation: Because the water is damp, otherwise, when you put stones in the pool, the waves will never stop the concussion.
Water refraction: Because the angle of inclination of different places in the water waves is different, so because of the refraction, the bottom we see from the point of view is not directly below the observation point, but there is a certain offset. This is why we can feel the shape of the waves without considering the reflection of the light at the top of the water.
Reflections: Water waves are reflected when they encounter obstacles.
Diffraction: Suddenly think of this point, but in the program is not seen, if you can put a rock in the center of the pool, or put a gap in the middle of the plate, then you can see the diffraction phenomenon of water waves.
Well, with these features, and using math and geometry, we can simulate real water waves. However, if you've ever animated a wave in 3DMax, you'll know that it takes dozens of seconds to render a real-world water wave, and what we need now is a real-time rendering, with at least 20 frames per second to make the water waves appear smooth. Considering the speed of computer operation, we can not construct the water waves according to the sine function or the exact formula, can not use the multiplication method, more can not use sin, cos, can only use a fast approximation of the algorithm, although the algorithm has some errors, but in order to meet the real-time animation requirements, we have to do so.
First we will build two arrays of the same size as the pool image buf1[poolwidth*poolheight] and buf2[poolwidth*poolheight] (the pixel width of the poolwidth= pool image, poolheight= The pixel height of the pool image), which is used to hold the previous and next moment amplitude data for each point on the water, since the amplitude also represents the energy of the wave, so later we call the two arrays as the energetic buffers. The water surface is a plane at the initial state, and the amplitude of each point is 0, so the initial values of the two arrays are equal to 0.
The formula for calculating the amplitude is deduced below.
We assume that there is such a formula, at any moment according to a point around the front, back, left and right four points and the amplitude of the point itself to calculate the next moment of the amplitude of the point, then, we may use the inductive method to find any moment of the surface of the amplitude of any point. As shown on the left, you can see that at some point the amplitude of the X0 points is affected by the amplitude of the X0 point itself, at the same time by the influence of the front, rear, left, and right four points (X1, X2, X3, X4) around it (in order to simplify, we ignore all other points), and, The influence of these four points on the A0 point can be said to be equal opportunity. Then we can assume that this one-time formula is:
X0 ' =a (x1+x2+x3+x4) +bx0 (equation 1)
A, B is the undetermined coefficient, X0 ' is the amplitude of the next moment at 0.
X0, X1, X2, X3, X4 are the amplitudes of the current moment.
Let's solve A and B.
Suppose the damping of water is 0. Under this ideal condition, the total potential energy of the water will remain unchanged. That is, at any moment, the amplitude of all points remains the same. Then you can get the following formula:
X0 ' +x1 ' +...+xn ' = X0+x1+...+xn
Each point is calculated as the Formula 1, and then put into the equation to get:
(4a+b) x0+ (4a+b) x1+ ... (4a+b) Xn = X0+x1+...+xn
=>4a+b=1
Find a simple solution: a = 1/2, B =-1
Since 1/2 can be done with the shift operator ">>" without the multiplication method, this group of solutions is the most applicable and the quickest. So the last formula that we get is:
X0 ' = (x1+x2+x3+x4)/2-x0
Well, with the approximate formula above, you can generalize to the following general conclusion: the amplitude at any point on the surface of a given moment is known, then, at the next moment, the amplitude of any point is equal to the amplitude of the front, back, left, and right four points adjacent to the point and divided by 2, minus the amplitude of that point.
It should be noted that water in practice is damped, otherwise, with the above formula, once you add a waves in the water, the water will never stop the shock. Therefore, the amplitude data also need to be attenuated processing, so that each point after a calculation, the amplitude is lower than the ideal value at a certain proportion. This attenuation rate has been tested, with 1/32 more appropriate, namely 1/2^5. Can be obtained quickly through the shift operation.
Here, the hardest part of the water-wave effect is over, and here's the code that calculates the amplitude data in the source program.
//*******************************************************
Calculate the wave data buffer
//*******************************************************
void Ripplespread ()
{
for (int i=backwidth; i<backwidth*backheight-backwidth; i++)
{
Wave Wave diffusion
Buf2[i] = ((buf1[i-1]+
buf1[i+1]+
buf1[i-backwidth]+
Buf1[i+backwidth])
>>1)
-Buf2[i];
Wave attenuation
Buf2[i]-= buf2[i]>>5;
}
Exchanging wave energy data buffers
Short *ptmp =buf1;
BUF1 = Buf2;
Buf2 = ptmp;
}
All right, here we go. Renders the page according to the calculated amplitude data.
Because of the refraction of water, when the surface of the water is not perpendicular to our vision, we see the underwater scenery is not at the point of observation is directly below, and there is a certain offset. The degree of migration is related to the slope of the water wave, the refractive index of the waters and the depth of water, which is obviously unrealistic if accurate calculations are to be made. Similarly, we just need to do the approximate processing of the line. Because the more inclined the water surface, the more we see the underwater scenery offset, so, we can approximate the surface of a point on the front and back, left and right two points of the amplitude difference to represent the observed underwater scenery offset.
In the program, the original image is loaded with one page, and another page is used to render it. Lock two pages with the lock function, get a pointer to the memory area of the page, and then copy each pixel on the original image to the rendered page, based on the offset. The code for page rendering is as follows: (the following code is not optimized for ease of understanding, in fact, the optimized code is much more cumbersome than it is)
//*******************************************************
Render off-screen pages according to the wave data buffer
//*******************************************************
void Renderripple ()
{
Lock two off-screen pages
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);
Gets the page pixel depth, and the page memory pointer
int DEPTH=DDSD1.DDPFPIXELFORMAT.DWRGBBITCOUNT/8;
BYTE *bitmap1 = (byte*) ddsd1.lpsurface;
BYTE *bitmap2 = (byte*) ddsd2.lpsurface;
Page Rendering below
int Xoff, Yoff;
int k = Backwidth;
for (int i=1; i<backheight-1; i++)
{
for (int j=0; j<backwidth; j + +)
{
Calculate offset
Xoff = buf1[k-1]-buf1[k+1];
Yoff = Buf1[k-backwidth]-buf1[k+backwidth];
Determines whether the coordinates are within the window range
if ((I+yoff) < 0) {k++; continue;}
if ((I+yoff) > Backheight) {k++; continue;}
if ((J+xoff) < 0) {k++; continue;}
if ((J+xoff) > Backwidth) {k++; continue;}
Calculates the memory address offset of the offset pixel and the original pixel
int pos1, Pos2;
pos1=ddsd1.lpitch* (I+yoff) + depth* (J+xoff);
pos2=ddsd2.lpitch*i+ depth*j;
Copy pixels
for (int d=0; d<depth; d++)
Bitmap2[pos2++]=bitmap1[pos1++];
k++;
}
}
Unlock page
Lpddspic1->unlock (&DDSD1);
Lpddspic2->unlock (&DDSD2);
}
Increase waves
As the saying goes: Smoke, in order to form waves, we have to add waves to the pool, you can imagine into the water into the stone, the formation of the waves size and energy and the radius of the stone and you throw the force of the stone is related. Knowing this, well, we just need to modify the wave data buffer buf, let it in the stone into the water place to a negative "sharp pulse", that is, let buf[x,y]=-n. After experiments, the range of n is more appropriate between (32~128).
Control waves radius Well done, you just take the stone into the center of the water point, draw a radius of the stone radius of the circle, so that all the points in the circle so a negative "sharp pulse" on it (here also do approximate treatment).
The code for adding waves is as follows:
//*****************************************************
Increase waves
//*****************************************************
void Dropstone (int x,//x coordinates
int y,//y coordinates
int stonesize,//Waves Radius
int stoneweight)//Waves Energy
{
Determine if the coordinates are within the screen range
if ((x+stonesize) >backwidth | |
(y+stonesize) >backheight| |
(x-stonesize) <0| |
(y-stonesize) <0)
Return
for (int posx=x-stonesize; posx<x+stonesize; posx++)
for (int posy=y-stonesize; posy<y+stonesize; posy++)
if ((posx-x) * (posx-x) + (posy-y) * (posy-y) < stonesize*stonesize)
BUF1[BACKWIDTH*POSY+POSX] =-stoneweight;
}
Well, so far, the production principle of the water-wave effect has been revealed in this regard. In the above deduction, there are a lot of seemingly outrageous approximations at each step, but you don't have to worry about it, and it turns out that using this method can be very good at both speed and image. The source program has very detailed comments, careful scrutiny, to understand that they should not be a problem.
This program is WIN32 under DirectX programming and does not use any wrapper libraries. On my Computer (amdk6-200, 2MVRam, 64MSRam), the screen size, can reach 25 frames per second. Unlike the previous programs, this program uses windowed mode, so debugging is convenient. This program is also a good example if you are unfamiliar with window-mode programming.
This data buffer to the image of the water wave processing method, there is one of the greatest advantage is that the program and its speed is not related to the complexity of the water waves, regardless of whether the surface is calm or choppy, the program's FPS has remained unchanged, this point you should be able to look at the program can be seen. In fact, if you have mastered this method, this method will be able to make other special effects, such as smoke, atmosphere, sunlight, etc., I am now studying the production of these special effects, I believe it will soon be a new harvest.
C + + simulates the formation of water waves