The key for release to market has been expired. Needs new key and package name.
[0xbench:0xbench.git] / src / com / nea / nehe / lesson16 / Cube.java
1 /*
2  * Authors Name: Jeff Molofee (NeHe)
3  *
4  * Disclaimer:
5  * This program may crash your system or run poorly depending on your
6  * hardware.  The program and code contained in this archive was scanned
7  * for virii and has passed all test before it was put online.  If you
8  * use this code in project of your own, send a shout out to the author!
9  *
10  * Ported to Android by INsanityDesign:
11  *  http://insanitydesign.com/wp/projects/nehe-android-ports/
12  */
13
14 package com.nea.nehe.lesson16;
15
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.nio.ByteBuffer;
19 import java.nio.ByteOrder;
20 import java.nio.FloatBuffer;
21
22 import javax.microedition.khronos.opengles.GL10;
23 import javax.microedition.khronos.opengles.GL11;
24
25 import android.content.Context;
26 import android.graphics.Bitmap;
27 import android.graphics.BitmapFactory;
28 import android.opengl.GLUtils;
29
30 /**
31  * This class is an object representation of
32  * a Cube containing the vertex information,
33  * texture coordinates, the vertex indices
34  * and drawing functionality, which is called
35  * by the renderer.
36  *
37  * @author Savas Ziplies (nea/INsanityDesign)
38  */
39 public class Cube {
40
41     /** The buffer holding the vertices */
42     private FloatBuffer vertexBuffer;
43     /** The buffer holding the texture coordinates */
44     private FloatBuffer textureBuffer;
45     /** The buffer holding the indices */
46     private ByteBuffer indexBuffer;
47     /** The buffer holding the normals */
48     private FloatBuffer normalBuffer;
49
50     /** Our texture pointer */
51     private int[] textures = new int[3];
52
53     /** The initial vertex definition */
54     private float vertices[] = {
55         //Vertices according to faces
56         -1.0f, -1.0f, 1.0f, //v0
57         1.0f, -1.0f, 1.0f,     //v1
58         -1.0f, 1.0f, 1.0f,     //v2
59         1.0f, 1.0f, 1.0f,     //v3
60
61         1.0f, -1.0f, 1.0f,     // ...
62         1.0f, -1.0f, -1.0f,
63         1.0f, 1.0f, 1.0f,
64         1.0f, 1.0f, -1.0f,
65
66         1.0f, -1.0f, -1.0f,
67         -1.0f, -1.0f, -1.0f,
68         1.0f, 1.0f, -1.0f,
69         -1.0f, 1.0f, -1.0f,
70
71         -1.0f, -1.0f, -1.0f,
72         -1.0f, -1.0f, 1.0f,
73         -1.0f, 1.0f, -1.0f,
74         -1.0f, 1.0f, 1.0f,
75
76         -1.0f, -1.0f, -1.0f,
77         1.0f, -1.0f, -1.0f,
78         -1.0f, -1.0f, 1.0f,
79         1.0f, -1.0f, 1.0f,
80
81         -1.0f, 1.0f, 1.0f,
82         1.0f, 1.0f, 1.0f,
83         -1.0f, 1.0f, -1.0f,
84         1.0f, 1.0f, -1.0f,
85     };
86
87     /**
88      * The initial normals for the lighting calculations
89      *
90      * The normals are not necessarily correct from a
91      * real world perspective, as I am too lazy to write
92      * these all on my own. But you get the idea and see
93      * what I mean if you run the demo.
94      */
95     private float normals[] = {
96         // Normals
97         0.0f, 0.0f, 1.0f,
98         0.0f, 0.0f, -1.0f,
99         0.0f, 1.0f, 0.0f,
100         0.0f, -1.0f, 0.0f,
101
102         0.0f, 0.0f, 1.0f,
103         0.0f, 0.0f, -1.0f,
104         0.0f, 1.0f, 0.0f,
105         0.0f, -1.0f, 0.0f,
106
107         0.0f, 0.0f, 1.0f,
108         0.0f, 0.0f, -1.0f,
109         0.0f, 1.0f, 0.0f,
110         0.0f, -1.0f, 0.0f,
111
112         0.0f, 0.0f, 1.0f,
113         0.0f, 0.0f, -1.0f,
114         0.0f, 1.0f, 0.0f,
115         0.0f, -1.0f, 0.0f,
116
117         0.0f, 0.0f, 1.0f,
118         0.0f, 0.0f, -1.0f,
119         0.0f, 1.0f, 0.0f,
120         0.0f, -1.0f, 0.0f,
121
122         0.0f, 0.0f, 1.0f,
123         0.0f, 0.0f, -1.0f,
124         0.0f, 1.0f, 0.0f,
125         0.0f, -1.0f, 0.0f,
126     };
127
128     /** The initial texture coordinates (u, v) */
129     private float texture[] = {
130         //Mapping coordinates for the vertices
131         0.0f, 0.0f,
132         0.0f, 1.0f,
133         1.0f, 0.0f,
134         1.0f, 1.0f,
135
136         0.0f, 0.0f,
137         0.0f, 1.0f,
138         1.0f, 0.0f,
139         1.0f, 1.0f,
140
141         0.0f, 0.0f,
142         0.0f, 1.0f,
143         1.0f, 0.0f,
144         1.0f, 1.0f,
145
146         0.0f, 0.0f,
147         0.0f, 1.0f,
148         1.0f, 0.0f,
149         1.0f, 1.0f,
150
151         0.0f, 0.0f,
152         0.0f, 1.0f,
153         1.0f, 0.0f,
154         1.0f, 1.0f,
155
156         0.0f, 0.0f,
157         0.0f, 1.0f,
158         1.0f, 0.0f,
159         1.0f, 1.0f,
160     };
161
162     /** The initial indices definition */
163     private byte indices[] = {
164         // Faces definition
165         0, 1, 3, 0, 3, 2,         // Face front
166         4, 5, 7, 4, 7, 6,         // Face right
167         8, 9, 11, 8, 11, 10,     // ...
168         12, 13, 15, 12, 15, 14,
169         16, 17, 19, 16, 19, 18,
170         20, 21, 23, 20, 23, 22,
171     };
172
173     /**
174      * The Cube constructor.
175      *
176      * Initiate the buffers.
177      */
178     public Cube() {
179         //
180         ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
181         byteBuf.order(ByteOrder.nativeOrder());
182         vertexBuffer = byteBuf.asFloatBuffer();
183         vertexBuffer.put(vertices);
184         vertexBuffer.position(0);
185
186         //
187         byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
188         byteBuf.order(ByteOrder.nativeOrder());
189         textureBuffer = byteBuf.asFloatBuffer();
190         textureBuffer.put(texture);
191         textureBuffer.position(0);
192
193         //
194         byteBuf = ByteBuffer.allocateDirect(normals.length * 4);
195         byteBuf.order(ByteOrder.nativeOrder());
196         normalBuffer = byteBuf.asFloatBuffer();
197         normalBuffer.put(normals);
198         normalBuffer.position(0);
199
200         //
201         indexBuffer = ByteBuffer.allocateDirect(indices.length);
202         indexBuffer.put(indices);
203         indexBuffer.position(0);
204     }
205
206     /**
207      * The object own drawing function.
208      * Called from the renderer to redraw this instance
209      * with possible changes in values.
210      *
211      * @param gl - The GL Context
212      * @param filter - Which texture filter to be used
213      */
214     public void draw(GL10 gl, int filter) {
215         //Bind the texture according to the set texture filter
216         gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[filter]);
217
218         //Enable the vertex, texture and normal state
219         gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
220         gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
221         gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
222
223         //Set the face rotation
224         gl.glFrontFace(GL10.GL_CCW);
225
226         //Point to our buffers
227         gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
228         gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
229         gl.glNormalPointer(GL10.GL_FLOAT, 0, normalBuffer);
230
231         //Draw the vertices as triangles, based on the Index Buffer information
232         gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_BYTE, indexBuffer);
233
234         //Disable the client state before leaving
235         gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
236         gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
237         gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
238     }
239
240     /**
241      * Load the textures
242      *
243      * @param gl - The GL Context
244      * @param context - The Activity context
245      */
246     public void loadGLTexture(GL10 gl, Context context) {
247         //Get the texture from the Android resource directory
248         InputStream is = context.getResources().openRawResource(org.zeroxlab.zeroxbenchmark.R.drawable.crate);
249         Bitmap bitmap = null;
250         try {
251             //BitmapFactory is an Android graphics utility for images
252             bitmap = BitmapFactory.decodeStream(is);
253
254         } finally {
255             //Always clear and close
256             try {
257                 is.close();
258                 is = null;
259             } catch (IOException e) {
260             }
261         }
262
263         //Generate there texture pointer
264         gl.glGenTextures(3, textures, 0);
265
266         //Create Nearest Filtered Texture and bind it to texture 0
267         gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
268         gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);
269         gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
270         GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
271
272         //Create Linear Filtered Texture and bind it to texture 1
273         gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[1]);
274         gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
275         gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
276         GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
277
278         //Create mipmapped textures and bind it to texture 2
279         gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[2]);
280         gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
281         gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR_MIPMAP_NEAREST);
282         /*
283          * This is a change to the original tutorial, as buildMipMap does not exist anymore
284          * in the Android SDK.
285          *
286          * We check if the GL context is version 1.1 and generate MipMaps by flag.
287          * Otherwise we call our own buildMipMap implementation
288          */
289         if(gl instanceof GL11) {
290             gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_GENERATE_MIPMAP, GL11.GL_TRUE);
291             GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
292
293         //
294         } else {
295             buildMipmap(gl, bitmap);
296         }
297
298         //Clean up
299         bitmap.recycle();
300     }
301
302     /**
303      * Our own MipMap generation implementation.
304      * Scale the original bitmap down, always by factor two,
305      * and set it as new mipmap level.
306      *
307      * Thanks to Mike Miller (with minor changes)!
308      *
309      * @param gl - The GL Context
310      * @param bitmap - The bitmap to mipmap
311      */
312     private void buildMipmap(GL10 gl, Bitmap bitmap) {
313         //
314         int level = 0;
315         //
316         int height = bitmap.getHeight();
317         int width = bitmap.getWidth();
318
319         //
320         while(height >= 1 || width >= 1) {
321             //First of all, generate the texture from our bitmap and set it to the according level
322             GLUtils.texImage2D(GL10.GL_TEXTURE_2D, level, bitmap, 0);
323
324             //
325             if(height == 1 || width == 1) {
326                 break;
327             }
328
329             //Increase the mipmap level
330             level++;
331
332             //
333             height /= 2;
334             width /= 2;
335             Bitmap bitmap2 = Bitmap.createScaledBitmap(bitmap, width, height, true);
336
337             //Clean up
338             bitmap.recycle();
339             bitmap = bitmap2;
340         }
341     }
342 }
343