Android OpenGL ES Draw Sphere

Source: Internet
Author: User
Tags clear screen cos gety android games

Recently, I started to learn OpenGL drawing because of my interest. This article takes "drawing the sphere" as the point, summarizes the recent study.


> Initial OpenGL ES contact OpenGL starts with Android. As is known to all, Android view is thread insecure and allows only the view to be manipulated in the main thread. However, if we need to implement the complex interface, especially the development of the game, in the main thread to draw a large number of images, it will take a long time, so that the main thread did not respond to user input in a timely manner, even the ANR. So Android offers a Surfaceview class, via a double buffering mechanism (two canvas?). A three-piece canvas? ), allowing the user to operate the canvas from a non-main thread, implementing an "asynchronous" refresh of the view. The canvas class offers a number of drawing methods: Drawpoint (...) Drawcircle (...) Drawbitmap (...) DrawRect (...) DrawText (...) DrawOval (...)

Then, if you want to achieve more complex effects (such as 3D), canvas is difficult. As you know, most Android games are now implemented with OpenGL.

What is OpenGL's sacred side? In fact, the final image (either 2D or 3D) is displayed on the display, so the final operation must be done on a 2D display memory. And OpenGL is a lot of ways to help us define the spatial stereoscopic model, and then through the various parameters we entered to calculate the mapping matrix, the final display screen on the effect.

OpenGL ES (OpenGL for Embedded Systems) is a special OpenGL API subset dedicated to embedded platforms such as mobile phones. The simple understanding is that it is developed specifically for the "low-end" environment. Cut a lot of unnecessary methods, left the most basic.


