1 | /* |
2 | * Copyright (C) 2009 Pierre H�bert <pierrox@pierrox.net> |
3 | * http://www.pierrox.net/mcompass/ |
4 | * |
5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
6 | * you may not use this file except in compliance with the License. |
7 | * You may obtain a copy of the License at |
8 | * |
9 | * http://www.apache.org/licenses/LICENSE-2.0 |
10 | * |
11 | * Unless required by applicable law or agreed to in writing, software |
12 | * distributed under the License is distributed on an "AS IS" BASIS, |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 | * See the License for the specific language governing permissions and |
15 | * limitations under the License. |
16 | */ |
17 | |
18 | package net.pierrox.mcompass; |
19 | |
20 | import java.nio.ByteBuffer; |
21 | import java.nio.ByteOrder; |
22 | import java.nio.IntBuffer; |
23 | |
24 | import javax.microedition.khronos.opengles.GL10; |
25 | |
26 | import android.graphics.Bitmap; |
27 | import android.graphics.Canvas; |
28 | import android.graphics.LinearGradient; |
29 | import android.graphics.Paint; |
30 | import android.graphics.Path; |
31 | import android.graphics.RadialGradient; |
32 | import android.graphics.Shader; |
33 | |
34 | public class Turntable { |
35 | private static final int DETAIL_X[]={ 15, 25, 30 }; |
36 | private static final int DETAIL_Y[]={ 3, 6, 6 }; |
37 | private static final int RING_HEIGHT[]={ 2, 3, 3}; |
38 | |
39 | private static final int TEXTURE_RING=0; |
40 | private static final int TEXTURE_DIAL=1; |
41 | |
42 | private static final String[] CARDINAL_POINTS={ "N", "W", "S", "E" }; |
43 | |
44 | // preference values |
45 | private int mDetailsLevel; |
46 | private boolean mReversedRing; |
47 | |
48 | private int[] mTextures; |
49 | |
50 | private IntBuffer mRingVertexBuffer; |
51 | private IntBuffer mRingNormalBuffer; |
52 | private IntBuffer mRingTexCoordBuffer; |
53 | private ByteBuffer mRingIndexBuffer; |
54 | |
55 | private IntBuffer mDialVertexBuffer; |
56 | private IntBuffer mDialNormalBuffer; |
57 | private IntBuffer mDialTexCoordBuffer; |
58 | private ByteBuffer mDialIndexBuffer; |
59 | |
60 | private IntBuffer mCapVertexBuffer; |
61 | private ByteBuffer mCapIndexBuffer; |
62 | |
63 | private boolean mNeedObjectsUpdate; |
64 | private boolean mNeedTextureUpdate; |
65 | |
66 | |
67 | public Turntable() { |
68 | mDetailsLevel=0; |
69 | mReversedRing=false; |
70 | |
71 | // initially both objects and textures need to be built |
72 | mNeedObjectsUpdate=true; |
73 | mNeedTextureUpdate=true; |
74 | } |
75 | |
76 | private void buildObjects() { |
77 | buildRingObject(); |
78 | buildCapObject(); |
79 | buildDialObject(); |
80 | |
81 | mNeedObjectsUpdate=false; |
82 | } |
83 | |
84 | void buildRingObject() { |
85 | // build vertices |
86 | int dx=DETAIL_X[mDetailsLevel]; |
87 | int dy=DETAIL_Y[mDetailsLevel]; |
88 | int rh=RING_HEIGHT[mDetailsLevel]; |
89 | |
90 | int vertices[]=new int[((dx+1)*(rh+1))*3]; |
91 | int normals[]=new int[((dx+1)*(rh+1))*3]; |
92 | int n=0; |
93 | for(int i=0; i<=dx; i++) { |
94 | for(int j=0; j<=rh; j++) { |
95 | double a = i*(Math.PI*2)/dx; |
96 | double b = j*Math.PI/(dy*2); |
97 | |
98 | double x = Math.sin(a)*Math.cos(b); |
99 | double y = -Math.sin(b); |
100 | double z = Math.cos(a)*Math.cos(b); |
101 | |
102 | vertices[n] = (int) (x*65536); |
103 | vertices[n+1] = (int) (y*65536); |
104 | vertices[n+2] = (int) (z*65536); |
105 | normals[n] = vertices[n]; |
106 | normals[n+1] = vertices[n+1]; |
107 | normals[n+2] = vertices[n+2]; |
108 | n+=3; |
109 | } |
110 | } |
111 | |
112 | // build textures coordinates |
113 | int texCoords[]=new int[(dx+1)*(rh+1)*2]; |
114 | n=0; |
115 | for(int i=0; i<=dx; i++) { |
116 | for(int j=0; j<=rh; j++) { |
117 | texCoords[n++] = (i<<16)/dx; |
118 | texCoords[n++] = (j<<16)/rh; |
119 | } |
120 | } |
121 | |
122 | // build indices |
123 | byte indices[]=new byte[dx*rh*3*2]; |
124 | n=0; |
125 | for(int i=0; i<dx; i++) { |
126 | for(int j=0; j<rh; j++) { |
127 | byte p0=(byte) ((rh+1)*i+j); |
128 | indices[n++]=p0; |
129 | indices[n++]=(byte) (p0+rh+1); |
130 | indices[n++]=(byte) (p0+1); |
131 | |
132 | indices[n++]=(byte) (p0+rh+1); |
133 | indices[n++]=(byte) (p0+rh+2); |
134 | indices[n++]=(byte) (p0+1); |
135 | } |
136 | } |
137 | |
138 | ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4); |
139 | vbb.order(ByteOrder.nativeOrder()); |
140 | mRingVertexBuffer = vbb.asIntBuffer(); |
141 | mRingVertexBuffer.put(vertices); |
142 | mRingVertexBuffer.position(0); |
143 | |
144 | ByteBuffer nbb = ByteBuffer.allocateDirect(normals.length*4); |
145 | nbb.order(ByteOrder.nativeOrder()); |
146 | mRingNormalBuffer = nbb.asIntBuffer(); |
147 | mRingNormalBuffer.put(normals); |
148 | mRingNormalBuffer.position(0); |
149 | |
150 | mRingIndexBuffer = ByteBuffer.allocateDirect(indices.length); |
151 | mRingIndexBuffer.put(indices); |
152 | mRingIndexBuffer.position(0); |
153 | |
154 | ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length*4); |
155 | tbb.order(ByteOrder.nativeOrder()); |
156 | mRingTexCoordBuffer = tbb.asIntBuffer(); |
157 | mRingTexCoordBuffer.put(texCoords); |
158 | mRingTexCoordBuffer.position(0); |
159 | } |
160 | |
161 | void buildCapObject() { |
162 | int dx=DETAIL_X[mDetailsLevel]; |
163 | int dy=DETAIL_Y[mDetailsLevel]; |
164 | int rh=RING_HEIGHT[mDetailsLevel]; |
165 | |
166 | int h=dy-rh; |
167 | |
168 | // build vertices |
169 | int vertices[]=new int[((dx+1)*(h+1))*3]; |
170 | int n=0; |
171 | for(int i=0; i<=dx; i++) { |
172 | for(int j=rh; j<=dy; j++) { |
173 | double a = i*(Math.PI*2)/dx; |
174 | double b = j*Math.PI/(dy*2); |
175 | |
176 | double x = Math.sin(a)*Math.cos(b); |
177 | double y = -Math.sin(b); |
178 | double z = Math.cos(a)*Math.cos(b); |
179 | |
180 | vertices[n++] = (int) (x*65536); |
181 | vertices[n++] = (int) (y*65536); |
182 | vertices[n++] = (int) (z*65536); |
183 | } |
184 | } |
185 | |
186 | // build indices |
187 | byte indices[]=new byte[dx*h*3*2]; |
188 | n=0; |
189 | for(int i=0; i<dx; i++) { |
190 | for(int j=0; j<h; j++) { |
191 | byte p0=(byte) ((h+1)*i+j); |
192 | indices[n++]=p0; |
193 | indices[n++]=(byte) (p0+h+1); |
194 | indices[n++]=(byte) (p0+1); |
195 | |
196 | indices[n++]=(byte) (p0+h+1); |
197 | indices[n++]=(byte) (p0+h+2); |
198 | indices[n++]=(byte) (p0+1); |
199 | } |
200 | } |
201 | |
202 | ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4); |
203 | vbb.order(ByteOrder.nativeOrder()); |
204 | mCapVertexBuffer = vbb.asIntBuffer(); |
205 | mCapVertexBuffer.put(vertices); |
206 | mCapVertexBuffer.position(0); |
207 | |
208 | mCapIndexBuffer = ByteBuffer.allocateDirect(indices.length); |
209 | mCapIndexBuffer.put(indices); |
210 | mCapIndexBuffer.position(0); |
211 | } |
212 | |
213 | void buildDialObject() { |
214 | // build vertices |
215 | int dx=DETAIL_X[mDetailsLevel]; |
216 | |
217 | int vertices[]=new int[(dx+2)*3]; |
218 | int normals[]=new int[(dx+2)*3]; |
219 | int n=0; |
220 | // center of the dial |
221 | vertices[n] = 0; |
222 | vertices[n+1] = 0; |
223 | vertices[n+2] = 0; |
224 | normals[n] = 0; |
225 | normals[n+1] = 1<<16; |
226 | normals[n+2] = 0; |
227 | n+=3; |
228 | for(int i=0; i<=dx; i++) { |
229 | double a = i*(Math.PI*2)/dx; |
230 | |
231 | double x = Math.sin(a); |
232 | double z = Math.cos(a); |
233 | |
234 | vertices[n] = (int) (x*65536); |
235 | vertices[n+1] = 0; |
236 | vertices[n+2] = (int) (z*65536); |
237 | normals[n] = 0; |
238 | normals[n+1] = 1<<16; |
239 | normals[n+2] = 0; |
240 | n+=3; |
241 | } |
242 | |
243 | // build textures coordinates |
244 | int texCoords[]=new int[(dx+2)*2]; |
245 | n=0; |
246 | texCoords[n++] = (int)(0.5*65536); |
247 | texCoords[n++] = (int)(0.5*65536); |
248 | for(int i=0; i<=dx; i++) { |
249 | double a = i*(Math.PI*2)/dx; |
250 | |
251 | double x = (Math.sin(a)+1)/2; |
252 | double z = (Math.cos(a)+1)/2; |
253 | |
254 | texCoords[n++] = (int)(x*65536); |
255 | texCoords[n++] = (int)(z*65536); |
256 | } |
257 | |
258 | // build indices |
259 | byte indices[]=new byte[dx+2]; |
260 | n=0; |
261 | for(int i=0; i<=(dx+1); i++) { |
262 | indices[n++]=(byte)i; |
263 | } |
264 | |
265 | ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4); |
266 | vbb.order(ByteOrder.nativeOrder()); |
267 | mDialVertexBuffer = vbb.asIntBuffer(); |
268 | mDialVertexBuffer.put(vertices); |
269 | mDialVertexBuffer.position(0); |
270 | |
271 | ByteBuffer nbb = ByteBuffer.allocateDirect(normals.length*4); |
272 | nbb.order(ByteOrder.nativeOrder()); |
273 | mDialNormalBuffer = nbb.asIntBuffer(); |
274 | mDialNormalBuffer.put(normals); |
275 | mDialNormalBuffer.position(0); |
276 | |
277 | mDialIndexBuffer = ByteBuffer.allocateDirect(indices.length); |
278 | mDialIndexBuffer.put(indices); |
279 | mDialIndexBuffer.position(0); |
280 | |
281 | ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length*4); |
282 | tbb.order(ByteOrder.nativeOrder()); |
283 | mDialTexCoordBuffer = tbb.asIntBuffer(); |
284 | mDialTexCoordBuffer.put(texCoords); |
285 | mDialTexCoordBuffer.position(0); |
286 | } |
287 | |
288 | public void draw(GL10 gl) { |
289 | // rebuild objects or textures if needed |
290 | if(mNeedObjectsUpdate) { |
291 | buildObjects(); |
292 | } |
293 | |
294 | if(mNeedTextureUpdate) { |
295 | buildTextures(gl); |
296 | } |
297 | |
298 | int dx=DETAIL_X[mDetailsLevel]; |
299 | int dy=DETAIL_Y[mDetailsLevel]; |
300 | int rh=RING_HEIGHT[mDetailsLevel]; |
301 | |
302 | gl.glFrontFace(GL10.GL_CW); |
303 | gl.glColor4x(1<<16, 0<<16, 0<<16, 1<<16); |
304 | |
305 | // common parameters for the ring and the dial |
306 | gl.glEnable(GL10.GL_TEXTURE_2D); |
307 | gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); |
308 | |
309 | gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); |
310 | gl.glColor4x(1<<16, 1<<16, 1<<16, 1<<16); |
311 | gl.glScalex(90000, 90000, 90000); |
312 | |
313 | // draw the ring |
314 | gl.glEnableClientState(GL10.GL_NORMAL_ARRAY); |
315 | gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[TEXTURE_RING]); |
316 | gl.glVertexPointer(3, GL10.GL_FIXED, 0, mRingVertexBuffer); |
317 | gl.glNormalPointer(GL10.GL_FIXED, 0, mRingNormalBuffer); |
318 | gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, mRingTexCoordBuffer); |
319 | gl.glDrawElements(GL10.GL_TRIANGLES, dx*rh*6, GL10.GL_UNSIGNED_BYTE, mRingIndexBuffer); |
320 | |
321 | // draw the dial |
322 | gl.glFrontFace(GL10.GL_CCW); |
323 | gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[TEXTURE_DIAL]); |
324 | gl.glVertexPointer(3, GL10.GL_FIXED, 0, mDialVertexBuffer); |
325 | gl.glNormalPointer(GL10.GL_FIXED, 0, mDialNormalBuffer); |
326 | gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, mDialTexCoordBuffer); |
327 | gl.glDrawElements(GL10.GL_TRIANGLE_FAN, dx+2, GL10.GL_UNSIGNED_BYTE, mDialIndexBuffer); |
328 | gl.glDisableClientState(GL10.GL_NORMAL_ARRAY); |
329 | |
330 | // draw the cap |
331 | gl.glFrontFace(GL10.GL_CW); |
332 | gl.glColor4x(0<<16, 0<<16, 0<<16, 1<<16); |
333 | gl.glDisable(GL10.GL_TEXTURE_2D); |
334 | gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); |
335 | gl.glVertexPointer(3, GL10.GL_FIXED, 0, mCapVertexBuffer); |
336 | gl.glDrawElements(GL10.GL_TRIANGLES, dx*(dy-rh)*6, GL10.GL_UNSIGNED_BYTE, mCapIndexBuffer); |
337 | } |
338 | |
339 | void buildTextures(GL10 gl) { |
340 | mTextures=new int[2]; |
341 | |
342 | gl.glGenTextures(2, mTextures, 0); |
343 | |
344 | buildRingTexture(gl); |
345 | buildDialTexture(gl); |
346 | |
347 | mNeedTextureUpdate=false; |
348 | } |
349 | |
350 | void buildRingTexture(GL10 gl) { |
351 | gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[TEXTURE_RING]); |
352 | gl.glPixelStorei(GL10.GL_UNPACK_ALIGNMENT, 1); |
353 | gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); |
354 | gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); |
355 | gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); |
356 | gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); |
357 | |
358 | final int length=512; |
359 | final int height=64; |
360 | Bitmap b=Bitmap.createBitmap(length, height, Bitmap.Config.ARGB_8888); |
361 | b.eraseColor(0xff000000); |
362 | Canvas canvas=new Canvas(b); |
363 | |
364 | Paint p=new Paint(); |
365 | p.setAntiAlias(true); |
366 | |
367 | // draw minor graduations in grey |
368 | /*p.setColor(0xffa0a0a0); |
369 | for(int d=0; d<360; d++) { |
370 | canvas.drawLine(d*2, 0, d*2, 10, p); |
371 | }*/ |
372 | |
373 | // draw medium graduations in white |
374 | p.setColor(0xffffffff); |
375 | for(int d=0; d<360; d+=10) { |
376 | int pos=d*length/360; |
377 | canvas.drawLine(pos, 0, pos, 20, p); |
378 | } |
379 | |
380 | // draw major graduations in red |
381 | p.setColor(0xffff0000); |
382 | for(int d=0; d<360; d+=90) { |
383 | int pos=d*length/360; |
384 | canvas.drawLine(pos, 0, pos, 30, p); |
385 | } |
386 | |
387 | // use center alignment for text |
388 | p.setTextAlign(Paint.Align.CENTER); |
389 | |
390 | // draw minor graduations text |
391 | p.setTextSize(9); |
392 | p.setColor(0xffffffff); |
393 | for(int d=0; d<360; d+=30) { |
394 | // do not draw 0/90/180/270 |
395 | int pos=d*length/360; |
396 | int angle=mReversedRing ? (360+180-d)%360 : 360-d; |
397 | if(d%90!=0) canvas.drawText(Integer.toString(angle), pos, 30, p); |
398 | } |
399 | |
400 | // draw N/O/S/E |
401 | // hack : go till 360, so that "N" is printed at both end of the texture... |
402 | p.setTextSize(20); |
403 | p.setColor(0xffff0000); |
404 | for(int d=0; d<=360; d+=90) { |
405 | int pos=d*length/360; |
406 | if(mReversedRing) { |
407 | canvas.drawText(CARDINAL_POINTS[((d+180)/90)%4], pos, 50, p); |
408 | } else { |
409 | canvas.drawText(CARDINAL_POINTS[(d/90)%4], pos, 50, p); |
410 | } |
411 | } |
412 | |
413 | p.setShader(new LinearGradient(0, 5, 0, 0, 0xff000000, 0xffffffff, Shader.TileMode.CLAMP)); |
414 | canvas.drawRect(0, 0, length, 5, p); |
415 | |
416 | /*BitmapDrawable bd=(BitmapDrawable)mContext.getResources().getDrawable(R.drawable.ruler);*/ |
417 | //GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, b, 0); |
418 | ByteBuffer bb=ByteBuffer.allocate(length*height*4); |
419 | b.copyPixelsToBuffer(bb); |
420 | gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, length, height, 0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, bb); |
421 | } |
422 | |
423 | void buildDialTexture(GL10 gl) { |
424 | int params[]=new int[1]; |
425 | gl.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, params, 0); |
426 | gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[TEXTURE_DIAL]); |
427 | gl.glPixelStorei(GL10.GL_UNPACK_ALIGNMENT, 1); |
428 | gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); |
429 | gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); |
430 | gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); |
431 | gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); |
432 | |
433 | final int radius=256; |
434 | Bitmap b=Bitmap.createBitmap(radius*2, radius*2, Bitmap.Config.ARGB_8888); |
435 | Canvas canvas=new Canvas(b); |
436 | |
437 | Paint p=new Paint(); |
438 | p.setAntiAlias(true); |
439 | |
440 | // external shaded ring |
441 | int colors[]={0xff000000, 0xff000000, 0xffffffff, 0xff000000, 0x00000000}; |
442 | float positions[]={0f, 0.94f, 0.95f, 0.98f, 1.0f}; |
443 | p.setShader(new RadialGradient(radius, radius, radius, colors, positions, Shader.TileMode.CLAMP)); |
444 | canvas.drawCircle(radius, radius, radius, p); |
445 | p.setShader(null); |
446 | |
447 | // build the inner decoration, using two symmetrical paths |
448 | Path pathl=new Path(); |
449 | pathl.moveTo(radius, radius/2); |
450 | pathl.lineTo(radius+20, radius-20); |
451 | pathl.lineTo(radius, radius); |
452 | pathl.close(); |
453 | Path pathr=new Path(); |
454 | pathr.moveTo(radius, radius/2); |
455 | pathr.lineTo(radius-20, radius-20); |
456 | pathr.lineTo(radius, radius); |
457 | pathr.close(); |
458 | canvas.save(); |
459 | for(int i=0; i<4; i++) { |
460 | canvas.rotate((float) (i*90), radius, radius); |
461 | p.setColor(0xff808080); |
462 | canvas.drawPath(pathl, p); |
463 | p.setColor(0xffffffff); |
464 | canvas.drawPath(pathr, p); |
465 | } |
466 | canvas.restore(); |
467 | |
468 | // draw medium graduations in white |
469 | p.setColor(0xffffffff); |
470 | p.setStrokeWidth(2); |
471 | for(int i=0; i<360; i+=10) { |
472 | canvas.save(); |
473 | canvas.rotate(i, radius, radius); |
474 | canvas.drawLine(radius, radius*2, radius, 1.75f*radius, p); |
475 | canvas.restore(); |
476 | } |
477 | |
478 | |
479 | // draw major graduations in red |
480 | p.setColor(0xffff0000); |
481 | p.setStrokeWidth(3); |
482 | for(int i=0; i<360; i+=90) { |
483 | canvas.save(); |
484 | canvas.rotate(i, radius, radius); |
485 | canvas.drawLine(radius, radius*2, radius, 1.70f*radius, p); |
486 | canvas.restore(); |
487 | } |
488 | |
489 | // medium graduation texts |
490 | p.setTextSize(24); |
491 | p.setTextAlign(Paint.Align.CENTER); |
492 | p.setColor(0xffffffff); |
493 | for(int i=0; i<360; i+=30) { |
494 | // do not draw 0/90/180/270 |
495 | if((i%90)!=0) { |
496 | double a = -i*(Math.PI*2)/360; |
497 | float x = (float)(Math.sin(a)*0.7*radius+radius); |
498 | float y = (float)(Math.cos(a)*0.7*radius+radius); |
499 | |
500 | canvas.save(); |
501 | canvas.rotate(i, x, y); |
502 | canvas.drawText(Integer.toString(i), x, y, p); |
503 | canvas.restore(); |
504 | } |
505 | } |
506 | |
507 | // draw N/O/S/E |
508 | p.setTextSize(40); |
509 | p.setColor(0xffff0000); |
510 | for(int i=0; i<360; i+=90) { |
511 | double a = i*(Math.PI*2)/360; |
512 | float x = (float)(Math.sin(a)*0.65*radius+radius); |
513 | float y = (float)(Math.cos(a)*0.65*radius+radius); |
514 | |
515 | canvas.save(); |
516 | canvas.rotate(-i, x, y); |
517 | canvas.drawText(CARDINAL_POINTS[i/90], x, y, p); |
518 | canvas.restore(); |
519 | } |
520 | |
521 | //GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, b, 0); |
522 | ByteBuffer bb=ByteBuffer.allocate(radius*2*radius*2*4); |
523 | b.copyPixelsToBuffer(bb); |
524 | gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, radius*2, radius*2, 0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, bb); |
525 | } |
526 | |
527 | public void setDetailsLevel(int detailsLevel) { |
528 | if(detailsLevel!=mDetailsLevel) { |
529 | mDetailsLevel=detailsLevel; |
530 | mNeedObjectsUpdate=true; |
531 | } |
532 | } |
533 | |
534 | public void setReversedRing(boolean reversedRing) { |
535 | if(reversedRing!=mReversedRing) { |
536 | mReversedRing=reversedRing; |
537 | mNeedTextureUpdate=true; |
538 | } |
539 | } |
540 | } |