青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天行健 君子當自強而不息

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 閱讀(621) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


公告

導航

統計

常用鏈接

隨筆分類(178)

3D游戲編程相關鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美性大战久久久久久久| 中文欧美在线视频| 亚洲图片你懂的| 亚洲九九九在线观看| 久久国产成人| 午夜精品一区二区三区四区| 欧美成人精品激情在线观看| 久久精品国产亚洲精品| 国产精品成人一区二区| 亚洲欧洲精品一区二区三区不卡 | 亚洲六月丁香色婷婷综合久久| 一区免费观看| 午夜精品一区二区在线观看| 亚洲一区高清| 欧美调教视频| av成人免费在线| 亚洲最新色图| 欧美日韩精品二区| 亚洲剧情一区二区| aa亚洲婷婷| 欧美日韩日日骚| 夜夜嗨av一区二区三区四季av | 欧美成人精品在线视频| 老司机免费视频一区二区| 国产日韩欧美在线一区| 午夜精品视频在线观看| 欧美在线网站| 韩日成人av| 欧美在线日韩精品| 香蕉久久夜色精品国产| 国外成人性视频| 欧美呦呦网站| 噜噜爱69成人精品| 亚洲第一网站| 欧美成人午夜激情在线| 亚洲欧洲日本专区| 99伊人成综合| 国产精品日产欧美久久久久| 亚洲主播在线观看| 久久九九热免费视频| 韩日成人av| 欧美成人综合| 亚洲少妇一区| 久久综合精品国产一区二区三区| 在线播放视频一区| 欧美日韩高清在线播放| 亚洲午夜av| 欧美综合77777色婷婷| 伊人久久成人| 欧美日韩国产色视频| 亚洲欧美日韩精品综合在线观看| 久久躁日日躁aaaaxxxx| 亚洲乱码国产乱码精品精可以看| 国产精品成人午夜| 久久久精品一区| 亚洲精品一区二区网址 | 99精品视频免费全部在线| 欧美日韩午夜在线| 午夜亚洲视频| 亚洲激情电影在线| 校园春色国产精品| 亚洲人成在线播放网站岛国| 国产精品久久久久久久久| 久久久精品午夜少妇| 亚洲靠逼com| 美女脱光内衣内裤视频久久网站| 一本色道婷婷久久欧美| 国产视频精品xxxx| 欧美另类一区二区三区| 久久精品91久久香蕉加勒比| 亚洲另类自拍| 欧美黄色日本| 久久久久久999| 亚洲一区二区三区视频播放| 亚洲福利国产精品| 国产精品一区二区黑丝| 欧美精品一区二区三区高清aⅴ| 性欧美1819性猛交| 99精品福利视频| 亚洲国产清纯| 蜜桃精品一区二区三区| 欧美一级视频免费在线观看| 99av国产精品欲麻豆| 狠狠色狠狠色综合日日91app| 国产精品国产三级国产| 欧美黄色片免费观看| 久久青草欧美一区二区三区| 亚洲欧美综合国产精品一区| 一本不卡影院| 日韩视频一区二区| 亚洲欧洲精品一区| 欧美激情女人20p| 美女精品网站| 久久夜色精品| 久久精品亚洲精品| 久久国产乱子精品免费女| 亚洲欧美日韩中文视频| 在线亚洲精品| 一区二区三区鲁丝不卡| 亚洲毛片av| 一本久久a久久精品亚洲| 亚洲精品一区二区三区樱花| 亚洲福利在线观看| 亚洲电影有码| 亚洲国产精品福利| 亚洲欧洲精品成人久久奇米网| 亚洲福利视频免费观看| 尤物精品在线| 亚洲国产三级在线| 亚洲精品乱码久久久久久| 亚洲第一主播视频| 亚洲精品少妇网址| 99精品视频一区| 亚洲一区二区日本| 亚洲欧美激情视频| 欧美在线视频观看免费网站| 久久成人av少妇免费| 久久人人爽爽爽人久久久| 鲁大师成人一区二区三区| 欧美国产精品久久| 亚洲人永久免费| 亚洲一区二区成人在线观看| 亚洲欧美久久久| 久久久久久久久久久久久久一区| 久久一区二区三区超碰国产精品| 免费成人av资源网| 欧美日韩福利| 国产日韩精品一区二区浪潮av| 国产综合久久| 亚洲精品偷拍| 亚洲综合成人在线| 久久国产欧美日韩精品| 欧美aⅴ一区二区三区视频| 亚洲精品美女在线观看| 一区二区三区四区五区视频| 欧美一级二区| 欧美精品粉嫩高潮一区二区 | 久久精品日产第一区二区三区| 美腿丝袜亚洲色图| 9久re热视频在线精品| 欧美一区二区三区免费视频| 免费一级欧美片在线播放| 欧美亚洲第一页| 韩国欧美一区| 亚洲午夜在线观看| 欧美aa国产视频| 亚洲午夜电影网| 久久综合九九| 国产精品一区二区久激情瑜伽| 在线播放不卡| 亚洲欧美日韩国产一区二区| 欧美成人午夜剧场免费观看| 亚洲视频网站在线观看| 久久综合给合| 国产欧美日韩专区发布| 99亚洲一区二区| 美女亚洲精品| 亚洲女ⅴideoshd黑人| 欧美成人乱码一区二区三区| 国产手机视频精品| 亚洲午夜一区二区三区| 欧美激情一区二区| 欧美一级成年大片在线观看| 欧美日本三区| 亚洲三级免费电影| 久久天天躁夜夜躁狠狠躁2022| 这里只有精品视频| 欧美日韩国产123| 亚洲欧洲精品一区二区| 久久先锋影音| 亚洲影音先锋| 国产精品www| 亚洲视频电影图片偷拍一区| 欧美成人激情视频免费观看| 欧美在线91| 国产亚洲欧洲| 久久av红桃一区二区小说| 99综合在线| 欧美日韩国产三级| 亚洲精品中文字幕在线| 欧美不卡视频一区发布| 久久久精品五月天| 国产一区三区三区| 久久gogo国模裸体人体| 亚洲一区二区三区三| 国产精品国产三级国产专播品爱网| 日韩亚洲综合在线| 亚洲人体偷拍| 欧美日韩国产三级| 国产精品99久久久久久久久久久久| 亚洲国产精品999| 欧美国产精品人人做人人爱| 最新成人在线| 亚洲精品乱码久久久久久蜜桃91 | 欧美日韩精品伦理作品在线免费观看| 最新中文字幕亚洲| 亚洲人成在线影院| 欧美午夜宅男影院在线观看| 亚洲一区三区电影在线观看| 亚洲视频电影图片偷拍一区|