Flame algorithm (used in Fuzzy algorithms)

Source: Internet
Author: User

A long time ago, I saw the algorithms for special effects on water waves and recently the algorithms for special effects on flame. There are many similarities between the two, I have translated an article on flame effects. For more information, see. For more information, see quantity! The author of this article is humorous and has a limited level, so the original text is used in some places.

Flame Effects
Translate Shaun Patterson into beauli
Flame effect may be one of my favorite special effects in all special effects. It is worthwhile to design a very effective flame routine.
In this article, I will show you how to create a very beautiful flame effect under DirectX 5.0. I think you will be able to design in any language as long as you study it carefully.
First, I will not talk about how to create DirectDraw surface or add any interesting practical code to the Code (this article is only about the theory of flame effects ). I guess you can find it on sweet. oblivion or gpmloud. However, I will show you how to create a palette, create a simple loop, and draw a flame. Flame is actually a relatively simple special effect, and programming it has a bit of entertaining taste.
Unfortunately, I do not understand assembly, so it is not the fastest flame routine in the world. However, it was incredibly fast running on my P2, and it did a good job on my p75.

Now, let's go to the subject. First, you must create a palette to make your code run. I did this:
Black (on the top of the flame effect), red, orange, and yellow at the bottom.
I just used some loops to create our own 256 colors. Now we need a "Container" to store our palette information.
Lpdirectdrawpalette lpddpal; // the palette object
Paletteentry mypal [256]; // stores palette stuff
I think this is a very appropriate comment. Now, we need to load our information. First, we load our RGB information into every array entry of mypal. (Why do I use loops)
Index = 0;

For (Index = 95; index <200; index ++)
{
Mypal [Index]. pered = index + 70;
Mypal [Index]. pegreen = index + 30;
Mypal [Index]. peblue = rand () % 10;
}
For (Index = 1; index <35; index ++)
{
Mypal [Index]. pered = index + 25;
Mypal [Index]. pegreen = rand () % 10;
Mypal [Index]. peblue = rand () % 10;
}
For (Index = 35; index <55; index ++)
{
Mypal [Index]. pered = index + 25;
Mypal [Index]. pegreen = index-25;
Mypal [Index]. peblue = rand () % 10;
}
For (Index = 55; index <95; index ++)
{
Mypal [Index]. pered = index + 75;
Mypal [Index]. pegreen = index;
Mypal [Index]. peblue = rand () % 5;
}
For (Index = 200; index <255; index ++)
{
Mypal [Index]. pered = index;
Mypal [Index]. pegreen = index-rand () % 25;
Mypal [Index]. peblue = rand () % 5;
}
This is the best structure I have found. Although it took me less than 10 minutes.
Everything is basically to load RGB values into entries in each of our palette arrays. In the mypal structure, the pered member is a red value, while the pegreen is a green value, and so on.
Now we are close to the values of the palette object (lpddpal) and the home page (primary surface. We only need to use the following statement to use the color palette.
Lpdd-> createpalette (ddpcaps_8bit | ddpcaps_allow256, mypal, & lpddpal, null );
Lpddsprimary-> setpalette (lpddpal );
Lpdd -- DirectDraw object
Lpddsprimary -- primary surface

With me so far? No? Hmm, not good. Go read another tutorial then! Geez! People these days...
Still holding your breath? Well breathe. The rest is a breeze.


Dun dun dunnnn
Flame Algorithm
First, I made a small program to lock the background page so that we could paint.

Unsigned char * lock_back_buffer (void)
{
Ddsurfacedesc ddsd;
Hresult ret;
Ddsd. dwsize = sizeof (ddsd );

Ret = dderr_wasstilldrawing;

While (ret = dderr_wasstilldrawing)
Ret = lpddsback-> lock (null, & ddsd, 0, null );

Return (ret = dd_ OK? (Unsigned char *) ddsd. lpsurface: NULL );
}

This function returns an unsigned char pointer pointing to the screen structure, so we need to create a screen structure.

Unsigned char * double_buffer = NULL;

Next, we will allocate some memory space for it.

Double_buffer = (unsigned char X) malloc (307200 );

Oh yeah. I work at a resolution of 640x480x8bit.

Next, we need another unsigned char pointer array to store our flame pixels.

Unsigned char * fire_buffer = NULL;
Fire_buffer = (unsigned char *) malloc (307200 );

Do not forget to release these spaces explicitly at the end.

Free (double_buffer); free (fire_buffer );

OK... whew. Now, create the flame part and draw some random points at the bottom of the screen (the last line). The color of these dots can be set to 0 or 255. Do the following:

For (x = 1; x <637; x + = rand () % 3)
{
If (RAND () % 2)
Fire_buffer [(480*640) + x] = 255;
Else
Fire_buffer [(480*640) + x] = 0;
}
The above is my favorite practice. Of course, you can also choose not to use random points.
Well, this is my method of making a flame. Select a pixel background pixel and remove it with the number of pixels. Now you may be thinking -- what ?! Okay, it's easy. Do you have a point? If you are familiar with pixel rendering, you must also know the method for finding vertices in a pointer array in the 1D array-y position * screenwidth + X position. Are you confused? Good. This indicates that you have started thinking =)
Think about it like a typewriter.

Tap tap ca Ching-Next line
Tap tap ca Ching-Next line
Tap tap ca Ching-Next line

Etc...

In this example, the screen has only 6 tap widths & #61514 ;. Well, the pixels you want to draw are in the third column of the second row. 2*6 =? 12.
12 + 3 =? 15. Whoa! Complete in one breath.
Now count 1, 2, 3... 15. Wait, we are now in the third line !! Does the start count start from 0 and then 1, 2, and 3? SO 2*6 = 12, 12 + 3 = 15 (the original article is so 1*6 is 6. Then 6 + 3 is 9. It may be a mistake ). Now, let's start the assignment.
Ah! What should we do next? By the way, use a loop. We need to draw the entire screen of the flame through loops. Start to enter the loop, first y and then X. You will understand immediately. In the cycle of X, as I previously mentioned, we average the surrounding pixels to get new pixels. Do not forget the palette ). If the random pixel value is 255, It is yellow. If it is 0, it is black. Next, 255 + 0 =? 255. 255/2 =? 128. Whoa !! We get the vertices in the orange area in the color palette. This is the most basic point of all flames. When the flame rises, you can average the color to get a new color. At this time, the more you think, the more you will understand. It starts to yellow, orange, red, and then black when it reaches a very red color. When the flame rises, it will become cool. You can see in the example.

