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

天行健 君子當自強而不息

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 閱讀(618) 評論(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>
            美日韩精品视频| 99亚洲视频| 亚洲视频一区二区| 一区在线播放| 亚洲欧美日韩国产综合在线| 亚洲精品国产精品久久清纯直播| 欧美一区二区精美| 亚洲男女自偷自拍| 欧美日韩亚洲高清一区二区| 欧美激情一区二区三区全黄| 国产主播精品在线| 亚洲欧美日韩另类| 亚洲欧美日本国产专区一区| 欧美精品尤物在线| 亚洲高清av在线| 激情亚洲成人| 久久精品国产99国产精品澳门| 欧美一区二区三区免费视| 欧美日韩在线第一页| 亚洲精品国产精品国自产观看| 亚洲国产成人精品视频 | 久久国产精品一区二区三区| 欧美日韩国产精品一区| 亚洲国内高清视频| 亚洲精品一二| 欧美理论电影在线播放| 最新国产成人在线观看| 最新中文字幕一区二区三区| 麻豆成人av| 欧美激情精品久久久久久| 亚洲电影毛片| 欧美成在线观看| 亚洲精品国产精品国产自| 99国产精品久久久| 欧美三级乱码| 亚洲欧美视频| 美女爽到呻吟久久久久| 亚洲国产成人不卡| 欧美日韩99| 在线视频你懂得一区| 欧美一区二区三区日韩| 国产一区深夜福利| 久久最新视频| 日韩亚洲欧美成人| 欧美一级一区| 国产综合欧美| 欧美电影打屁股sp| 亚洲小说欧美另类社区| 久久精品国产99精品国产亚洲性色 | 亚洲制服av| 国产欧美va欧美va香蕉在| 久久精品国产99| 亚洲国产成人高清精品| 亚洲午夜日本在线观看| 国产欧美一区二区精品仙草咪| 欧美一级在线播放| 亚洲成色777777在线观看影院| 日韩午夜三级在线| 国产欧美日韩一区二区三区在线| 久久婷婷丁香| 亚洲网址在线| 欧美国产日韩a欧美在线观看| 99精品国产在热久久下载| 国产精品素人视频| 欧美成人久久| 午夜精品免费视频| 亚洲国产一区二区在线| 性xx色xx综合久久久xx| 亚洲黄色小视频| 国产精品夜夜夜一区二区三区尤| 久久免费的精品国产v∧| 一区二区三区.www| 免费亚洲一区| 欧美一区二区三区日韩视频| 亚洲国语精品自产拍在线观看| 国产精品久久久久久久久久久久久久 | 亚洲一区黄色| 欧美国产一区二区| 久久狠狠久久综合桃花| 日韩亚洲欧美一区二区三区| 国产亚洲一区二区三区| 欧美日韩国产综合视频在线观看中文| 久久国产精品色婷婷| 一区二区三区高清视频在线观看 | 久久在线免费观看| 亚洲在线观看视频| 亚洲精品专区| 亚洲国产精品成人| 韩国福利一区| 国产视频久久久久| 欧美体内谢she精2性欧美| 女生裸体视频一区二区三区| 欧美在线黄色| 性欧美长视频| 亚洲综合三区| 亚洲综合国产| 亚洲一区二区高清| 一区二区三区国产在线观看| 亚洲国内自拍| 亚洲国产成人久久综合| 欧美成人tv| 欧美va亚洲va香蕉在线| 久久综合九色综合欧美就去吻| 亚洲欧美一区二区视频| 亚洲尤物在线| 亚洲男人的天堂在线观看| 一区二区成人精品| 正在播放日韩| 亚洲一区二区免费| 亚洲一区二区三区涩| 在线视频一区观看| 亚洲一区二区视频在线观看| 夜夜嗨av一区二区三区中文字幕| 最新日韩在线视频| 亚洲精品少妇| 在线亚洲国产精品网站| 亚洲一区国产精品| 亚洲欧美日韩国产综合在线| 亚洲主播在线| 欧美伊人久久久久久午夜久久久久 | 日韩天天综合| 亚洲视频电影图片偷拍一区| 在线综合亚洲| 香蕉免费一区二区三区在线观看| 午夜精品国产精品大乳美女| 欧美一区二区三区电影在线观看| 欧美一级网站| 男女精品网站| 亚洲精品免费一二三区| 一本久久a久久免费精品不卡| 亚洲一区二区成人| 久久电影一区| 欧美高清一区| 国产精品夜色7777狼人| 国产在线精品自拍| 亚洲三级电影在线观看| 亚洲一区二区三区中文字幕在线 | 久久久噜噜噜| 欧美日本免费一区二区三区| 国产精品日韩精品欧美在线 | 亚洲黄网站在线观看| 一本色道久久综合狠狠躁的推荐| 中文精品视频| 久久精品一区二区三区四区| 欧美高清免费| 一区二区三区日韩精品| 久久精品中文字幕一区| 欧美二区在线| 国产欧美一区二区白浆黑人| 亚洲国产mv| 亚洲欧美日韩在线综合| 久久免费视频在线| 亚洲人久久久| 久久精品国产免费| 欧美三级小说| 亚洲国产精品www| 欧美在线看片| 最近看过的日韩成人| 性久久久久久久| 欧美高清视频www夜色资源网| 国产欧美另类| 99国产精品久久| 久久午夜av| 在线亚洲一区二区| 麻豆精品精华液| 国产女主播一区二区| 亚洲免费久久| 欧美成人免费va影院高清| 亚洲综合精品四区| 欧美日韩亚洲系列| 亚洲精品少妇30p| 免费国产一区二区| 亚洲欧美日韩国产中文| 欧美日韩精品在线观看| 亚洲国产精品第一区二区| 久久精品青青大伊人av| 99在线视频精品| 欧美日本一区| 亚洲精品乱码久久久久久蜜桃麻豆 | 欧美成人免费全部| 好吊一区二区三区| 欧美中日韩免费视频| 亚洲视频一起| 欧美四级在线| 亚洲视频成人| 99视频在线观看一区三区| 欧美福利视频网站| 亚洲国语精品自产拍在线观看| 久久综合色天天久久综合图片| 亚洲综合电影一区二区三区| 国产精品成人在线观看| 亚洲小视频在线观看| 亚洲区一区二区三区| 欧美精品成人91久久久久久久| 亚洲成人在线| 欧美成人午夜激情视频| 麻豆91精品91久久久的内涵| 亚洲国产岛国毛片在线| 亚洲电影一级黄| 欧美成人一品|