动态模拟粒子溃堤效果

这是一个C#代码示例,用于创建一个动态模拟粒子溃堤效果的程序。程序初始化设定最大粒子数,使用颜色数组实现彩虹效果,并通过随机数生成器设置粒子的初始位置、速度和方向。代码中包含粒子系统的初始化、更新和绘制方法,以及纹理加载和面向摄像机的平移矩阵计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

火灾模拟

 

using System;
using System.Collections.Generic;
using System.Text;
using ESRI.ArcGIS.Geometry;
using CsGL.Basecode;
using CsGL.OpenGL;
using System.Drawing.Imaging;
using CsGL;
using System.Drawing;
using ESRI.ArcGIS.Analyst3D;

namespace USTC
{
    /// <summary>
    /// 使用如下:
    ///  Particles pt = new Particles();
    /// pt.initParticles(@"D:/rr.bmp",this.m_sceneViwer);
    ///  pt.DrawParticles(pp.glX,pp.glY,pp.glZ);
    /// </summary>
    class Particles
    {
        #region Private Fields
        private const int MAX_PARTICLES = 300;                                            // Number Of Particles To Create
        private static bool rainbow = true;                                                // Rainbow Mode?
        private static bool sbp;                                                        // Space Bar Pressed?
        private static bool rp;                                                            // R Pressed?

        private static float slowdown = 2.0f;                                            // Slow Down Particles
        private static float xspeed = 0.0f;                                                // Base X Speed (To Allow Keyboard Direction Of Tail)
        private static float yspeed = 0.0f;                                                // Base Y Speed (To Allow Keyboard Direction Of Tail)
        private static float zoom = -40.0f;                                                // Used To Zoom Out

        private static uint loop;                                                        // Misc Loop Variable
        private static uint col;                                                        // Current Color Selection
        private static uint delay;                                                        // Rainbow Effect Delay
        private static uint[] texture = new uint[1];                                    // Our Particle Texture

        private struct Particle
        {                                                        // Create A Structure For Particle
            public bool active;                                                            // Active True / False
            public float life;                                                            // Particle Life
            public float fade;                                                            // Fade Speed
            public float r;                                                                // Red Value
            public float g;                                                                // Green Value
            public float b;                                                                // Blue Value
            public float x;                                                                // X Position
            public float y;                                                                // Y Position
            public float z;                                                                // Z Position
            public float xi;                                                            // X Direction
            public float yi;                                                            // Y Direction
            public float zi;                                                            // Z Direction
            public float xg;                                                            // X Gravity
            public float yg;                                                            // Y Gravity
            public float zg;                                                            // Z Gravity
        }

        private static Particle[] particle = new Particle[MAX_PARTICLES];                // Particle Array

        private static float[][] colors = new float[12][] {                                // Rainbow Of Colors
            new float[] {1.0f,  0.5f,  0.5f},
            new float[] {1.0f,  0.75f, 0.5f},
            new float[] {1.0f,  1.0f,  0.5f},
            new float[] {0.75f, 1.0f,  0.5f},
            new float[] {0.5f,  1.0f,  0.5f},
            new float[] {0.5f,  1.0f,  0.75f},
            new float[] {0.5f,  1.0f,  1.0f},
            new float[] {0.5f,  0.75f, 1.0f},
            new float[] {0.5f,  0.5f,  1.0f},
            new float[] {0.75f, 0.5f,  1.0f},
            new float[] {1.0f,  0.5f,  1.0f},
            new float[] {1.0f,  0.5f,  0.75f}
        };
        private static Random rand = new Random();                                        // Random Number Generator
        #endregion Private Fields
        private double[] m_modelViewMatrix = null;
        private double[] m_billboardMatrix = null;
        private ISceneViewer m_sceneViwer = null;
        #region 粒子系统计算
        public void initParticles(string filename, ISceneViewer  sceneViwer)
        {
            this.m_sceneViwer = sceneViwer;
            texture[0] = OpenGLTool.CreateTexture(filename);
            // Jump To Texture Loading Routine
            m_modelViewMatrix = new double[16];
            m_billboardMatrix = new double[16];

            for (loop = 0; loop < MAX_PARTICLES; loop++)
            {            // Initialize All The Particles
                particle[loop].active = true;                                            // Make All The Particles Active
                particle[loop].life = 1.0f;                                                // Give All The Particles Full Life
                particle[loop].fade = (rand.Next() % 100) / 1000.0f + 0.003f;            // Random Fade Speed
                particle[loop].r = colors[loop * (12 / MAX_PARTICLES)][0];                // Select Red Rainbow Color
                particle[loop].g = colors[loop * (12 / MAX_PARTICLES)][1];                // Select Red Rainbow Color
                particle[loop].b = colors[loop * (12 / MAX_PARTICLES)][2];                // Select Red Rainbow Color
                particle[loop].xi = ((rand.Next() % 50) - 26.0f) * 10.0f;                // Random Speed On X Axis
                particle[loop].yi = ((rand.Next() % 50) - 25.0f) * 10.0f;                // Random Speed On Y Axis
                particle[loop].zi = ((rand.Next() % 50) - 25.0f) * 10.0f;                // Random Speed On Z Axis
                particle[loop].xg = 0.0f;                                                // Set Horizontal Pull To Zero
                particle[loop].yg = -0.8f;                                                // Set Vertical Pull Downward
                particle[loop].zg = 0.0f;                                                // Set Pull On Z Axis To Zero
            }

        }
        #endregion

