examples/opengl/hellogl_es/glwidget.cpp
changeset 30 5dc02b23752f
parent 18 2f34d5167611
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
     4 ** All rights reserved.
     4 ** All rights reserved.
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     6 **
     6 **
     7 ** This file is part of the examples of the Qt Toolkit.
     7 ** This file is part of the examples of the Qt Toolkit.
     8 **
     8 **
     9 ** $QT_BEGIN_LICENSE:LGPL$
     9 ** $QT_BEGIN_LICENSE:BSD$
    10 ** No Commercial Usage
    10 ** You may use this file under the terms of the BSD license as follows:
    11 ** This file contains pre-release code and may not be distributed.
    11 **
    12 ** You may use this file in accordance with the terms and conditions
    12 ** "Redistribution and use in source and binary forms, with or without
    13 ** contained in the Technology Preview License Agreement accompanying
    13 ** modification, are permitted provided that the following conditions are
    14 ** this package.
    14 ** met:
    15 **
    15 **   * Redistributions of source code must retain the above copyright
    16 ** GNU Lesser General Public License Usage
    16 **     notice, this list of conditions and the following disclaimer.
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
    17 **   * Redistributions in binary form must reproduce the above copyright
    18 ** General Public License version 2.1 as published by the Free Software
    18 **     notice, this list of conditions and the following disclaimer in
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
    19 **     the documentation and/or other materials provided with the
    20 ** packaging of this file.  Please review the following information to
    20 **     distribution.
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
    21 **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    22 **     the names of its contributors may be used to endorse or promote
    23 **
    23 **     products derived from this software without specific prior written
    24 ** In addition, as a special exception, Nokia gives you certain additional
    24 **     permission.
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
    25 **
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    26 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    27 **
    27 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    28 ** If you have questions regarding the use of this file, please contact
    28 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    29 ** Nokia at qt-info@nokia.com.
    29 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    30 **
    30 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    31 **
    31 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    32 **
    32 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    33 **
    33 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    34 **
    34 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    35 **
    35 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    36 **
    36 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
    37 **
       
    38 ** $QT_END_LICENSE$
    37 ** $QT_END_LICENSE$
    39 **
    38 **
    40 ****************************************************************************/
    39 ****************************************************************************/
    41 
    40 
    42 #include "glwidget.h"
    41 #include "glwidget.h"
    43 #include <QPainter>
    42 #include <QPainter>
    44 #include <math.h>
    43 #include <math.h>
    45 
    44 
    46 #include "bubble.h"
    45 #include "bubble.h"
    47 #include "cl_helper.h"
       
    48 
    46 
    49 
    47 
    50 const int bubbleNum = 8;
    48 const int bubbleNum = 8;
    51 
    49 
    52 inline void CrossProduct(qreal &xOut, qreal &yOut, qreal &zOut, qreal x1, qreal y1, qreal z1, qreal x2, qreal y2, qreal z2)
    50 inline void CrossProduct(qreal &xOut, qreal &yOut, qreal &zOut, qreal x1, qreal y1, qreal z1, qreal x2, qreal y2, qreal z2)
   112 //! [2]
   110 //! [2]
   113 void GLWidget::paintQtLogo()
   111 void GLWidget::paintQtLogo()
   114 {
   112 {
   115     glDisable(GL_TEXTURE_2D);
   113     glDisable(GL_TEXTURE_2D);
   116     glEnableClientState(GL_VERTEX_ARRAY);
   114     glEnableClientState(GL_VERTEX_ARRAY);
   117     glVertexPointer(3,q_vertexTypeEnum,0, createdVertices);
   115     glVertexPointer(3,GL_FLOAT,0, createdVertices);
   118     glEnableClientState(GL_NORMAL_ARRAY);
   116     glEnableClientState(GL_NORMAL_ARRAY);
   119     glNormalPointer(q_vertexTypeEnum,0,createdNormals);
   117     glNormalPointer(GL_FLOAT,0,createdNormals);
   120     glDrawArrays(GL_TRIANGLES, 0, m_vertexNumber / 3);
   118     glDrawArrays(GL_TRIANGLES, 0, m_vertexNumber / 3);
   121 }
   119 }
   122 //! [2]
   120 //! [2]
   123 
   121 
   124 void GLWidget::paintTexturedCube()
   122 void GLWidget::paintTexturedCube()
   125 {
   123 {
   126     glEnable(GL_TEXTURE_2D);
   124     glEnable(GL_TEXTURE_2D);
   127     glBindTexture(GL_TEXTURE_2D, m_uiTexture);
   125     glBindTexture(GL_TEXTURE_2D, m_uiTexture);
   128     q_vertexType afVertices[] = {
   126     GLfloat afVertices[] = {
   129         f2vt(-0.5), f2vt(0.5), f2vt(0.5), f2vt(0.5),f2vt(-0.5),f2vt(0.5),f2vt(-0.5),f2vt(-0.5),f2vt(0.5),
   127         -0.5, 0.5, 0.5, 0.5,-0.5,0.5,-0.5,-0.5,0.5,
   130         f2vt(0.5), f2vt(-0.5), f2vt(0.5), f2vt(-0.5),f2vt(0.5),f2vt(0.5),f2vt(0.5),f2vt(0.5),f2vt(0.5),
   128         0.5, -0.5, 0.5, -0.5,0.5,0.5,0.5,0.5,0.5,
   131         f2vt(-0.5), f2vt(-0.5), f2vt(-0.5), f2vt(0.5),f2vt(-0.5),f2vt(-0.5),f2vt(-0.5),f2vt(0.5),f2vt(-0.5),
   129         -0.5, -0.5, -0.5, 0.5,-0.5,-0.5,-0.5,0.5,-0.5,
   132         f2vt(0.5), f2vt(0.5), f2vt(-0.5), f2vt(-0.5),f2vt(0.5),f2vt(-0.5),f2vt(0.5),f2vt(-0.5),f2vt(-0.5),
   130         0.5, 0.5, -0.5, -0.5,0.5,-0.5,0.5,-0.5,-0.5,
   133 
   131 
   134         f2vt(0.5), f2vt(-0.5), f2vt(-0.5), f2vt(0.5),f2vt(-0.5),f2vt(0.5),f2vt(0.5),f2vt(0.5),f2vt(-0.5),
   132         0.5, -0.5, -0.5, 0.5,-0.5,0.5,0.5,0.5,-0.5,
   135         f2vt(0.5), f2vt(0.5), f2vt(0.5), f2vt(0.5),f2vt(0.5),f2vt(-0.5),f2vt(0.5),f2vt(-0.5),f2vt(0.5),
   133         0.5, 0.5, 0.5, 0.5,0.5,-0.5,0.5,-0.5,0.5,
   136         f2vt(-0.5), f2vt(0.5), f2vt(-0.5), f2vt(-0.5),f2vt(-0.5),f2vt(0.5),f2vt(-0.5),f2vt(-0.5),f2vt(-0.5),
   134         -0.5, 0.5, -0.5, -0.5,-0.5,0.5,-0.5,-0.5,-0.5,
   137         f2vt(-0.5), f2vt(-0.5), f2vt(0.5), f2vt(-0.5),f2vt(0.5),f2vt(-0.5),f2vt(-0.5),f2vt(0.5),f2vt(0.5),
   135         -0.5, -0.5, 0.5, -0.5,0.5,-0.5,-0.5,0.5,0.5,
   138 
   136 
   139         f2vt(0.5), f2vt(0.5),  f2vt(-0.5), f2vt(-0.5), f2vt(0.5),  f2vt(0.5),  f2vt(-0.5),  f2vt(0.5),  f2vt(-0.5),
   137         0.5, 0.5,  -0.5, -0.5, 0.5,  0.5,  -0.5,  0.5,  -0.5,
   140         f2vt(-0.5),  f2vt(0.5),  f2vt(0.5),  f2vt(0.5),  f2vt(0.5),  f2vt(-0.5), f2vt(0.5), f2vt(0.5),  f2vt(0.5),
   138         -0.5,  0.5,  0.5,  0.5,  0.5,  -0.5, 0.5, 0.5,  0.5,
   141         f2vt(-0.5),  f2vt(-0.5), f2vt(-0.5), f2vt(-0.5), f2vt(-0.5), f2vt(0.5),  f2vt(0.5), f2vt(-0.5), f2vt(-0.5),
   139         -0.5,  -0.5, -0.5, -0.5, -0.5, 0.5,  0.5, -0.5, -0.5,
   142         f2vt(0.5), f2vt(-0.5), f2vt(0.5),  f2vt(0.5),  f2vt(-0.5), f2vt(-0.5), f2vt(-0.5),  f2vt(-0.5), f2vt(0.5)
   140         0.5, -0.5, 0.5,  0.5,  -0.5, -0.5, -0.5,  -0.5, 0.5
   143     };
   141     };
   144     glEnableClientState(GL_VERTEX_ARRAY);
   142     glEnableClientState(GL_VERTEX_ARRAY);
   145     glVertexPointer(3,q_vertexTypeEnum,0,afVertices);
   143     glVertexPointer(3,GL_FLOAT,0,afVertices);
   146 
   144 
   147     q_vertexType afTexCoord[] = {
   145     GLfloat afTexCoord[] = {
   148         f2vt(0.0f),f2vt(0.0f), f2vt(1.0f),f2vt(1.0f), f2vt(1.0f),f2vt(0.0f),
   146         0.0f,0.0f, 1.0f,1.0f, 1.0f,0.0f,
   149         f2vt(1.0f),f2vt(1.0f), f2vt(0.0f),f2vt(0.0f), f2vt(0.0f),f2vt(1.0f),
   147         1.0f,1.0f, 0.0f,0.0f, 0.0f,1.0f,
   150         f2vt(1.0f),f2vt(1.0f), f2vt(1.0f),f2vt(0.0f), f2vt(0.0f),f2vt(1.0f),
   148         1.0f,1.0f, 1.0f,0.0f, 0.0f,1.0f,
   151         f2vt(0.0f),f2vt(0.0f), f2vt(0.0f),f2vt(1.0f), f2vt(1.0f),f2vt(0.0f),
   149         0.0f,0.0f, 0.0f,1.0f, 1.0f,0.0f,
   152 
   150 
   153         f2vt(1.0f),f2vt(1.0f), f2vt(1.0f),f2vt(0.0f), f2vt(0.0f),f2vt(1.0f),
   151         1.0f,1.0f, 1.0f,0.0f, 0.0f,1.0f,
   154         f2vt(0.0f),f2vt(0.0f), f2vt(0.0f),f2vt(1.0f), f2vt(1.0f),f2vt(0.0f),
   152         0.0f,0.0f, 0.0f,1.0f, 1.0f,0.0f,
   155         f2vt(0.0f),f2vt(0.0f), f2vt(1.0f),f2vt(1.0f), f2vt(1.0f),f2vt(0.0f),
   153         0.0f,0.0f, 1.0f,1.0f, 1.0f,0.0f,
   156         f2vt(1.0f),f2vt(1.0f), f2vt(0.0f),f2vt(0.0f), f2vt(0.0f),f2vt(1.0f),
   154         1.0f,1.0f, 0.0f,0.0f, 0.0f,1.0f,
   157 
   155 
   158         f2vt(0.0f),f2vt(1.0f), f2vt(1.0f),f2vt(0.0f), f2vt(1.0f),f2vt(1.0f),
   156         0.0f,1.0f, 1.0f,0.0f, 1.0f,1.0f,
   159         f2vt(1.0f),f2vt(0.0f), f2vt(0.0f),f2vt(1.0f), f2vt(0.0f),f2vt(0.0f),
   157         1.0f,0.0f, 0.0f,1.0f, 0.0f,0.0f,
   160         f2vt(1.0f),f2vt(0.0f), f2vt(1.0f),f2vt(1.0f), f2vt(0.0f),f2vt(0.0f),
   158         1.0f,0.0f, 1.0f,1.0f, 0.0f,0.0f,
   161         f2vt(0.0f),f2vt(1.0f), f2vt(0.0f),f2vt(0.0f), f2vt(1.0f),f2vt(1.0f)
   159         0.0f,1.0f, 0.0f,0.0f, 1.0f,1.0f
   162     };
   160     };
   163     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
   161     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
   164     glTexCoordPointer(2,q_vertexTypeEnum,0,afTexCoord);
   162     glTexCoordPointer(2,GL_FLOAT,0,afTexCoord);
   165 
   163 
   166     q_vertexType afNormals[] = {
   164     GLfloat afNormals[] = {
   167 
   165 
   168         f2vt(0),f2vt(0),f2vt(-1), f2vt(0),f2vt(0),f2vt(-1), f2vt(0),f2vt(0),f2vt(-1),
   166         0,0,-1, 0,0,-1, 0,0,-1,
   169         f2vt(0),f2vt(0),f2vt(-1), f2vt(0),f2vt(0),f2vt(-1), f2vt(0),f2vt(0),f2vt(-1),
   167         0,0,-1, 0,0,-1, 0,0,-1,
   170         f2vt(0),f2vt(0),f2vt(1), f2vt(0),f2vt(0),f2vt(1), f2vt(0),f2vt(0),f2vt(1),
   168         0,0,1, 0,0,1, 0,0,1,
   171         f2vt(0),f2vt(0),f2vt(1), f2vt(0),f2vt(0),f2vt(1), f2vt(0),f2vt(0),f2vt(1),
   169         0,0,1, 0,0,1, 0,0,1,
   172 
   170 
   173         f2vt(-1),f2vt(0),f2vt(0), f2vt(-1),f2vt(0),f2vt(0), f2vt(-1),f2vt(0),f2vt(0),
   171         -1,0,0, -1,0,0, -1,0,0,
   174         f2vt(-1),f2vt(0),f2vt(0), f2vt(-1),f2vt(0),f2vt(0), f2vt(-1),f2vt(0),f2vt(0),
   172         -1,0,0, -1,0,0, -1,0,0,
   175         f2vt(1),f2vt(0),f2vt(0), f2vt(1),f2vt(0),f2vt(0), f2vt(1),f2vt(0),f2vt(0),
   173         1,0,0, 1,0,0, 1,0,0,
   176         f2vt(1),f2vt(0),f2vt(0), f2vt(1),f2vt(0),f2vt(0), f2vt(1),f2vt(0),f2vt(0),
   174         1,0,0, 1,0,0, 1,0,0,
   177 
   175 
   178         f2vt(0),f2vt(-1),f2vt(0), f2vt(0),f2vt(-1),f2vt(0), f2vt(0),f2vt(-1),f2vt(0),
   176         0,-1,0, 0,-1,0, 0,-1,0,
   179         f2vt(0),f2vt(-1),f2vt(0), f2vt(0),f2vt(-1),f2vt(0), f2vt(0),f2vt(-1),f2vt(0),
   177         0,-1,0, 0,-1,0, 0,-1,0,
   180         f2vt(0),f2vt(1),f2vt(0), f2vt(0),f2vt(1),f2vt(0), f2vt(0),f2vt(1),f2vt(0),
   178         0,1,0, 0,1,0, 0,1,0,
   181         f2vt(0),f2vt(1),f2vt(0), f2vt(0),f2vt(1),f2vt(0), f2vt(0),f2vt(1),f2vt(0)
   179         0,1,0, 0,1,0, 0,1,0
   182     };
   180     };
   183     glEnableClientState(GL_NORMAL_ARRAY);
   181     glEnableClientState(GL_NORMAL_ARRAY);
   184     glNormalPointer(q_vertexTypeEnum,0,afNormals);
   182     glNormalPointer(GL_FLOAT,0,afNormals);
   185 
   183 
   186     glDrawArrays(GL_TRIANGLES, 0, 36);
   184     glDrawArrays(GL_TRIANGLES, 0, 36);
   187 }
   185 }
   188 
   186 
   189 void GLWidget::initializeGL ()
   187 void GLWidget::initializeGL ()
   190 {
   188 {
   191     q_glClearColor(f2vt(0.1f), f2vt(0.1f), f2vt(0.2f), f2vt(1.0f));
   189     glClearColor(0.1f, 0.1f, 0.2f, 1.0f);
   192 
   190 
   193     glEnable(GL_TEXTURE_2D);
   191     glEnable(GL_TEXTURE_2D);
   194     glGenTextures(1, &m_uiTexture);
   192     glGenTextures(1, &m_uiTexture);
   195     m_uiTexture = bindTexture(QImage(":/qt.png"));
   193     m_uiTexture = bindTexture(QImage(":/qt.png"));
   196 
   194 
   197     q_glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
   195     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
   198     q_glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
   196     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
   199     glEnable(GL_LIGHTING);
   197     glEnable(GL_LIGHTING);
   200     glEnable(GL_LIGHT0);
   198     glEnable(GL_LIGHT0);
   201 
   199 
   202     q_vertexType aLightPosition[] = {f2vt(0.0f),f2vt(0.3f),f2vt(1.0f),f2vt(0.0f)};
   200     GLfloat aLightPosition[] = {0.0f,0.3f,1.0f,0.0f};
   203 
   201 
   204     q_glLightv(GL_LIGHT0, GL_SPOT_DIRECTION, aLightPosition);
   202     glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, aLightPosition);
   205     m_fAngle = 0;
   203     m_fAngle = 0;
   206     m_fScale = 1;
   204     m_fScale = 1;
   207     createGeometry();
   205     createGeometry();
   208     createBubbles(bubbleNum - bubbles.count());
   206     createBubbles(bubbleNum - bubbles.count());
   209 }
   207 }
   228     glPushMatrix();
   226     glPushMatrix();
   229 
   227 
   230     //Since OpenGL ES does not support glPush/PopAttrib(GL_ALL_ATTRIB_BITS) 
   228     //Since OpenGL ES does not support glPush/PopAttrib(GL_ALL_ATTRIB_BITS) 
   231     //we have to take care of the states ourselves
   229     //we have to take care of the states ourselves
   232 
   230 
   233     q_glClearColor(f2vt(0.1f), f2vt(0.1f), f2vt(0.2f), f2vt(1.0f));
   231     glClearColor(0.1f, 0.1f, 0.2f, 1.0f);
   234     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   232     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   235     glEnable(GL_TEXTURE_2D);
   233     glEnable(GL_TEXTURE_2D);
   236 
   234 
   237     q_glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
   235     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
   238     q_glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
   236     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
   239     glEnable(GL_LIGHTING);
   237     glEnable(GL_LIGHTING);
   240     glEnable(GL_LIGHT0);
   238     glEnable(GL_LIGHT0);
   241 
   239 
   242     glShadeModel(GL_FLAT);
   240     glShadeModel(GL_FLAT);
   243     glFrontFace(GL_CW);
   241     glFrontFace(GL_CW);
   246     glEnable(GL_DEPTH_TEST);
   244     glEnable(GL_DEPTH_TEST);
   247 
   245 
   248     glMatrixMode(GL_MODELVIEW);
   246     glMatrixMode(GL_MODELVIEW);
   249     glLoadIdentity();
   247     glLoadIdentity();
   250 
   248 
   251     q_glRotate(f2vt(m_fAngle), f2vt(0.0), f2vt(1.0), f2vt(0.0));
   249     glRotatef(m_fAngle, 0.0f, 1.0f, 0.0f);
   252     q_glRotate(f2vt(m_fAngle), f2vt(1.0), f2vt(0.0), f2vt(0.0));
   250     glRotatef(m_fAngle, 1.0f, 0.0f, 0.0f);
   253     q_glRotate(f2vt(m_fAngle), f2vt(0.0), f2vt(0.0), f2vt(1.0));
   251     glRotatef(m_fAngle, 0.0f, 0.0f, 1.0f);
   254     q_glScale(f2vt(m_fScale), f2vt(m_fScale),f2vt(m_fScale));
   252     glScalef(m_fScale, m_fScale,m_fScale);
   255     q_glTranslate(f2vt(0),f2vt(-0.2),f2vt(0));
   253     glTranslatef(0.0f,-0.2f,0.0f);
   256 
   254 
   257     q_vertexType matDiff[] = {f2vt(0.40), f2vt(1.0), f2vt(0.0), f2vt(1.0)};
   255     GLfloat matDiff[] = {0.40f, 1.0f, 0.0f, 1.0f};
   258     q_glMaterialv(GL_FRONT_AND_BACK, GL_DIFFUSE, matDiff);
   256     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matDiff);
   259 
   257 
   260     if (qtLogo)
   258     if (qtLogo)
   261         paintQtLogo();
   259         paintQtLogo();
   262     else
   260     else
   263         paintTexturedCube();
   261         paintTexturedCube();
   374         extrude(x8, y8, x5, y5);
   372         extrude(x8, y8, x5, y5);
   375     }
   373     }
   376 
   374 
   377 //! [1]
   375 //! [1]
   378     m_vertexNumber = vertices.size();
   376     m_vertexNumber = vertices.size();
   379     createdVertices = new q_vertexType[m_vertexNumber];
   377     createdVertices = new GLfloat[m_vertexNumber];
   380     createdNormals = new q_vertexType[m_vertexNumber];
   378     createdNormals = new GLfloat[m_vertexNumber];
   381     for (int i = 0;i < m_vertexNumber;i++) {
   379     for (int i = 0;i < m_vertexNumber;i++) {
   382       createdVertices[i] = f2vt(vertices.at(i) * 2);
   380       createdVertices[i] = vertices.at(i) * 2;
   383       createdNormals[i] = f2vt(normals.at(i));
   381       createdNormals[i] = normals.at(i);
   384     }
   382     }
   385     vertices.clear();
   383     vertices.clear();
   386     normals.clear();
   384     normals.clear();
   387 }
   385 }
   388 //! [1]
   386 //! [1]