zoukankan      html  css  js  c++  java
  • D3D中的粒子系统(4)

    14.3具体的粒子系统:雪、火、粒子枪

    现在让我们用cParticleSystem类开始一个具体的粒子系统,为了说明用意,这些系统的设计很简单,没有用到cParticleSystem类所提供的所有灵活性。我们实现雪、火、粒子枪系统。雪系统模拟下落的雪花,火系统模拟看上去像火焰的爆炸,粒子枪系统从照相机位置向对面发射出粒子(用键盘)。
    14.3.1 例子程序:雪

    雪系统类定义如下:
        class cSnow : public cParticleSystem
        {
        public:
            cSnow(cBoundingBox* bounding_box, int num_particles);
            virtual void reset_particle(sParticleAttribute* attr);
            virtual void update(float time_delta);
        };

    构造函数提供一个点给边界盒结构,边界盒是粒子系统的成员。边界盒描述雪花在哪个范围内(体积范围)下落,如果雪花出了边界盒,它将被杀死并再生。这样,雪系统始终能保存有同样数量的激粒子,构造函数的实现:
        cSnow::cSnow(cBoundingBox* bounding_box, int num_particles)
        {
            m_bounding_box    = *bounding_box;
            m_size            = 0.25f;
            m_vb_num        = 2048;
            m_vb_offset        = 0;
            m_vb_batch_num    = 512;
            for(int i = 0; i < num_particles; i++)
                add_particle();
        }

    同样注意:我们指定顶点缓存的尺寸,每一批的尺寸和开始的偏移。

    reset_particle方法创建一个雪花,在x、z轴随机的位置并在边界盒的范围内。设置y轴高度为边界盒的顶部。我们给雪花一个速度,以便让雪花下落时稍稍向左倾斜。雪花是白色的。
        void cSnow::reset_particle(sParticleAttribute* attr)
        {
            attr->is_alive = true;
            // get random x, z coordinate for the position of the snow flake
                get_random_vector(&attr->position, &m_bounding_box.m_min, &m_bounding_box.m_max);
            // no randomness for height (y-coordinate). 
            // Snow flake always starts at the top of bounding box.
                attr->position.y = m_bounding_box.m_max.y;
            // snow flakes fall downwards and slightly to the left
                attr->velocity.x = get_random_float(0.0f, 1.0f) * (-3.0f);
            attr->velocity.y = get_random_float(0.0f, 1.0f) * (-10.0f);
            attr->velocity.z = 0.0f;
            // white snow flake
            attr->color = WHITE;
        }

    update方法更新粒子和粒子间的位置,并且测试粒子是否在系统的边界盒之外,如果它已经跳出边界盒,就再重新创建。
        void cSnow::update(float time_delta)
        {
            for(list<sParticleAttribute>::iterator iter = m_particles.begin(); iter != m_particles.end(); iter++)
            {
                iter->position += iter->velocity * time_delta;
                // is the point outside bounds?
                if(! m_bounding_box.is_point_inside(iter->position))
                    // recycle dead particles, so respawn it.
                        reset_particle(&(*iter));
            }
        }

    执行程序:
        #include "d3dUtility.h"
        #include "camera.h"
        #include "ParticleSystem.h"
        #include <cstdlib>
        #include <ctime>
        #pragma warning(disable : 4100)
        const int WIDTH  = 640;
        const int HEIGHT = 480;
        IDirect3DDevice9*    g_device;
        cParticleSystem*    g_snow;
        cCamera                g_camera(AIR_CRAFT);
            ////////////////////////////////////////////////////////////////////////////////////////////////////
        bool setup()
        {   
            srand((unsigned int)time(NULL));
            // create snow system
            cBoundingBox bounding_box;
            bounding_box.m_min = D3DXVECTOR3(-10.0f, -10.0f, -10.0f);
            bounding_box.m_max = D3DXVECTOR3(10.0f, 10.0f, 10.0f);
            g_snow = new cSnow(&bounding_box, 5000);
            g_snow->init(g_device, "snowflake.dds");
            // setup a basic scnen, the scene will be created the first time this function is called.
                draw_basic_scene(g_device, 1.0f);
            // set the projection matrix
            D3DXMATRIX proj;
            D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI/4.0f, (float)WIDTH/HEIGHT, 1.0f, 1000.0f);
            g_device->SetTransform(D3DTS_PROJECTION, &proj);
            return true;
        }
            ///////////////////////////////////////////////////////////////////////////////////////////////////////
        void cleanup()
        {   
            delete g_snow;
            // pass NULL for the first parameter to instruct cleanup
            draw_basic_scene(NULL, 0.0f);
        }
            ///////////////////////////////////////////////////////////////////////////////////////////////////////
        bool display(float time_delta)
        {
            // update the camera
            if( GetAsyncKeyState(VK_UP) & 0x8000f )
                g_camera.walk(4.0f * time_delta);
            if( GetAsyncKeyState(VK_DOWN) & 0x8000f )
                g_camera.walk(-4.0f * time_delta);
            if( GetAsyncKeyState(VK_LEFT) & 0x8000f )
                g_camera.yaw(-1.0f * time_delta);
            if( GetAsyncKeyState(VK_RIGHT) & 0x8000f )
                g_camera.yaw(1.0f * time_delta);
            if( GetAsyncKeyState('N') & 0x8000f )
                g_camera.strafe(-4.0f * time_delta);
            if( GetAsyncKeyState('M') & 0x8000f )
                g_camera.strafe(4.0f * time_delta);
            if( GetAsyncKeyState('W') & 0x8000f )
                g_camera.pitch(1.0f * time_delta);
            if( GetAsyncKeyState('S') & 0x8000f )
                g_camera.pitch(-1.0f * time_delta);   
            // update the view matrix representing the camera's new position/orientation
            D3DXMATRIX view_matrix;
            g_camera.get_view_matrix(&view_matrix);
            g_device->SetTransform(D3DTS_VIEW, &view_matrix);   
            g_snow->update(time_delta);
            // render now
            g_device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
            g_device->BeginScene();
            D3DXMATRIX identity_matrix;
            D3DXMatrixIdentity(&identity_matrix);
            g_device->SetTransform(D3DTS_WORLD, &identity_matrix);
            draw_basic_scene(g_device, 1.0f);
            // order important, render snow last.
                g_device->SetTransform(D3DTS_WORLD, &identity_matrix);
            g_snow->render();
            g_device->EndScene();
            g_device->Present(NULL, NULL, NULL, NULL);
            return true;
        }
            ///////////////////////////////////////////////////////////////////////////////////////////////////////
        LRESULT CALLBACK wnd_proc(HWND hwnd, UINT msg, WPARAM word_param, LPARAM long_param)
        {
            switch(msg)
            {
            case WM_DESTROY:
                PostQuitMessage(0);
                break;
            case WM_KEYDOWN:
                if(word_param == VK_ESCAPE)
                    DestroyWindow(hwnd);
                break;
            }
            return DefWindowProc(hwnd, msg, word_param, long_param);
        }
            ///////////////////////////////////////////////////////////////////////////////////////////////////////
        int WINAPI WinMain(HINSTANCE inst, HINSTANCE, PSTR cmd_line, int cmd_show)
        {
            if(! init_d3d(inst, WIDTH, HEIGHT, true, D3DDEVTYPE_HAL, &g_device))
            {
                MessageBox(NULL, "init_d3d() - failed.", 0, MB_OK);
                return 0;
            }
            if(! setup())
            {
                MessageBox(NULL, "Steup() - failed.", 0, MB_OK);
                return 0;
            }
            enter_msg_loop(display);
            cleanup();
            g_device->Release();
            return 0;
        }

    下载源程序

  • 相关阅读:
    JDK源码之LinkedList
    MySQL常规知识点总结
    根据不同分辨率载入相应CSS样式表
    关于1.0.0版Backbone.js调用validate
    弹性盒模型计算
    使用CocoaPods
    Objective-C中的Block[转]
    将UTF8编码转化为中文 - NSString方法
    添加第三方类库造成的Undefined symbols for architecture i386:编译错误
    App适配iPhone 6/ Plus和iOS 8:10条小秘诀
  • 原文地址:https://www.cnblogs.com/flying_bat/p/1137670.html
Copyright © 2011-2022 走看看