        public void DrawParticles(double dx,double dy,double dz)
        {
            GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX, m_modelViewMatrix);

            //populate the billboard matrix
            m_billboardMatrix[0] = m_modelViewMatrix[0];
            m_billboardMatrix[1] = m_modelViewMatrix[4];
            m_billboardMatrix[2] = m_modelViewMatrix[8];
            m_billboardMatrix[3] = 0;

            m_billboardMatrix[4] = m_modelViewMatrix[1];
            m_billboardMatrix[5] = m_modelViewMatrix[5];
            m_billboardMatrix[6] = m_modelViewMatrix[9];
            m_billboardMatrix[7] = 0;

            m_billboardMatrix[8] = m_modelViewMatrix[2];
            m_billboardMatrix[9] = m_modelViewMatrix[6];
            m_billboardMatrix[10] = m_modelViewMatrix[10];
            m_billboardMatrix[11] = 0;

            m_billboardMatrix[12] = 0;
            m_billboardMatrix[13] = 0;
            m_billboardMatrix[14] = 0;
            m_billboardMatrix[15] = 1;

            GL.glEnable(GL.GL_TEXTURE_2D);                                                    // Enable Texture Mapping
            //glClearColor(0.0f, 0.0f, 0.0f, 0.0f);                                        // Black Background
            //GL.glDisable(GL.GL_DEPTH_TEST);                                                    // Disables Depth Testing
            //GL.glEnable(GL.GL_BLEND);                                                            // Enable Blending
            //GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);                                    // Type Of Blending To Perform
            //GL.glHint(GL.GL_POINT_SMOOTH_HINT, GL.GL_NICEST);                                    // Really Nice Point Smoothing
            GL.glBindTexture(GL.GL_TEXTURE_2D, texture[0]);                                    // Select Our Texture
            double dblObsX, dblObsY, dblObsZ, dMagnitude, scale;
            ICamera camera = m_sceneViwer.Camera;
            camera.Observer.QueryCoords(out dblObsX, out dblObsY);
            dblObsZ = camera.Observer.Z;
            for (loop = 0; loop < MAX_PARTICLES; loop++)
            {                                // Loop Through All The Particles
                if (particle[loop].active)
                {                                                // If The Particle Is Active
                    float x = particle[loop].x / 1000 + (float)dx;                                            // Grab Our Particle X Position
                    float y = particle[loop].y / 1000 + (float)dy;                                            // Grab Our Particle Y Position
                    float z = (particle[loop].z) / 1000 + (float)dz;                                    // Particle Z Pos + Zoom
                    IVector3D m_vector3D = new Vector3DClass();
                     m_vector3D .SetComponents(dblObsX -dx, dblObsY - dy, dblObsZ - dz);
                    dMagnitude = m_vector3D.Magnitude;

                    scale = 0.01 * dMagnitude;
                    GL.glDisable(GL.GL_LIGHTING);
                    GL.glEnable(GL.GL_BLEND);
                    GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
                    GL.glDepthFunc(GL.GL_LEQUAL);
                    // GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);                            // Clear Screen And Depth Buffer
                    // GL.glLoadIdentity();                                                            // Reset The Current Modelview Matrix
                    GL.glPushMatrix();
                   // GL.glAlphaFunc(GL.GL_GREATER, 0.5f);
                    //translate to the items location
                    GL.glTranslatef((float)x, (float)y, (float)z);

                    //orient the icon so that it'll face the camera
                    OrientBillboard();

                    //scale the item (original size is 1 ubit)
                    GL.glScaled(scale, scale, 1.0);

                    // Draw The Particle Using Our RGB Values, Fade The Particle Based On It's Life
                  //  GL.glColor4f(particle[loop].r, particle[loop].g, particle[loop].b, particle[loop].life);

                    // GL.glBegin(GL.GL_TRIANGLE_STRIP);        // Build Quad From A Triangle Strip
                    GL.glBegin(GL.GL_QUADS);
                    GL.glTexCoord2d(1, 1); GL.glVertex3f(0.5f, 0.5f, 0);            // Top Right
                    GL.glTexCoord2d(0, 1); GL.glVertex3f(-0.5f, 0.5f, 0);            // Top Left
                    GL.glTexCoord2d(1, 0); GL.glVertex3f(0.5f, -0.5f, 0);            // Bottom Right
                    GL.glTexCoord2d(0, 0); GL.glVertex3f(-0.5f, -0.5f, 0);            // Bottom Left
                    GL.glEnd();
                    GL.glPopMatrix();// Done Building Triangle Strip
                    // GL.glPolygonMode(GL.GL_FRONT, GL.GL_FILL);
                    particle[loop].x += particle[loop].xi / (slowdown * 1000);            // Move On The X Axis By X Speed
                    particle[loop].y += particle[loop].yi / (slowdown * 1000);            // Move On The Y Axis By Y Speed
                    particle[loop].z += particle[loop].zi / (slowdown * 1000);            // Move On The Z Axis By Z Speed
                    particle[loop].xi += particle[loop].xg;                                // Take Pull On X Axis Into Account
                    particle[loop].yi += particle[loop].yg;                                // Take Pull On Y Axis Into Account
                    particle[loop].zi += particle[loop].zg;                                // Take Pull On Z Axis Into Account
                    particle[loop].life -= particle[loop].fade;                            // Reduce Particles Life By 'Fade'
                    if (particle[loop].life < 0.0f)
                    {                                    // If Particle Is Burned Out
                        particle[loop].life = 1.0f;                                        // Give It New Life
                        particle[loop].fade = (rand.Next() % 100) / 1000.0f + 0.003f;    // Random Fade Value
                        particle[loop].x = 0.0f;                                        // Center On X Axis
                        particle[loop].y = 0.0f;                                        // Center On Y Axis
                        particle[loop].z = 0.0f;                                        // Center On Z Axis
                        particle[loop].xi = (xspeed + (rand.Next() % 60)) - 32.0f;        // X Axis Speed And Direction
                        particle[loop].yi = (yspeed + (rand.Next() % 60)) - 30.0f;        // Y Axis Speed And Direction
                        particle[loop].zi = (rand.Next() % 60) - 30.0f;                    // Z Axis Speed And Direction
                        particle[loop].r = colors[col][0];                                // Select Red From Color Table
                        particle[loop].g = colors[col][1];                                // Select Green From Color Table
                        particle[loop].b = colors[col][2];                                // Select Blue From Color Table
                    }

                }
            }
            delay++;
            // Increase Rainbow Mode Color Cycling Delay Counter
            if (rainbow && (delay > 25))
            {                                                // If rainbow Is On And delay Is Too High
                delay = 0;                                                                // Reset The Rainbow Color Cycling Delay
                col++;                                                                    // Change The Particle Color
                if (col > 11)
                {                                                            // If col Is Too High
                    col = 0;                                                            // Reset It
                }
            }
            GL.glDisable(GL.GL_BLEND);

        }
        private void LoadTextures(string filename)
        {
            //string filename = @"D:/OpenGL专题3D/CsGLExamples/data/NeHeLesson19/Particle.bmp";                    // The File To Load
            Bitmap bitmap = null;                                                        // The Bitmap Image For Our Texture
            Rectangle rectangle;                                                        // The Rectangle For Locking The Bitmap In Memory
            BitmapData bitmapData = null;                                                // The Bitmap's Pixel Data

            // Load The Bitmap
            try
            {
                bitmap = new Bitmap(filename);                                            // Load The File As A Bitmap
                bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);                        // Flip The Bitmap Along The Y-Axis
                rectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height);            // Select The Whole Bitmap

                // Get The Pixel Data From The Locked Bitmap
                bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

                GL.glGenTextures(1, texture);                                                // Create 1 Texture
                // Create Linear Filtered Texture
                GL.glBindTexture(GL.GL_TEXTURE_2D, texture[0]);
                GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
                GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
                GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, (int)GL.GL_RGB8, bitmap.Width, bitmap.Height, 0, GL.GL_BGR_EXT, GL.GL_UNSIGNED_BYTE, bitmapData.Scan0);
            }
            catch (Exception e)
            {
                // Handle Any Exceptions While Loading Textures, Exit App
                string errorMsg = "An Error Occurred While Loading Texture:/n/t" + filename + "/n" + "/n/nStack Trace:/n/t" + e.StackTrace + "/n";
                //MessageBox.Show(errorMsg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);

            }
            finally
            {
                if (bitmap != null)
                {
                    bitmap.UnlockBits(bitmapData);                                        // Unlock The Pixel Data From Memory
                    bitmap.Dispose();                                                    // Clean Up The Bitmap
                }
            }
        }
        /// <summary>
        /// orient the icons so that it'll face the camera
        /// </summary>
        private void OrientBillboard()
        {
            GL.glMultMatrixd(m_billboardMatrix);
        }
    }
}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值