Android OpenGL ES sphere

Source: Internet
Author: User
Tags android games

Recently, due to interest, I began to learn OpenGL plotting. This article uses "Draw sphere" as a point to summarize what we have learned recently.


> OpenGL ES started with OpenGL from Android. As we all know, Android View is thread unsafe, so it is only allowed to operate on the View in the main thread. However, if we need to implement a complex interface, especially for game development, and draw a large number of images in the main thread, it will take a long time, so that the winner thread fails to respond to user input in time, or even appears ANR. Therefore, Android provides a SurfaceView class through the dual-buffer mechanism (two canvases? Three Canvases ?), Allows the user to operate the Canvas in non-main threads to Implement Asynchronous refresh of the View. The Canvas class provides many painting methods: drawPoint (...) drawCircle (...) drawBitmap (...) drawRect (...) drawText (...) drawOval (...)

Then, if you want to achieve more complex effects (such as 3D), Canvas is hard to be competent. Now, most Android games are implemented using OpenGL.

Where is OpenGL holy? In fact, the final image (2D or 3D) is displayed on the display screen, so the final operation must be performed on a 2D Display memory. OpenGL provides many methods to help us define a spatial three-dimensional model, and then calculate the ing matrix based on the various parameters we input, so as to reflect the effect on the display screen.

OpenGL ES (OpenGL for Embedded Systems) is a subset of specialized OpenGL APIs and is used for Embedded platforms such as mobile phones. A simple understanding is that it is specially developed to a "low-end" environment. Many unnecessary methods are removed, leaving the most basic.