Pseudo code:

For y = 1, y to screenheight, increment y
For x = 1, x to screenwidth, increment x
Find our offset-What pixel we are going to start
Averaging around-(y * screenheight) + x
Add up the surrounding pixels-all eight of them
Divide that total by 8-hard concept there =)

Now if that value is not 0-not black
We decrement it-subtract 1 =)

End

Draw to our back buffer

End

Okay, next is the c ++ code.

Int X, Y, fireoffset;


// Calculate the bottom line pixels
For (x = 1; x <637; x + = rand () % 3)
{
If (RAND () % 2)
Fire_buffer [(480*640) + x] = 255;
Else
Fire_buffer [(480*640) + x] = 0;
}
}

// Calculate the surrounding pixels
For (y = 1; y <480; ++ y)
{
For (x = 1; x <640; ++ X)
{
Fireoffset = (y * 640) + X;
Firevalue = (fire_buffer [fireoffset-640] +
Fire_buffer [fireoffset + 640] +
Fire_buffer [fireoffset + 1] +
Fire_buffer [fireoffset-1] +
Fire_buffer [fireoffset-641] +
Fire_buffer [fireoffset-639] +
Fire_buffer [fireoffset + 641] +
Fire_buffer [fireoffset + 639])/8); // This can be optimized by
// Look up table as I'll show you later

If (firevalue! = 0) // is it black?
{
-- Firevalue; // nope. Beam me down Scotty.
Fire_buffer [fireoffset-640] = firevalue; // plot that new color
// On the above Pixel
// Remember the typewriter analogy
}
}
}

Double_buffer = lock_back_buffer (); // remember this function? Good
Memcpy (double_buffer, fire_buffer, (640*480); // copy fire buffer to the screen
Lpddsback-> unlock (null); // unlock! Important! You have no idear!

Well, you may have thought it hard to understand it, but it is very simple to think about it.
We can find this pixel point, which we discussed above -- y * 640 + X, which is our fireoffset -- this point is the center point we use for average.
Now fireoffset-640 =? Is it at the top of this point? Fireoffset-639 =? It is located at the top of the vertex but slightly to the right. So it is the point in the upper right corner. Fireoffset + 640 =? At the bottom of the page. Do you understand ??
I said it was very simple, didn't it? Ha! You don't trust me. I think it may have been a bit confused. But after you think about it, you will understand it all at once-like me. For more information, see)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.