diff options
Diffstat (limited to 'docs/html/training/graphics/opengl/touch.jd')
| -rw-r--r-- | docs/html/training/graphics/opengl/touch.jd | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/docs/html/training/graphics/opengl/touch.jd b/docs/html/training/graphics/opengl/touch.jd new file mode 100644 index 0000000..c058a59 --- /dev/null +++ b/docs/html/training/graphics/opengl/touch.jd @@ -0,0 +1,145 @@ +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> |