> Using OpenGL ES paint OpenGL ES provides two ways to draw space geometry. 1. gldrawarrays (int mode, int first, int count), 2. gldrawelements (int mode, int count, int type, Buffer indices), parameter mode has the following values: Gl_points, Gl_line_strip, Gl_line_loo P, Gl_lines, Gl_triangles, Gl_triangle_strip, Gl_triangle_fan. Draw points, draw lines, draw triangles! That's all! We believe that any spatial graph can be represented by dots, lines, or triangles. 3. Glvertexpointer (...) Defines all vertex methods for the geometry. When this method is called, the Gldrawarrays,gldrawelements method will draw the graph according to the vertex.
Because we're going to draw a sphere next, it's done by drawing a lot of triangles (sounds interesting). So let's take a quick look at the three patterns of the triangle:
According to the order of the vertices, gl_triangles the triangle by three vertices, and gl_triangl_strip always makes the triangle with the last three vertices, Gl_triangle_fan is centered on the first vertex, and the subsequent vertices form triangles respectively. We then use the Gl_triangle_strip pattern to draw the sphere.
> Using triangles to form space spheres what we're using here is the idea of extreme approximation. Think of that year, Zuchongzhi not also use this kind of thought to calculate Pi Pi. When the number of sides of a positive polygon is plenty, it looks like a circle!
So, we also think that when the regular polyhedron number of sides is enough, it looks like a ball!
Well, thought is there, but ultimately we don't draw by drawing regular polyhedron. Because it seems, it's more troublesome to use regular polyhedron to cut a ball. If using the longitude cutting method, it is much easier to calculate!
About two meridians, the upper and lower parallels form a square (approximate). A square can be seen as a two-triangle composition. The yellow arrow on the way represents the vertex order used when drawing with Gl_triangle_strip mode. This cutting method looks a lot clearer, and the crossbar loops through all the vertices. The key is: How to calculate the vertex coordinates of the sphere? (x, y, z)
> spherical vertex coordinate calculation first, we confirm two traverse direction: the first layer: starting from the negative direction of the y-axis, increasing the angle until the y-axis is in a positive direction. (Clock 6 point->5 Point->4 Point->3 Point->2 Point->1 Point->12 Point) second layer: fixed y value, with Y axis as rotation axis, 360 degrees rotation. You can traverse all vertices. For example, a angle increments, b angle makes a 360 degree change.
For example, the point on the free-kick surface, three-dimensional coordinates (x0, y0, z0) are calculated: (R is the sphere radius) x0 = R * COS (a) * sin (b); y0 = R * Sin (a); z0 = R * COS (a) * cos (b);
> Source The following part of the reference or is copied in: http://blog.csdn.net/wuzongpo/article/details/7230285
The general steps for using OpenGL ES drawing are: 1, Get Egldisplay object 2, initialize connection to Egldisplay 3, Get Eglconfig object 4, create Eglcontext object 5, create Eglsurface instance 6, Connect Eglcontext with EGLSurface7, use GL instruction to draw 8, disconnect release Eglcontext object 9, delete EGLSurface10, delete EGLContext11, terminate connection to Egldisplay
Android Glsurfaceview class, the OpenGL Api is a layer of encapsulation. Help us manage Display,context,surface. We just need to implement the Android.opengl.GLSurfaceView.Renderer interface.
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 implements Renderer {// Ambient light private final float[] Mat_ambient = {0.2f, 0.3f, 0.4f, 1.0f};p rivate floatbuffer mat_ambient_buf;//parallel incident light private FINA L float[] Mat_diffuse = {0.4f, 0.6f, 0.8f, 1.0f};p rivate floatbuffer mat_diffuse_buf;//highlighted area private final float[] Mat_sp  Ecular = {0.2f * 0.4f, 0.2f * 0.6f, 0.2f * 0.8f, 1.0f};p rivate floatbuffer mat_specular_buf;private Sphere msphere = new Sphere ();p ublic volatile float mlightx = 10f;public volatile float mlighty = 10f;public volatile float mlightz = 10f; @Ove rridepublic void Ondrawframe (GL10 gl) {//clear screen and depth cache Gl.glclear (Gl10.gl_color_buffer_bit | Gl10.gl_depth_buffer_bit);//Resets the current model observation matrix gl.glloadidentity (); gl.glenable (gl10.gl_lighting); Gl.glenable (GL10.GL_    LIGHT0);Material GL.GLMATERIALFV (Gl10.gl_front_and_back, gl10.gl_ambient, mat_ambient_buf);    GL.GLMATERIALFV (Gl10.gl_front_and_back, Gl10.gl_diffuse, mat_diffuse_buf);    GL.GLMATERIALFV (Gl10.gl_front_and_back, Gl10.gl_specular, mat_specular_buf);        Mirror index 0~128 The smaller the coarser the Gl.glmaterialf (Gl10.gl_front_and_back, gl10.gl_shininess, 96.0f); Light source position 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 Output screen size gl.glviewport (0, 0, width, height);//settings Projection matrix Gl.glmatrixmode (gl10.gl_projection);//Reset projection matrix gl.glloadidentity ();//Set viewport size//GL.GLFRUSTUMF (0, width, 0, height, 0.1f, 100.0f); GLu.gluperspective (GL, 90.0f, (float) width/height, 0.1f, 50.0f);//select Model observation Matrix Gl.glmatrixmode (Gl10.gl_modelview);// Reset Model Observation Matrix gl.glloadidentity ();} @Overridepublic void onsurfacecreated (GL10 gl, EGLConfig arg1) {//Correction of perspective Gl.glhint (Gl10.gl_perspective_correction_ HINT, gl10.gl_fastest);//Background: Black Gl.glclearcolor (0, 0.0f, 0.0f, 0.0f);//Start Shadow Smoothing Gl.glshademodel (Gl10.gl_smooth);// Reset Depth Cache GL.GLCLEARDEPTHF (1.0f);//Start Depth Test gl.glenable (gl10.gl_depth_test);//depth test of the type Gl.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;//Compute spherical vertex public class Sphere {public void Draw (GL10 gl) {Floatanglea, Angleb;    Floatcos, sin;    FLOATR1, R2;    Floath1, H2;    Floatstep = 30.0f;    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.glenableclientstate (Gl10.gl_vertex_array);        Gl.glenableclientstate (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 degree rotation traverse a parallel for (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 + Note] = (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.0 F;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);// Set full screen GetWindow (). SetFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN ); Mopenglview = new Openglview (this); Setcontentview (Mopenglview);}}

> Step = 30.0f

Step = 2.0f

As for the lighting effect, we'll discuss it later.

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.