> Using OpenGL ES to draw OpenGL ES provides two ways to draw space ry. 1. glDrawArrays (int mode, int first, int count); 2. glDrawElements (int mode, int count, int type, Buffer indices); the mode parameter has the following values: GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_TRIANGLES, distance, GL_TRIANGLE_FAN. draw point, draw line, draw triangle! That's all! We believe that any spatial image can be represented by a point, line, or triangle. 3. glVertexPointer (...) defines all vertices of A ry. After this method is called, The glDrawArrays and glDrawElements Methods draw a Graph Based on the vertex.
This is because we will draw a sphere by splicing a lot of triangles (which sounds interesting ). So let's take a look at three models of triangle painting:
According to the order of vertices, GL_TRIANGLES draws triangles by three vertices. GL_TRIANGL_STRIP always forms a triangle with the last three vertices. GL_TRIANGLE_FAN is centered on the first vertex, the following vertices form triangles respectively. Next we will use the GL_TRIANGLE_STRIP mode to draw a sphere.
> Using triangles to form a space sphere we use the idea of extreme approximation. I thought that I would not use this idea to calculate the circumference rate π. When there are too many sides in the positive polygon, it looks like a circle!
So we also think that when there are enough sides in the positive polygon, it looks like a ball! Vcw = "alt =" \ "src =" http://www.bkjia.com/uploads/allimg/140706/00211H0F-4.jpg "width =" 758 "height =" 269 ">
Well, the idea is there, but we didn't end up painting through a positive polygon. It seems that it is troublesome to use a positive polygon to cut a ball. If you use the vertical and horizontal cutting method of the cable, it is much easier to calculate!
The left and right longitude lines and the upper and lower weft lines form a square (approximate ). A square can be viewed as composed of two triangles. The yellow arrow on the way represents the vertex sequence used for drawing in GL_TRIANGLE_STRIP mode. This cutting method looks much clearer, and the vertical and longitude layers traverse all vertices cyclically. The key is: how to calculate the vertex coordinates of the sphere? (X, y, z)
> For Coordinate Calculation of spherical vertices, we first confirm two traversal directions: the first layer: Starting from the negative direction of the Y axis, the angle continues to increase until the positive direction of the Y axis. (Clock->) second layer: fixed Y value, take the Y axis as the rotation axis and rotate it at 360 degrees. All vertices can be traversed. For example, angle a increases progressively, and angle B changes 360 degrees. SeogKHgwLCB5MCwgejApILzGy + fill + INS0wus8L2gyPgrS1M/Csr + export/hiouv1_pc3bsyxm21m/Export /HIoUVHTENvbmZpZ7bUz/MKNKOstLS9qEVHTENvbnRleHS21M/empty + qys23xUVHTENvbnRleHS21M/zCjmjrMm + s/empty Export/2ry0v8mhowo8YnI + Cgo8cHJlIGNsYXNzPQ = "brush: java;"> import java. nio. byteBuffer; import java. nio. byteOrder; import java. nio. floatBuffer; import javax. microedition. khronos. egl. EGLConfig; import javax. microedition. khronos. opengles. GL10; import android. opengl. GLU; import android. opengl. GLSurfaceView. renderer; public class OpenGLRenderer4 im Plements Renderer {// environment light private final float [] mat_ambient = {0.2f, 0.3f, 0.4f, 1.0f}; private FloatBuffer mat_ambient_buf; // parallel incident light private final float [] mat_diffuse = {0.4f, 0.6f, 0.8f, 1.0f}; private FloatBuffer mat_diffuse_buf; // private final float [] mat_specular = {0.2f * 0.4f, 0.2f * 0.6f, 0.2f * 0.8f, 1.0f}; private FloatBuffer mat_specular_buf; private Sphere mSphere = new Sphere (); pu Blic volatile float mLightX = 10f; public volatile float mLightY = 10f; public volatile float mLightZ = 10f; @ Overridepublic void onDrawFrame (GL10 gl) {// clear the screen and depth cache gl. glClear (GL10.GL _ COLOR_BUFFER_BIT | GL10.GL _ DEPTH_BUFFER_BIT); // reset the current model observation matrix gl. glLoadIdentity (); gl. glable (GL10.GL _ LIGHTING); gl. glable (GL10.GL _ LIGHT0); // material gl. glMaterialfv (GL10.GL _ FRONT_AND_BACK, GL10.GL _ AMBIENT, mat_ambient_buf); g L. glMaterialfv (GL10.GL _ FRONT_AND_BACK, GL10.GL _ DIFFUSE, latency); gl. glMaterialfv (GL10.GL _ FRONT_AND_BACK, GL10.GL _ SPECULAR, mat_specular_buf); // The Mirror index is 0 ~ The smaller the value of 128, the more rough the gl. glMaterialf (GL10.GL _ FRONT_AND_BACK, GL10.GL _ SHININESS, 96.0f); // float [] light_position = {mLightX, mLightY, mLightZ, 0.0f}; ByteBuffer mpbb = ByteBuffer. allocateDirect (light_position.length * 4); mpbb. order (ByteOrder. nativeOrder (); FloatBuffer mat_posiBuf = mpbb. asFloatBuffer (); mat_posiBuf.put (light_position); mat_posiBuf.position (0); gl. glLightfv (GL10.GL _ LIGHT0, GL10.GL _ POSITION, mat_posiBuf); gl. glTranslatef (0.0f, 0.0f,-3.0f); mSphere. draw (gl) ;}@ Overridepublic void onSurfaceChanged (GL10 gl, int width, int height) {// set the size of the output screen gl. glViewport (0, 0, width, height); // sets the gl projection matrix. glMatrixMode (GL10.GL _ PROJECTION); // reset the PROJECTION matrix gl. glLoadIdentity (); // you can specify the size of the backend port. glFrustumf (0, width, 0, height, 0.1f, 100366f); GLU. gluPerspective (gl, 90.0f, (float) width/height, 0.1f, 50366f); // select the model observation matrix gl. glMatrixMode (GL10.GL _ MODELVIEW); // resets the model observation matrix gl. glLoadIdentity () ;}@ Overridepublic void onSurfaceCreated (GL10 gl, EGLConfig arg1) {// modify gl for perspective. glHint (GL10.GL _ PERSPECTIVE_CORRECTION_HINT, GL10.GL _ FASTEST); // Background: Black gl. glClearColor (0, 0.0f, 0.0f, 0.0f); // starts the shadow smooth gl. glShadeModel (GL10.GL _ SMOOTH); // reset the deep cache gl. glClearDepthf (1.0f); // start the deep test gl. glable (GL10.GL _ DEPTH_TEST); // type of the deep test. glDepthFunc (GL10.GL _ LEQUAL); initBuffers ();} private void initBuffers () {ByteBuffer bufTemp = ByteBuffer. allocateDirect (mat_ambient.length * 4); bufTemp. order (ByteOrder. nativeOrder (); mat_ambient_buf = bufTemp. asFloatBuffer (); mat_ambient_buf.put (mat_ambient); mat_ambient_buf.position (0); bufTemp = ByteBuffer. allocateDirect (mat_diffuse.length * 4); bufTemp. order (ByteOrder. nativeOrder (); mat_diffuse_buf = bufTemp. asFloatBuffer (); mat_diffuse_buf.put (mat_diffuse); mat_diffuse_buf.position (0); bufTemp = ByteBuffer. allocateDirect (mat_specular.length * 4); bufTemp. order (ByteOrder. nativeOrder (); mat_specular_buf = bufTemp. asFloatBuffer (); mat_specular_buf.put (mat_specular); mat_specular_buf.position (0 );}}
Import java. nio. byteBuffer; import java. nio. byteOrder; import java. nio. floatBuffer; import javax. microedition. khronos. opengles. GL10; // calculate the spherical vertex public class Sphere {public void draw (GL10 gl) {floatangleA, angleB; floatcos, sin; floatr1, r2; floath1, h2; floatstep = 30366f; float [] [] v = new float [32] [3]; ByteBuffer vbb; FloatBuffer vBuf; vbb = ByteBuffer. allocateDirect (v. length * v [0]. length * 4); vbb. order (ByteOrder. nativeOrder (); vBuf = vbb. asFloatBuffer (); gl. glableclientstate (GL10.GL _ VERTEX_ARRAY); gl. glableclientstate (GL10.GL _ NORMAL_ARRAY); for (angleA =-90.0f; angleA <90.0f; angleA + = step) {intn = 0; r1 = (float) Math. cos (angleA * Math. PI/180.0); r2 = (float) Math. cos (angleA + step) * Math. PI/180.0); h1 = (float) Math. sin (angleA * Math. PI/180.0); h2 = (float) Math. sin (angleA + step) * Math. PI/180.0); // fixed latitude, 360 degrees rotated to traverse a weft (angleB = 0.0f; angleB <= 360.0f; angleB + = step) {cos = (float) Math. cos (angleB * Math. PI/180.0); sin =-(float) Math. sin (angleB * Math. PI/180.0); v [n] [0] = (r2 * cos); v [n] [1] = (h2 ); v [n] [2] = (r2 * sin); v [n + 1] [0] = (r1 * cos ); v [n + 1] [1] = (h1); v [n + 1] [2] = (r1 * sin); vBuf. put (v [n]); vBuf. put (v [n + 1]); n + = 2; if (n> 31) {vBuf. position (0); gl. glVertexPointer (3, GL10.GL _ FLOAT, 0, vBuf); gl. glNormalPointer (GL10.GL _ FLOAT, 0, vBuf); gl. glDrawArrays (GL10.GL _ TRIANGLE_STRIP, 0, n); n = 0; angleB-= step ;}} vBuf. position (0); gl. glVertexPointer (3, GL10.GL _ FLOAT, 0, vBuf); gl. glNormalPointer (GL10.GL _ FLOAT, 0, vBuf); gl. glDrawArrays (GL10.GL _ TRIANGLE_STRIP, 0, n);} gl. glDisableClientState (GL10.GL _ VERTEX_ARRAY); gl. glDisableClientState (GL10.GL _ NORMAL_ARRAY );}}

import android.content.Context;import android.opengl.GLSurfaceView;import android.view.MotionEvent;public class OpenGLView extends GLSurfaceView {private OpenGLRenderer4 mRenderer;private float mDownX = 0.0f;private float mDownY = 0.0f;public OpenGLView(Context context) {super(context);mRenderer = new OpenGLRenderer4();this.setRenderer(mRenderer);}@Overridepublic boolean onTouchEvent(MotionEvent event) {int action = event.getActionMasked();switch (action) {case MotionEvent.ACTION_DOWN:mDownX = event.getX();mDownY = event.getY();return true;case MotionEvent.ACTION_UP:return true;case MotionEvent.ACTION_MOVE:float mX = event.getX();float mY = event.getY();mRenderer.mLightX += (mX-mDownX)/10;mRenderer.mLightY -= (mY-mDownY)/10;mDownX = mX;mDownY = mY;return true;default:return super.onTouchEvent(event);}}}

Import android. OS. bundle; import android. app. activity; import android. view. window; import android. view. windowManager; public class MainActivity extends Activity {private OpenGLView mOpenGLView; @ Overrideprotected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); // go to the title bar requestWindowFeature (Window. FEATURE_NO_TITLE); // sets full screen getWindow (). setFlags (WindowManager. layoutParams. FLAG_FULLSCREEN, WindowManager. layoutParams. FLAG_FULLSCREEN); mOpenGLView = new OpenGLView (this); setContentView (mOpenGLView );}}

> Step = 30366f

Step = 2.0f

We will discuss the lighting effect later.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.