• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            天行健 君子當(dāng)自強(qiáng)而不息

            Using Key?Framed Skeletal Animation(5)

            Check Out the Demos

            In this chapter, you learned how to load animation sets and use that data to animate your on−screen meshes. To better demonstrate these animation concepts, I have created a program (SkeletalAnim) that shows your favorite lady of skeletal−based animation, Microsoft's Tiny (from the DirectX SDK samples), doing what she does best walking around! When you run the demo application, you'll be greeted with a scene like the one shown in Figure 5.3.

            Figure 5.3: Tiny on the move in the SkeletalAnim demo! This demo shows you how to use skeletal−based animated meshes.

             

            SkeletalAnim.h:

            #ifndef SKELETAL_ANIM_H
            #define SKELETAL_ANIM_H

            #include 
            <windows.h>
            #include 
            "Direct3D.h"
            #include 
            "XParser.h"

            //=====================================================================================
            // Animation key type data structures
            //=====================================================================================
            struct sAnimVectorKey
            {
                DWORD        time;
                D3DXVECTOR3    vec;
            };

            struct sAnimQuatKey
            {
                DWORD            time;
                D3DXQUATERNION    quat;
            };

            struct sAnimMatrixKey
            {
                DWORD        time;
                D3DXMATRIX    matrix;
            };

            //=====================================================================================
            // Animation structures
            //=====================================================================================
            struct sAnimation
            {
                
            char*            bone_name;
                D3DXFRAME_EX
            *    bone;        // pointer to bone frame
                sAnimation*        next;        // next animation object in list

                
            // each key type and array of each type's keys

                DWORD            num_translation_keys;
                sAnimVectorKey
            *    translation_keys;

                DWORD            num_scale_keys;
                sAnimVectorKey
            *    scale_keys;

                DWORD            num_rotation_keys;
                sAnimQuatKey
            *    rotation_keys;

                DWORD            num_matrix_keys;
                sAnimMatrixKey
            *    matrix_keys;

                sAnimation()
                {
                    ZeroMemory(
            thissizeof(*this));
                }

                
            ~sAnimation()
                {
                    delete[] bone_name;    bone_name 
            = NULL;
                    delete[] translation_keys;
                    delete[] scale_keys;
                    delete[] rotation_keys;
                    delete[] matrix_keys;    

                    delete next;        next 
            = NULL;        
                }
            };

            //=====================================================================================
            // Animation set is container of animation.
            //=====================================================================================
            struct sAnimationSet
            {
                
            char*            name;        // name of animation set
                DWORD            length;        // length of animation
                sAnimationSet*    next;

                DWORD            num_anims;
                sAnimation
            *        anims;

                sAnimationSet()
                {
                    ZeroMemory(
            thissizeof(*this));
                }

                
            ~sAnimationSet()
                {
                    delete[] name;    name  
            = NULL;
                    delete anims;    anims 
            = NULL;
                    delete next;    next  
            = NULL;
                }
            };

            //=====================================================================================
            // Parse animation data from X file.
            //=====================================================================================
            class cAnimationCollection : public cXParser
            {
            protected:
                DWORD            m_num_anim_sets;
                sAnimationSet
            *    m_anim_sets;

            protected:
                
            virtual bool parse_objects(ID3DXFileData* xfile_data,
                                           ID3DXFileData
            * parent_xfile_data,
                                           DWORD  depth,
                                           
            void** data,
                                           
            bool   force_ref);

            public:
                cAnimationCollection()
                {
                    m_num_anim_sets 
            = 0;
                    m_anim_sets        
            = NULL;
                }

                
            ~cAnimationCollection()
                {
                    free();
                }

                
            void free()
                {
                    m_num_anim_sets 
            = 0;
                    delete m_anim_sets; m_anim_sets 
            = NULL;
                }

                
            bool load(const char* filename)
                {
                    free();        
            // free a prior loaded collection

                    
            return parse(filename, NULL);
                }

                
            void map_frames(D3DXFRAME_EX* root_frame);
                
            void update(const char* anim_set_name, DWORD time, bool is_loop);
            };

            #endif

             

            SkeletalAnim.cpp:

            #include <d3dx9xof.h>
            #include 
            "XTemplate.h"
            #include 
            "SkeletalAnim.h"

            #pragma warning(disable : 
            4996)

            bool cAnimationCollection::parse_objects(ID3DXFileData* xfile_data, 
                                                     ID3DXFileData
            * parent_xfile_data, 
                                                     DWORD depth, 
            void** data, bool force_ref)
            {
                GUID type;
                get_object_guid(xfile_data, 
            &type);

                
            if(type == TID_D3DRMAnimationSet)    
                {
                    
            // create and link in a sAnimationSet object
                    sAnimationSet* anim_set = new sAnimationSet;
                    anim_set
            ->next = m_anim_sets;
                    m_anim_sets 
            = anim_set;

                    m_num_anim_sets
            ++;

                    anim_set
            ->name = get_object_name(xfile_data);
                }
                
            else if(type == TID_D3DRMAnimation && m_anim_sets)
                {
                    
            // add a sAnimation to top-level sAnimationSet
                    sAnimation* anim = new sAnimation;
                    anim
            ->next = m_anim_sets->anims;
                    m_anim_sets
            ->anims = anim;

                    m_anim_sets
            ->num_anims++;
                }
                
            else if(type == TID_D3DRMFrame && force_ref == true && m_anim_sets && m_anim_sets->anims)
                {
                    
            // a frame reference inside animation template

                    
            if(parent_xfile_data)
                    {
                        GUID parent_type;
                        get_object_guid(parent_xfile_data, 
            &parent_type);

                        
            // make sure parent object is an animation template
                        if(parent_type == TID_D3DRMAnimation)
                            m_anim_sets
            ->anims->bone_name = get_object_name(xfile_data);
                    }

                    
            return true;    // do not process child of reference frames
                }
                
            else if(type == TID_D3DRMAnimationKey && m_anim_sets && m_anim_sets->anims)
                {
                    sAnimation
            * anim = m_anim_sets->anims;

                    SIZE_T size;
                    DWORD
            * data_ptr;
                    xfile_data
            ->Lock(&size, (LPCVOID*&data_ptr);

                    DWORD type       
            = *data_ptr++;
                    DWORD num_keys 
            = *data_ptr++;

                    
            // branch based on key type
                    switch(type)
                    {
                    
            case 0:    // rotation
                        delete[] anim->rotation_keys;
                        anim
            ->num_rotation_keys = num_keys;
                        anim
            ->rotation_keys        = new sAnimQuatKey[num_keys];

                        
            for(DWORD i = 0; i < num_keys; i++)
                        {
                            anim
            ->rotation_keys[i].time = *data_ptr++;

                            
            if(anim->rotation_keys[i].time > m_anim_sets->length)
                                m_anim_sets
            ->length = anim->rotation_keys[i].time;

                            data_ptr
            ++;        // skip number of keys to follow (should be 4)    

                            
            // quaternion data stored with w,x,y,z order in xfile, so can not cast directly to assigned!
                            
                            
            float* float_ptr = (float*) data_ptr;

                            anim
            ->rotation_keys[i].quat.w = *float_ptr++;
                            anim
            ->rotation_keys[i].quat.x = *float_ptr++;
                            anim
            ->rotation_keys[i].quat.y = *float_ptr++;
                            anim
            ->rotation_keys[i].quat.z = *float_ptr++;

                            data_ptr 
            += 4;
                        }

                        
            break;

                    
            case 1:    // scaling
                        delete[] anim->scale_keys;
                        anim
            ->num_scale_keys = num_keys;
                        anim
            ->scale_keys = new sAnimVectorKey[num_keys];

                        
            for(DWORD i = 0; i < num_keys; i++)
                        {
                            anim
            ->scale_keys[i].time = *data_ptr++;

                            
            if(anim->scale_keys[i].time > m_anim_sets->length)
                                m_anim_sets
            ->length = anim->scale_keys[i].time;

                            data_ptr
            ++;        // skip number of keys to follow (should be 3)            
                            anim->scale_keys[i].vec = *((D3DXVECTOR3*) data_ptr);
                            data_ptr 
            += 3;
                        }

                        
            break;

                    
            case 2:    // translation
                        delete[] anim->translation_keys;
                        anim
            ->num_translation_keys = num_keys;
                        anim
            ->translation_keys = new sAnimVectorKey[num_keys];

                        
            for(DWORD i = 0; i < num_keys; i++)
                        {
                            anim
            ->translation_keys[i].time = *data_ptr++;

                            
            if(anim->translation_keys[i].time > m_anim_sets->length)
                                m_anim_sets
            ->length = anim->translation_keys[i].time;

                            data_ptr
            ++;        // skip number of keys to follow (should be 3)            
                            anim->translation_keys[i].vec = *((D3DXVECTOR3*) data_ptr);
                            data_ptr 
            += 3;
                        }

                        
            break;

                    
            case 4:    // transformation matrix
                        delete[] anim->matrix_keys;
                        anim
            ->num_matrix_keys = num_keys;
                        anim
            ->matrix_keys = new sAnimMatrixKey[num_keys];

                        
            for(DWORD i = 0; i < num_keys; i++)
                        {
                            anim
            ->matrix_keys[i].time = *data_ptr++;

                            
            if(anim->matrix_keys[i].time > m_anim_sets->length)
                                m_anim_sets
            ->length = anim->matrix_keys[i].time;

                            data_ptr
            ++;    // skip number of keys to follow (should be 16)                
                            anim->matrix_keys[i].matrix = *((D3DXMATRIX*) data_ptr);
                            data_ptr 
            += 16;
                        }

                        
            break;
                    }

                    xfile_data
            ->Unlock();
                }

                
            return parse_child_objects(xfile_data, depth, data, force_ref);
            }

            ////////////////////////////////////////////////////////////////////////////////////////////////

            void cAnimationCollection::map_frames(D3DXFRAME_EX* root_frame)
            {
                
            for(sAnimationSet* anim_set = m_anim_sets; anim_set != NULL; anim_set = anim_set->next)
                {
                    
            for(sAnimation* anim = anim_set->anims; anim != NULL; anim = anim->next)
                        anim
            ->bone = root_frame->find(anim->bone_name);
                }
            }

            ////////////////////////////////////////////////////////////////////////////////////////////////

            void cAnimationCollection::update(const char* anim_set_name, DWORD time, bool is_loop)
            {
                sAnimationSet
            * anim_set = m_anim_sets;

                
            // look for matching animation set if name used
                if(anim_set_name)
                {
                    
            // find matching animation set name
                    while(anim_set != NULL)
                    {
                        
            // break when match found
                        if(! stricmp(anim_set->name, anim_set_name))
                            
            break;

                        anim_set 
            = anim_set->next;
                    }
                }

                
            if(anim_set == NULL)    // no animation set found
                    return;

                
            // bounds time to animation length
                if(time > anim_set->length)
                    time 
            = is_loop ? (time % (anim_set->length + 1)) : anim_set->length;

                
            for(sAnimation* anim = anim_set->anims; anim != NULL; anim = anim->next)
                {
                    
            if(anim->bone == NULL)    // only process if it is attached to a bone
                        continue;
                
                    
            // reset transformation
                    D3DXMatrixIdentity(&anim->bone->TransformationMatrix);

                    
            // apply various matrices to transformation

                    
            // scaling
                    if(anim->num_scale_keys && anim->scale_keys)
                    {
                        DWORD key1 
            = 0, key2 = 0;

                        
            // loop for matching scale key
                        for(DWORD i = 0; i < anim->num_scale_keys; i++)
                        {
                            
            if(time >= anim->scale_keys[i].time)
                                key1 
            = i;
                        }

                        key2 
            = (key1 >= (anim->num_scale_keys - 1)) ? key1 : key1+1;

                        DWORD time_diff 
            = anim->scale_keys[key2].time - anim->scale_keys[key1].time;

                        
            if(time_diff == 0)
                            time_diff 
            = 1;

                        
            float scalar = (float)(time - anim->scale_keys[key1].time) / time_diff;

                        
            // calculate interpolated scale values
                        D3DXVECTOR3 scale_vec = anim->scale_keys[key2].vec - anim->scale_keys[key1].vec;
                        scale_vec 
            *= scalar;
                        scale_vec 
            += anim->scale_keys[key1].vec;

                        
            // create scale matrix and combine with transformation
                        D3DXMATRIX scale_matrix;
                        D3DXMatrixScaling(
            &scale_matrix, scale_vec.x, scale_vec.y, scale_vec.z);
                        anim
            ->bone->TransformationMatrix *= scale_matrix;
                    }

                    
            // rotation
                    if(anim->num_rotation_keys && anim->rotation_keys)
                    {
                        DWORD key1 
            = 0, key2 = 0;

                        
            // loop for matching rotation key
                        for(DWORD i = 0; i < anim->num_rotation_keys; i++)
                        {
                            
            if(time >= anim->rotation_keys[i].time)
                                key1 
            = i;
                        }

                        key2 
            = (key1 >= (anim->num_rotation_keys - 1)) ? key1 : key1+1;

                        DWORD time_diff 
            = anim->rotation_keys[key2].time - anim->rotation_keys[key1].time;

                        
            if(time_diff == 0)
                            time_diff 
            = 1;

                        
            float scalar = (float)(time - anim->rotation_keys[key1].time) / time_diff;

                        
            // slerp rotation values
                        D3DXQUATERNION rot_quat;
                        D3DXQuaternionSlerp(
            &rot_quat, &anim->rotation_keys[key1].quat, &anim->rotation_keys[key2].quat, scalar);

                        
            // create rotation matrix and combine with transformation
                        D3DXMATRIX rot_matrix;
                        D3DXMatrixRotationQuaternion(
            &rot_matrix, &rot_quat);
                        anim
            ->bone->TransformationMatrix *= rot_matrix;
                    }

                    
            // translation
                    if(anim->num_translation_keys && anim->translation_keys)
                    {
                        DWORD key1 
            = 0, key2 = 0;

                        
            // loop for matching translation key
                        for(DWORD i = 0; i < anim->num_translation_keys; i++)
                        {
                            
            if(time >= anim->translation_keys[i].time)
                                key1 
            = i;
                        }

                        key2 
            = (key1 >= (anim->num_matrix_keys - 1)) ? key1 : key1+1;

                        DWORD time_diff 
            = anim->translation_keys[key2].time - anim->translation_keys[key1].time;

                        
            if(time_diff == 0)
                            time_diff 
            = 1;

                        
            float scalar = (float)(time - anim->translation_keys[key1].time) / time_diff;

                        
            // calculate interpolated vector values
                        D3DXVECTOR3 pos_vec = anim->translation_keys[key2].vec - anim->translation_keys[key1].vec;
                        pos_vec 
            *= scalar;
                        pos_vec 
            += anim->translation_keys[key1].vec;

                        
            // create translation matrix and combine with transformation
                        D3DXMATRIX translation_matrix;
                        D3DXMatrixTranslation(
            &translation_matrix, pos_vec.x, pos_vec.y, pos_vec.z);
                        anim
            ->bone->TransformationMatrix *= translation_matrix;
                    }

                    
            // matrix
                    if(anim->num_matrix_keys && anim->matrix_keys)
                    {
                        DWORD key1 
            = 0, key2 = 0;

                        
            // loop for matching matrix key
                        for(DWORD i = 0; i < anim->num_matrix_keys; i++)
                        {
                            
            if(time >= anim->matrix_keys[i].time)
                                key1 
            = i;
                        }

                        key2 
            = (key1 >= (anim->num_matrix_keys - 1)) ? key1 : key1+1;

                        DWORD time_diff 
            = anim->matrix_keys[key2].time - anim->matrix_keys[key1].time;

                        
            if(time_diff == 0)
                            time_diff 
            = 1;

                        
            float scalar = (float)(time - anim->matrix_keys[key1].time) / time_diff;

                        
            // calculate interpolated matrix
                        D3DXMATRIX diff_matrix = anim->matrix_keys[key2].matrix - anim->matrix_keys[key1].matrix;
                        diff_matrix 
            *= scalar;
                        diff_matrix 
            += anim->matrix_keys[key1].matrix;

                        
            // combine with transformation
                        anim->bone->TransformationMatrix *= diff_matrix;
                    }
                }
            }

             

            WinMain.cpp:

            #include <windows.h>
            #include 
            <d3d9.h>
            #include 
            <d3dx9.h>
            #include 
            "Direct3D.h"
            #include 
            "SkeletalAnim.h"

            IDirect3D9
            *                g_d3d;
            IDirect3DDevice9
            *        g_device;
            D3DXMESHCONTAINER_EX
            *    g_mesh_container;
            D3DXFRAME_EX
            *            g_frame;

            cAnimationCollection    g_anim_collection;

            float g_mesh_radius = 0.0f;    // bounding radius of mesh

            const char CLASS_NAME[] = "SkeletalAnimClass";
            const char CAPTION[]    = "Skeletal Animation Demo";

            ////////////////////////////////////////////////////////////////////////////////////////////////

            LRESULT FAR PASCAL window_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

            bool do_init(HWND hwnd);
            void do_shutdown();
            void do_frame();


            //////////////////////////////////////////////////////////////////////////////////////////////

            int PASCAL WinMain(HINSTANCE inst, HINSTANCE, LPSTR, int cmd_show)
            {      
                CoInitialize(NULL);    
            // Initialize the COM system

                
            // Create the window class here and register it

                WNDCLASSEX win_class;  

                win_class.cbSize        
            = sizeof(win_class);
                win_class.style         
            = CS_CLASSDC;
                win_class.lpfnWndProc   
            = window_proc;
                win_class.cbClsExtra    
            = 0;
                win_class.cbWndExtra    
            = 0;
                win_class.hInstance     
            = inst;
                win_class.hIcon         
            = LoadIcon(NULL, IDI_APPLICATION);
                win_class.hCursor       
            = LoadCursor(NULL, IDC_ARROW);
                win_class.hbrBackground 
            = NULL;
                win_class.lpszMenuName  
            = NULL;
                win_class.lpszClassName 
            = CLASS_NAME;
                win_class.hIconSm       
            = LoadIcon(NULL, IDI_APPLICATION);

                
            if(!RegisterClassEx(&win_class))
                    
            return -1;

                
            // Create the main window
                HWND hwnd = CreateWindow(CLASS_NAME, CAPTION, WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
                                         
            00640480, NULL, NULL, inst, NULL);

                
            if(hwnd == NULL)
                    
            return -1;

                ShowWindow(hwnd, cmd_show);
                UpdateWindow(hwnd);

                
            // Call init function and enter message pump
                if(do_init(hwnd)) 
                {
                    MSG msg;    
                    ZeroMemory(
            &msg, sizeof(MSG));

                    
            // Start message pump, waiting for user to exit
                    while(msg.message != WM_QUIT) 
                    {
                        
            if(PeekMessage(&msg, NULL, 00, PM_REMOVE)) 
                        {
                            TranslateMessage(
            &msg);
                            DispatchMessage(
            &msg);
                        }
                        
                        do_frame();    
            // Render a single frame
                    }
                }
              
                do_shutdown();
                UnregisterClass(CLASS_NAME, inst);
                CoUninitialize();

                
            return 0;
            }

            LRESULT FAR PASCAL window_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
            {
                
            // Only handle window destruction messages
                switch(msg) 
                {
                
            case WM_DESTROY:
                    PostQuitMessage(
            0);
                    
            break;

                
            case WM_KEYDOWN:
                    
            if(wParam == VK_ESCAPE)
                        DestroyWindow(hwnd);

                    
            break;
                }

                
            return DefWindowProc(hwnd, msg, wParam, lParam);
            }

            bool do_init(HWND hwnd)
            {
                init_d3d(
            &g_d3d, &g_device, hwnd, falsefalse);

                
            // load skeletal mesh
                if(FAILED(load_mesh(&g_mesh_container, &g_frame, g_device, "..\\Data\\tiny.x""..\\Data\\"0, D3DXMESH_SYSTEMMEM)))
                    
            return false;

                
            // load animation data
                if(! g_anim_collection.load("..\\Data\\tiny.x"))
                    
            return false;

                
            // map the animation to the frame hierarchy
                g_anim_collection.map_frames(g_frame);

                
            // get the bounding radius of the object

                g_mesh_radius 
            = 0.0f;

                D3DXMESHCONTAINER_EX
            * mesh_container = g_mesh_container;

                
            while(mesh_container)
                {
                    ID3DXMesh
            * mesh = mesh_container->MeshData.pMesh;

                    
            if(mesh)
                    {
                        
            // lock the vertex buffer, get its radius, and unlock buffer.

                        D3DXVECTOR3
            * vertices;
                        D3DXVECTOR3  center;
                        
            float         radius;

                        mesh
            ->LockVertexBuffer(D3DLOCK_READONLY, (void**)&vertices);

                        D3DXComputeBoundingSphere(vertices, mesh
            ->GetNumVertices(), D3DXGetFVFVertexSize(mesh->GetFVF()),
                                                  
            &center, &radius);
                        
                        mesh
            ->UnlockVertexBuffer();

                        
            // update radius
                        if(radius > g_mesh_radius)
                            g_mesh_radius 
            = radius;
                    }

                    
            // goto next mesh
                    mesh_container = (D3DXMESHCONTAINER_EX*) mesh_container->pNextMeshContainer;
                }

                
            return true;
            }

            void do_shutdown()
            {
                
            // free mesh data
                delete g_mesh_container;    g_mesh_container = NULL;
                delete g_frame;                g_frame 
            = NULL;
                
                
            // release D3D objects
                release_com(g_device);
                release_com(g_d3d);
            }

            void do_frame()
            {
                
            static DWORD start_time = timeGetTime();
                DWORD curr_time 
            = timeGetTime();

                
            // update the animation (convert to 30 fps)
                g_anim_collection.update(NULL, (curr_time - start_time) * 3true);

                
            // rebuild the frame hierarchy transformations
                if(g_frame)
                    g_frame
            ->update_hierarchy(NULL);

                
            // rebuild the mesh
                update_skin_mesh(g_mesh_container);

                
            // calculate a view transformation matrix using the mesh's bounding radius to position the viewer

                
            float distance = g_mesh_radius * 3.0f;
                
            float angle       = timeGetTime() / 2000.0f;        

                D3DXMATRIX  mat_view;
                D3DXVECTOR3 eye(cos(angle) 
            * distance, g_mesh_radius, sin(angle) * distance);
                D3DXVECTOR3 at(
            0.0f0.0f0.0f);
                D3DXVECTOR3 up(
            0.0f1.0f0.0f);

                D3DXMatrixLookAtLH(
            &mat_view, &eye, &at, &up);
                g_device
            ->SetTransform(D3DTS_VIEW, &mat_view);    

                D3DXMATRIX mat_world;
                D3DXMatrixIdentity(
            &mat_world);
                g_device
            ->SetTransform(D3DTS_WORLD, &mat_world);

                
            // clear the device and start drawing the scene

                g_device
            ->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(000255), 1.0f0);

                g_device
            ->BeginScene();    
                draw_mesh(g_mesh_container);
                g_device
            ->EndScene();

                g_device
            ->Present(NULL, NULL, NULL, NULL);
            }


            download source file



            posted on 2008-04-25 13:43 lovedday 閱讀(608) 評(píng)論(0)  編輯 收藏 引用


            只有注冊用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            公告

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關(guān)鏈接

            搜索

            最新評(píng)論

            久久青青草原亚洲av无码app| 99精品国产免费久久久久久下载| 久久九九亚洲精品| 国产精品综合久久第一页| 亚洲精品乱码久久久久久蜜桃| 日韩人妻无码一区二区三区久久99 | 久久久久免费视频| 久久AV高潮AV无码AV| 久久96国产精品久久久| 亚洲午夜无码AV毛片久久| 狠狠色丁香久久婷婷综| 天天综合久久一二三区| 国产V亚洲V天堂无码久久久| 无码人妻久久一区二区三区蜜桃| 久久久无码精品亚洲日韩蜜臀浪潮| 国产精品VIDEOSSEX久久发布| 久久久久久久女国产乱让韩| 91久久国产视频| 乱亲女H秽乱长久久久| 激情五月综合综合久久69| 亚洲国产精品无码久久98| 久久九九免费高清视频| avtt天堂网久久精品| 狠狠色丁香婷婷久久综合五月| 久久伊人精品青青草原高清| 久久久www免费人成精品| 久久国产免费直播| 久久久久久a亚洲欧洲aⅴ| 久久精品国产亚洲av麻豆蜜芽| 精品久久久久久久久久久久久久久 | 久久久久久久人妻无码中文字幕爆 | 久久久久久久波多野结衣高潮| 九九久久精品无码专区| 精品久久久久久无码中文字幕一区| 一级A毛片免费观看久久精品| 成人精品一区二区久久久| 久久综合给合久久狠狠狠97色 | 久久综合综合久久97色| 久久夜色精品国产网站| 久久人妻少妇嫩草AV蜜桃| 久久久综合香蕉尹人综合网|