50e990c64f
Change-Id: Idc55a0b368c1d2c1e7d4999601b739dd57f08eb3
146 lines
4.9 KiB
Plaintext
146 lines
4.9 KiB
Plaintext
page.title= Responding to Touch Events
|
|
parent.title=Displaying Graphics with OpenGL ES
|
|
parent.link=index.html
|
|
|
|
trainingnavtop=true
|
|
previous.title=Adding Motion
|
|
previous.link=motion.html
|
|
|
|
@jd:body
|
|
|
|
<div id="tb-wrapper">
|
|
<div id="tb">
|
|
|
|
<h2>This lesson teaches you to</h2>
|
|
<ol>
|
|
<li><a href="#listener">Setup a Touch Listener</a></li>
|
|
<li><a href="#angle">Expose the Rotation Angle</a></li>
|
|
<li><a href="#rotate">Apply Rotation</a></li>
|
|
</ol>
|
|
|
|
<h2>You should also read</h2>
|
|
<ul>
|
|
<li><a href="{@docRoot}guide/topics/graphics/opengl.html">OpenGL</a></li>
|
|
</ul>
|
|
|
|
<div class="download-box">
|
|
<a href="http://developer.android.com/shareables/training/OpenGLES.zip"
|
|
class="button">Download the sample</a>
|
|
<p class="filename">OpenGLES.zip</p>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<p>Making objects move according to a preset program like the rotating triangle is useful for
|
|
getting some attention, but what if you want to have users interact with your OpenGL ES graphics?
|
|
The key to making your OpenGL ES application touch interactive is expanding your implementation of
|
|
{@link android.opengl.GLSurfaceView} to override the {@link
|
|
android.opengl.GLSurfaceView#onTouchEvent onTouchEvent()} to listen for touch events.</p>
|
|
|
|
<p>This lesson shows you how to listen for touch events to let users rotate an OpenGL ES object.</p>
|
|
|
|
|
|
<h2 id="listener">Setup a Touch Listener</h2>
|
|
|
|
<p>In order to make your OpenGL ES application respond to touch events, you must implement the
|
|
{@link android.opengl.GLSurfaceView#onTouchEvent onTouchEvent()} method in your
|
|
{@link android.opengl.GLSurfaceView} class. The example implementation below shows how to listen for
|
|
{@link android.view.MotionEvent#ACTION_MOVE MotionEvent.ACTION_MOVE} events and translate them to
|
|
an angle of rotation for a shape.</p>
|
|
|
|
<pre>
|
|
@Override
|
|
public boolean onTouchEvent(MotionEvent e) {
|
|
// MotionEvent reports input details from the touch screen
|
|
// and other input controls. In this case, you are only
|
|
// interested in events where the touch position changed.
|
|
|
|
float x = e.getX();
|
|
float y = e.getY();
|
|
|
|
switch (e.getAction()) {
|
|
case MotionEvent.ACTION_MOVE:
|
|
|
|
float dx = x - mPreviousX;
|
|
float dy = y - mPreviousY;
|
|
|
|
// reverse direction of rotation above the mid-line
|
|
if (y > getHeight() / 2) {
|
|
dx = dx * -1 ;
|
|
}
|
|
|
|
// reverse direction of rotation to left of the mid-line
|
|
if (x < getWidth() / 2) {
|
|
dy = dy * -1 ;
|
|
}
|
|
|
|
mRenderer.mAngle += (dx + dy) * TOUCH_SCALE_FACTOR; // = 180.0f / 320
|
|
requestRender();
|
|
}
|
|
|
|
mPreviousX = x;
|
|
mPreviousY = y;
|
|
return true;
|
|
}
|
|
</pre>
|
|
|
|
<p>Notice that after calculating the rotation angle, this method calls {@link
|
|
android.opengl.GLSurfaceView#requestRender requestRender()} to tell the
|
|
renderer that it is time to render the frame. This approach is the most efficient in this example
|
|
because the frame does not need to be redrawn unless there is a change in the rotation. However, it
|
|
does not have any impact on efficiency unless you also request that the renderer only redraw when
|
|
the data changes using the {@link android.opengl.GLSurfaceView#setRenderMode setRenderMode()}
|
|
method, so make sure this line is uncommented in the renderer:</p>
|
|
|
|
<pre>
|
|
public MyGLSurfaceView(Context context) {
|
|
...
|
|
// Render the view only when there is a change in the drawing data
|
|
<strong>setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);</strong>
|
|
}
|
|
</pre>
|
|
|
|
<h2 id="angle">Expose the Rotation Angle</h2>
|
|
|
|
<p>The example code above requires that you expose the rotation angle through your renderer by
|
|
adding a public member. Since the renderer code is running on a separate thread from the main user
|
|
interface thread of your application, you must declare this public variable as {@code volatile}.
|
|
Here is the code to do that:</p>
|
|
|
|
<pre>
|
|
public class MyGLRenderer implements GLSurfaceView.Renderer {
|
|
...
|
|
public volatile float mAngle;
|
|
</pre>
|
|
|
|
|
|
<h2 id="rotate">Apply Rotation</h2>
|
|
|
|
<p>To apply the rotation generated by touch input, comment out the code that generates an angle and
|
|
add {@code mAngle}, which contains the touch input generated angle:</p>
|
|
|
|
<pre>
|
|
public void onDrawFrame(GL10 gl) {
|
|
...
|
|
// Create a rotation for the triangle
|
|
// long time = SystemClock.uptimeMillis() % 4000L;
|
|
// float angle = 0.090f * ((int) time);
|
|
<strong>Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f);</strong>
|
|
|
|
// Combine the rotation matrix with the projection and camera view
|
|
Matrix.multiplyMM(mMVPMatrix, 0, mRotationMatrix, 0, mMVPMatrix, 0);
|
|
|
|
// Draw triangle
|
|
mTriangle.draw(mMVPMatrix);
|
|
}
|
|
</pre>
|
|
|
|
<p>When you have completed the steps described above, run the program and drag your finger over the
|
|
screen to rotate the triangle:</p>
|
|
|
|
<img src="{@docRoot}images/opengl/ogl-triangle-touch.png">
|
|
<p class="img-caption">
|
|
<strong>Figure 1.</strong> Triangle being rotated with touch input (circle shows touch
|
|
location).</p>
|