<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      [OpenGL ES 04]3D變換實踐篇:平移,旋轉,縮放

      [OpenGL ES 04]3D變換實踐篇:平移,旋轉,縮放

      羅朝輝 (http://www.rzrgm.cn/kesalin/)

      本文遵循“署名-非商業用途-保持一致”創作公用協議

      前言

      前文《[OpenGL ES 03]3D變換:模型,視圖,投影與Viewport》中已經詳細介紹了3D變換相關的數學知識,也講了基本的模型變換:平移,旋轉與縮放,如果你還沒有閱讀前文或對這些知識還不夠明白,務必先弄懂前文再繼續。假如你已經準備好繼續了,那么在接下來的內容中,我將介紹如何在 OpenGL ES 中運用這些知識,來渲染一個四棱錐,并對它進行平移,旋轉與縮放操作,此外本文也演示了如何將 OpenGL View 與 UIView 結合在一起(注意:在實際運用中,不推薦這么做,混合使用 OpenGL View 和 UIView 對效率影響較大)。

      本文代碼可以從這里獲得:點此下載(Tutorial03),最終效果圖如下:

       

      一,創建工程

      1,新建工程

      從今天起,我們不再從頭開始創建 window 和 view 了,新建一個名為 Tutorial03 的 Single view application 工程:

      2,從前面的效果圖中可以看到,在這個教程中,我們需要兩個 view:OpenGL view 和 UIView。因此打開 MainStoryboard.storyboard,向其中加入兩個 view,其中上面那一個用于 OpenGL view,下面那一個用于 control view。調整兩個view 的大小與位置,將下面的 view 的背景設置為淺藍色,以方便區分。

      3,拷貝 Tutorial02 教程中的 GLESUtils.h, GLESUtils.m OpenGLView.h, OpenGLView.m 以及 FragmentShader.glsl, VertexShader.glsl 到 Tutorial03 中,并加入到工程中進來,再添加 OpenGLES 以及 QuartzCore framework。

      4,在 ViewController.h 中,為這兩個view 添加 IBOutlet:

      #import "OpenGLView.h"
      
      @interface ViewController : UIViewController
      
      @property (nonatomic, strong) IBOutlet UIView * controlView;
      @property (nonatomic, strong) IBOutlet OpenGLView * openGLView;

      在 ViewController.m 中 @implementation ViewController 下面的添加

      @synthesize controlView, openGLView;

      并在 viewDidUnload 中進行清理:

      - (void)viewDidUnload
      {
          [super viewDidUnload];
          
          [self.openGLView cleanup];
          self.openGLView = nil;
          
          self.controlView = nil;
      }

      5,回到 MainStoryboard.storyboard,將上面那個 view 的類型設置為 OpenGLView,并關聯相關的 IBOutlet:

       

      二,描繪四棱錐

      1,在 Tutorial02 中只描繪了一個三角形,這回我們來描繪一個真正的 3D 物體:四棱錐。在 OpenGLView.m 中 render() 上面添加如下函數:

      - (void)drawTriCone
      {
          GLfloat vertices[] = {
              0.5f, 0.5f, 0.0f, 
              0.5f, -0.5f, 0.0f,
              -0.5f, -0.5f, 0.0f,
              -0.5f, 0.5f, 0.0f, 
              0.0f, 0.0f, -0.707f,
          };
          
          GLubyte indices[] = {
              0, 1, 1, 2, 2, 3, 3, 0,
              4, 0, 4, 1, 4, 2, 4, 3
          };
          
          glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, 0, vertices );
          glEnableVertexAttribArray(_positionSlot);
          
          // Draw lines
          //
          glDrawElements(GL_LINES, sizeof(indices)/sizeof(GLubyte), GL_UNSIGNED_BYTE, indices);
      }

      這次我們使用頂點索引數組結合 glDrawElements 來渲染,而在 Tutorial02 中,使用的是 glDrawArrays。使用頂點索引數組有什么好處呢?很明顯,我們可以減少存儲重復頂點的內存消耗。比如在本例的索引表中,我們重復利用了頂點 0,1,2,3,4,它們對應 vertices 數組中5個頂點(三個浮點數組成一個頂點)。

      glDrawElements 函數的原型為:

      void glDrawElements(    GLenum      mode,
           GLsizei      count,
           GLenum      type,
           const GLvoid *      indices);

      第一個參數 mode 為描繪圖元的模式,其有效值為:GL_POINTS, GL_LINES, GL_LINE_STRIP,  GL_LINE_LOOP,  GL_TRIANGLES,  GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN。這些模式具體含義下面有介紹。

      第二個參數 count 為頂點索引的個數也就是,type 是指頂點索引的數據類型,因為索引始終是正值,索引這里必須是無符號型的非浮點類型,因此只能是 GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT 之一,為了減少內存的消耗,盡量使用最小規格的類型如 GL_UNSIGNED_BYTE。

      第三個參數 indices 是存放頂點索引的數組。(indices 是 index 的復數形式,3D 里面很多單詞的復數都挺特別的。)

      2,使用

      修改 render() 函數如下:

      - (void)render
      {
          glClearColor(0, 1.0, 0, 1.0);
          glClear(GL_COLOR_BUFFER_BIT);
      
          // Setup viewport
          //
          glViewport(0, 0, self.frame.size.width, self.frame.size.height);    
          
          [self drawTriCone];
      
          [_context presentRenderbuffer:GL_RENDERBUFFER];
      }

      編譯運行程序,你就應該就能看到一個四棱錐了。

      也許你會說,怎么看起來不像呢?那是因為你是從四棱錐的正上方朝下俯視它,索引四棱錐的尖頂(就是圖中間交叉的那個點)看起來就是平的了。如果我們給程序加入旋轉功能,那就會看得非常明顯了,在介紹完圖元模式之后,我們將加入旋轉功能。

       

      三,圖元模式介紹:

      對于畫 line 來說有三種模式:

      此外還可以通過函數 glLineWidth(GLfloat width) 來設定線的寬度,要獲得當前設置的線寬度可以使用如下代碼:

      GLfloat lineWidthRange[2];
      glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, lineWidthRange);

      在 Tutorial02 教程中,我們使用模式 GL_TRIANGLES 描繪了一個三角形。對于三角形來說也有三種模式:

      OpenGL ES 還支持描繪點(精靈, sprite)的模式:GL_POINTS,此外還可以通過內建變量 gl_PointSize 來設置點精靈的大小,要獲取當前設置的點精靈的大小可以使用如下代碼:

      GLfloat pointSizeRange[2]; 
      glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, pointSizeRange);

       

      四,平移

      1,添加控件

      為了加入平移控制,我們需要在下面的 view 上面添加滑塊對平移的距離進行調節。為此,打開 MainStoryboard.storyboard,在下面淺藍色背景的 UIView 上添加一個 UILabel 和 UISlider。

      并設置滑塊的最大值 3,最小值 -3 和當前值 0 :

       

      2,加入控件關聯代碼

      在 ViewController.h 中加入滑塊的 IBOutlet 和 IBAction,并將它與 UISlider 關聯起來。

      @property (nonatomic, strong) IBOutlet UISlider * posXSlider;
      
      - (IBAction)xSliderValueChanged:(id)sender;

      在 ViewController.m 中加入:

      @synthesize posXSlider;
      
      - (IBAction)xSliderValueChanged:(id)sender
      {
          UISlider * slider = (UISlider *)sender;
          float currentValue = [slider value];
      
          NSLog(@" >> current x is %f", currentValue);
      }

      這時,如果你拖動滑塊,就能輸出滑塊當前的值。不要忘記在 viewDidUnload 清理該滑塊:

      self.posXSlider = nil;

       

      3,加入平移代碼

      為了讓我們的三棱錐可以在 x 軸上移動,打開 OpenGLView.h,在 @interface 中加入:

      float _posX;

      然后再加入屬性:

      @property (nonatomic, assign) float posX;

      打開 OpenGLView.m,加入:

      @synthesize posX = _posX;

       

      4,修改頂點著色器代碼

      打開 VertexShader.glsl,修改其內容如下:

      uniform mat4 projection;
      uniform mat4 modelView;
      attribute vec4 vPosition; 
       
      void main(void)
      {
          gl_Position = projection * modelView * vPosition;
      }

      在上面的代碼中,我們對輸入頂點進行了自定義的投影和模型視圖變換,還記得在前文中介紹的內容么?尤其是左乘,在這里,頂點先進行模型視圖變換,然后再進行投影變換。

      5,增加實現 Transform 代碼

      回到 OpenGLView.h 中,加入對應的投影矩陣與模型視圖矩陣:

          KSMatrix4 _modelViewMatrix;
          KSMatrix4 _projectionMatrix;

      KSMatrix4 是定義在數學輔助庫 GLESMath 中用 4 * 4 的二維數組表示的矩陣,你可以在這里獲取 GLESMath.hGLESMath.c,并將它們加入工程中。這個數學輔助庫中包含了常見的一些 3D 計算,后面還會提到它。

      在 OpenGLView.m 中,在 setupProgram 的最后加入獲取模型視圖矩陣以及投影矩陣變量的槽位:

          // Get the attribute position slot from program
          //
          _positionSlot = glGetAttribLocation(_programHandle, "vPosition");
          
          // Get the uniform model-view matrix slot from program
          //
          _modelViewSlot = glGetUniformLocation(_programHandle, "modelView");
          
          // Get the uniform projection matrix slot from program
          //
          _projectionSlot = glGetUniformLocation(_programHandle, "projection");

       在OpenGLView 的匿名 category 中加入以下兩個函數聲明:

      - (void)setupProjection;
      
      - (void)updateTransform;

      然后在 @implemetion 中實現它們:

      -(void)setupProjection
      {
          // Generate a perspective matrix with a 60 degree FOV
          //
          float aspect = self.frame.size.width / self.frame.size.height;
          ksMatrixLoadIdentity(&_projectionMatrix);
          ksPerspective(&_projectionMatrix, 60.0, aspect, 1.0f, 20.0f);
          
          // Load projection matrix
          glUniformMatrix4fv(_projectionSlot, 1, GL_FALSE, (GLfloat*)&_projectionMatrix.m[0][0]);
      }

      上面的代碼中,ksMatrixLoadIdentity 是 GLESMath 中的一個數學函數,用來將指定矩陣重置為單位矩陣,而 ksPerspective 與前文中講到的 gluPersoective 作用一樣。在這里,我們設置視錐體的近裁剪面到觀察者的距離為 1, 遠裁剪面到觀察者的距離為 20,視角為 60度,然后裝載投影矩陣。默認的觀察者位置在原點,視線朝向 -Z 方向,因此近裁剪面其實就在 z = -1 這地方,遠裁剪面在 z = -20 這地方,z 值不在(-1, -20) 之間的物體是看不到的。不要忘記在初始化代碼中調用該函數:

      - (id)initWithCoder:(NSCoder *)aDecoder
      {
          self = [super initWithCoder:aDecoder];
          if (self) {
              [self setupLayer];        
              [self setupContext];
              [self setupProgram];
              [self setupProjection];
          }
      
          return self;
      }

      下面的代碼是更新模型視圖矩陣,以響應用戶的控制。

      - (void)updateTransform
      {
          // Generate a model view matrix to rotate/translate/scale
          //
          ksMatrixLoadIdentity(&_modelViewMatrix);
          
          // Translate away from the viewer
          //
          ksTranslate(&_modelViewMatrix, self.posX, 0.0, -5.5);
          
          // Rotate the triangle
          //
          ksRotate(&_modelViewMatrix, 0.0, 1.0, 0.0, 0.0);
          
          // Scale the triangle
          ksScale(&_modelViewMatrix, 1.0, 1.0, 1.0);
          
          // Load the model-view matrix
          glUniformMatrix4fv(_modelViewSlot, 1, GL_FALSE, (GLfloat*)&_modelViewMatrix.m[0][0]);
      }

      上面的代碼中,ksTranslate,ksRotate,ksScale 也是 GLESMath 中的數學函數,作用與 glTranslate,glRotate,glScale 相同,分別用于平移,繞軸旋繞以及縮放。在這里,設置在 x 方向上平移,平移量將由 self.posX 控制,而這個屬性最終是由滑塊控制的,從而達到用戶移動物體的目的;將 z 設置為 -5.5 (介于 (-1, -20) 之間,前面有講);此外還設置繞 x 軸旋繞 0 度,在 x,y,z三個方向上縮放 1 倍,這兩個函數的調用是為下一步的旋轉和縮放控制準備的。最后,裝載模型視圖矩陣。

      由于需要在 posX 的值變化時,及時更新模型視圖矩陣,并重新描繪,以便能及時看到效果,我們得自己實現屬性 posX 的 setter 和 getter 方法:

      - (void)setPosX:(float)x
      {
          _posX = x;
          
          [self updateTransform];
          [self render];
      }
      
      - (float)posX
      {
          return _posX;
      }

      6,至此,下層的控制代碼就緒了,我們來實現上層 UI 的響應代碼,修改 ViewController.m 中的 xSliderValueChanged 方法如下:

      - (IBAction)xSliderValueChanged:(id)sender
      {
          UISlider * slider = (UISlider *)sender;
          float currentValue = [slider value];
          
          openGLView.posX = currentValue;
      
          NSLog(@" >> current x is %f", currentValue);
      }

      7,編譯運行,滑動滑塊你就能夠控制四棱錐在 x 方向上來回移動了(還記得前面限制了 x 的位置只能在 (-3, 3) 之間么,這是為了不讓四棱錐跑到屏幕外邊去)。聰明的你,應該很容易實現如何控制在 y 和 z 方向的移動了。在實現的過程中要注意,y 滑塊的取值范圍也為(-3, 3),默認值為0,而 z 滑塊的取值范圍為(-10, -1),默認值居中為-5.5。這樣的設置可以確保物體不會完全跑出視錐體所圈定的范圍,因為視錐體之外的物體是不可見的。比如下圖中四棱錐的尖頂部分就跑到視錐體的近裁剪面外面去了,所以尖頂就被裁剪了。

      五,旋繞,縮放

      1,實現下層控制代碼

      有了控制平移的基礎,我們也很容易就能控制旋轉與縮放。我們還是從下層開始,修改 OpenGLView.h 中的代碼(我將在 y 和 z 方向平移的代碼放在這里了,希望你是自己實現它的):

          float _posX;
          float _posY;
          float _posZ;
          
          float _rotateX;
          float _scaleZ;
      }
      
      @property (nonatomic, assign) float posX;
      @property (nonatomic, assign) float posY;
      @property (nonatomic, assign) float posZ;
      
      @property (nonatomic, assign) float scaleZ;
      @property (nonatomic, assign) float rotateX;

      修改 OpenGLView.m 中的代碼:

      @synthesize posX = _posX;
      @synthesize posY = _posY;
      @synthesize posZ = _posZ;
      @synthesize scaleZ = _scaleZ;
      @synthesize rotateX = _rotateX;

      前面說過,我們需要自己實現這些屬性的 setter 和 getter 方法,在這里就不一一列出了, 它們與 setPosX 和 posX 的實現是類似的。我們需要讓這些屬性來控制模型視圖矩陣,因此還要更新 updateTransform 方法如下:

      - (void)updateTransform
      {
          // Generate a model view matrix to rotate/translate/scale
          //
          ksMatrixLoadIdentity(&_modelViewMatrix);
          
          // Translate away from the viewer
          //
          ksTranslate(&_modelViewMatrix, self.posX, self.posY, self.posZ);
          
          // Rotate the triangle
          //
          ksRotate(&_modelViewMatrix, self.rotateX, 1.0, 0.0, 0.0);
          
          // Scale the triangle
          ksScale(&_modelViewMatrix, 1.0, 1.0, self.scaleZ);
          
          // Load the model-view matrix
          glUniformMatrix4fv(_modelViewSlot, 1, GL_FALSE, (GLfloat*)&_modelViewMatrix.m[0][0]);
      }

      這樣四棱錐就能繞 x 軸旋轉 rotateX 角度,并在 z 方向上縮放 scaleZ 倍。注意:屬性 scaleZ 默認值為 0,所以我們需要對它進行初始化,此外為了能方便重置模型視圖矩陣,我實現了 resetTransform,該方法在 initWithCoder 方法的最后被調用。

      - (void)resetTransform
      {
          _posX = 0.0;
          _posY = 0.0;
          _posZ = -5.5;
          
          _scaleZ = 1.0;
          _rotateX = 0.0;
          
          [self updateTransform];
      }

      2,添加上層控制代碼

       打開 MainStoryboard.storyboard,在下方的 control view 中添加滑塊與按鈕,如圖所示:

       然后修改 ViewController.h 為:

      @interface ViewController : UIViewController
      
      @property (nonatomic, strong) IBOutlet UIView * controlView;
      @property (nonatomic, strong) IBOutlet OpenGLView * openGLView;
      
      @property (nonatomic, strong) IBOutlet UISlider * posXSlider;
      @property (nonatomic, strong) IBOutlet UISlider * posYSlider;
      @property (nonatomic, strong) IBOutlet UISlider * posZSlider;
      @property (nonatomic, strong) IBOutlet UISlider * scaleZSlider;
      @property (nonatomic, strong) IBOutlet UISlider * rotateXSlider;
      
      - (IBAction)xSliderValueChanged:(id)sender; 
      - (IBAction)ySliderValueChanged:(id)sender; 
      - (IBAction)ySliderValueChanged:(id)sender;
      
      - (IBAction)scaleZSliderValueChanged:(id)sender; 
      - (IBAction)rotateXSliderValueChanged:(id)sender;
      
      - (IBAction)autoButtonClick:(id)sender;
      - (IBAction)resetButtonClick:(id)sender;
      
      @end

      在 ViewController.m 中添加屬性相關代碼:

      @synthesize posXSlider, posYSlider, posZSlider;
      @synthesize scaleZSlider, rotateXSlider;
      
      - (void)viewDidUnload
      {
          [super viewDidUnload];
          
          [self.openGLView cleanup];
          self.openGLView = nil;
          
          self.posXSlider = nil;
          self.posYSlider = nil;
          self.posZSlider = nil;
          self.scaleZSlider = nil;
          self.rotateXSlider = nil;
          self.controlView = nil;
      }

      以及響應事件的方法:

      - (IBAction)ySliderValueChanged:(id)sender
      {
          UISlider * slider = (UISlider *)sender;
          float currentValue = [slider value];
          
          openGLView.posY = currentValue;
          
          NSLog(@" >> current y is %f", currentValue);
      }
      
      - (IBAction)zSliderValueChanged:(id)sender
      {
          UISlider * slider = (UISlider *)sender;
          float currentValue = [slider value];
          
          openGLView.posZ = currentValue;
          
          NSLog(@" >> current z is %f", currentValue);
      }
      
      - (IBAction)scaleZSliderValueChanged:(id)sender
      {
          UISlider * slider = (UISlider *)sender;
          float currentValue = [slider value];
          
          openGLView.scaleZ = currentValue;
          
          NSLog(@" >> current z scale is %f", currentValue);
      }
      
      - (IBAction)rotateXSliderValueChanged:(id)sender
      {
          UISlider * slider = (UISlider *)sender;
          float currentValue = [slider value];
          
          openGLView.rotateX = currentValue;
          
          NSLog(@" >> current x rotation is %f", currentValue);   
      }
      
      - (IBAction)autoButtonClick:(id)sender
      {
      }
      
      - (IBAction)resetButtonClick:(id)sender
      {
      }

      上面的代碼很簡單,基本與平移 x 的代碼類似,所以在這里也就不一一講述了。然后回到 MainStoryboard.storyboard 中,使用拖拽技巧將相關屬性和事件與控件關聯起來。 

      3,編譯運行,滑動不同的滑塊,體驗下 3D 變換的效果。

       

      六,自動旋轉與重置

      1,重置恢復默認狀態

      還記得在前面我提到有一個重置模型視圖矩陣的方法么,如果想讓物體恢復默認狀態,只要調用此方法,再重新描繪即可。因此,resetButtonClick 實現如下:

      - (void)resetControls
      {
          [posXSlider setValue:self.openGLView.posX];
          [posYSlider setValue:self.openGLView.posY];
          [posZSlider setValue:self.openGLView.posZ];
          
          [scaleZSlider setValue:self.openGLView.scaleZ];
          [rotateXSlider setValue:self.openGLView.rotateX];
      }
      
      - (IBAction)resetButtonClick:(id)sender
      {
          [openGLView resetTransform];
          [openGLView render];
          
          [self resetControls];
      }

      在 Tutorial02 教程中 render 方法是私有方法,在這里,需要把它修改為公開方法。resetControls 是用來設置控件的默認值,以保持模型矩陣與控件的相關值同步,記得在 viewDidLoad 中調用此函數。編譯運行,無論你做了多么復雜的變換,只要按下 Reset 按鈕,一切都恢復原樣了。

      2,自動旋轉

      下面來添加點好玩的,讓物體自動繞 X 軸旋轉。這通常是通過 timer 來實現的,但蘋果為我們提供了更好的辦法:CADisplayLink(其實它內部也是使用的 timer),它可以讓我們的應用程序與屏幕的刷新率保持同步,每當屏幕刷新時,就會調用我們提供的回調函數。下面我們來使用它,在 OpenGLView.m 中的匿名 category 中添加成員變量:

      @interface OpenGLView()
      {
          CADisplayLink * _displayLink;
      }

      并添加回調函數聲明:

      - (void)displayLinkCallback:(CADisplayLink*)displayLink;

      然后在下面的 @implemetion 中實現此回調,屏幕沒刷新一次就讓四棱錐繞 x 軸旋轉一定的角度:

      - (void)displayLinkCallback:(CADisplayLink*)displayLink
      {
          self.rotateX += displayLink.duration * 90;
      }

      在 OpenGLView.h 中添加公開方法:

      - (void)toggleDisplayLink;

      然后在 OpenGLView.m 中實現之:

      - (void)toggleDisplayLink
      {
          if (_displayLink == nil) {
              _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkCallback:)];
              [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
          }
          else {
              [_displayLink invalidate];
              [_displayLink removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
              _displayLink = nil;
          }
      }

      在上面的代碼中,我們實現了一個 toggle 開關方法,如果沒有自動旋轉,那么就啟動自動旋轉;如果已經在自動旋轉了,那么就停止它。CADisplayLink 的使用很簡單,創建一個對象,設置它的 target 和回調函數,然后將它加入 NSRunLoop 中開始運行;如果要停止它,首先調用 invalidate 方法,然后將它從 NSRunLoop 中移除。

      最后,我們在按鈕的響應方法中添加對 toggleDisplayLink 的調用:

      - (IBAction)autoButtonClick:(id)sender
      {
          [openGLView toggleDisplayLink];
          
          UIButton * button = (UIButton *)sender;
          NSString * text = button.titleLabel.text;
          if ([text isEqualToString:@"Auto"]) {
              [button setTitle: @"Stop" forState: UIControlStateNormal];
          }
          else {
              [button setTitle: @"Auto" forState: UIControlStateNormal];
          }
      }

      編譯運行代碼,點擊 Auto 就能讓四棱錐自動旋轉了,再次點擊就能讓它停止自動旋轉,很妙吧?

       

      七,總結

      在這一篇文章中,介紹了如何通過 3D 變換來實現平移,旋轉和縮放,以更好地理解前文中介紹的理論知識;同時也實現了如何通過 UIControl 來控制 OpenGL View 中的物體;此外還詳細介紹了描繪圖元的模式以及頂點索引模式。在文章的最后,介紹了如何使用 CADisplayLink 來實現動畫效果。

      最后,四棱錐看起來有點丑陋,來個水立方怎么樣?(長方體),這個任務就交給看官你了,相信你一定可以實現的。

       

      
      
      posted @ 2012-12-07 22:10  飄飄白云  閱讀(9640)  評論(0)    收藏  舉報
      本博客遵循 Creative Commons License “署名-非商業用途-保持一致”創作共用協議。 與我聯系
      主站蜘蛛池模板: 色悠悠国产在线视频一线| 午夜欧美精品久久久久久久| 澳门永久av免费网站| √天堂资源地址在线官网| 中文字幕亚洲男人的天堂网络| 在线观看成人永久免费网站| 午夜高清福利在线观看| 蜜芽久久人人超碰爱香蕉| 与子乱对白在线播放单亲国产 | 人妻激情视频一区二区三区| 成人免费精品网站在线观看影片 | 亚洲真人无码永久在线| 亚洲精品色在线网站| 中文字幕国产精品一区二| 久久精品娱乐亚洲领先| 精品无码久久久久久尤物| av无码一区二区大桥久未| 亚洲av鲁丝一区二区三区黄| 国产一码二码三码区别| 色老99久久精品偷偷鲁| 国产日韩精品一区在线不卡| 欧美精品V欧洲精品| 116美女极品a级毛片| 国产精品黄色片在线观看| 国产v亚洲v天堂a无码99 | 国产乱子伦一区二区三区四区五区 | 久久香蕉国产线看观看怡红院妓院| 柠檬福利第一导航在线| 亚洲色最新高清AV网站| 日本一道一区二区视频| 少妇放荡的呻吟干柴烈火动漫| 无码专区人妻系列日韩精品少妇| 公与淑婷厨房猛烈进出视频免费 | 免费无码又爽又刺激网站直播| 人妻精品人妻无码一区二区三区| 国产亚洲精品第一综合另类| 《特殊的精油按摩》3| 亚洲国产成人久久一区久久| 2021国产成人精品久久| 日韩乱码人妻无码中文字幕视频| 日韩深夜免费在线观看|