`
antkingwei
  • 浏览: 42036 次
  • 性别: Icon_minigender_1
  • 来自: 日照
社区版块
存档分类
最新评论

Android 3D壁纸开发设计

阅读更多

其中一个画面

希望能给需要得人一点帮助,这个触屏可以改变壁纸映射,

JAVA与Androdi交流群150086842

 

这个是主类

package com.android.first3Dlive;


import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import android.view.MotionEvent;

public class First3DLive extends GLWallpaperService{
   private GLRender1 mRender;
 
   public Engine onCreateEngine(){
	   
	   if(mRender == null){
		   mRender = new GLRender1();
		 
	   }
	   
	   return new First3DLiveEngine(this);
	 
   }
  class First3DLiveEngine extends GLWallpaperService.GLEngine{
   public First3DLiveEngine(Context context){
	  
	   setRenderer(mRender);
	   GLImage.load(context.getResources());
	   setRenderMode(RENDERMODE_CONTINUOUSLY);
	   
   }
   public void onTouchEvent(MotionEvent event){
	   mRender.onTouchEvent(event);  
   }
   
}
}
class GLImage

{
	public static Bitmap mt[] = new Bitmap[6];
	//public static Bitmap mBitmap=null;
	public static void load(Resources resources)
	{
		// mBitmap = BitmapFactory.decodeResource(resources, R.drawable.antking1);
		mt[0] = BitmapFactory.decodeResource(resources, R.drawable.antking);
		mt[1] = BitmapFactory.decodeResource(resources, R.drawable.antking1);
		mt[2] = BitmapFactory.decodeResource(resources, R.drawable.antking2);
		mt[3] = BitmapFactory.decodeResource(resources, R.drawable.antking3);
		mt[4] = BitmapFactory.decodeResource(resources, R.drawable.antking4);
		mt[5] = BitmapFactory.decodeResource(resources, R.drawable.xiaofei);
		
	}
}

 package com.android.first3Dlive;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLU;
import android.opengl.GLUtils;

import android.view.MotionEvent;

public class GLRender1 implements GLWallpaperService.Renderer
{
	private  final  IntBuffer  mVertexBuffer;
	private final IntBuffer nBuffer;
	float xrot, yrot, zrot;
	int[] texture;
	int i=0;
	boolean key= true;
	int one =0x10000;
	 
	public GLRender1(){	
    int texCoord[]={
		one,0,0,0,0,one,one,one,	
		0,0,0,one,one,one,one,0,
		one,one,one,0,0,0,0,one,
		0,one,one,one,one,0,0,0,
		0,0,0,one,one,one,one,0,
		one,0,0,0,0,one,one,one,	
		};
	int vertices[]={
			-one,-one,one,
			one,-one,one,
			one,one,one,
			-one,one,one,
			
			-one,-one,-one,
			-one,one,-one,
			one,one,-one,
			one,-one,-one,
			
			-one,one,-one,
			-one,one,one,
			one,one,one,
			one,one,-one,
			
			-one,-one,-one,
			one,-one,-one,
			one,-one,one,
			-one,-one,one,
			
			one,-one,-one,
			one,one,-one,
			one,one,one,
			one,-one,one,
			
			-one,-one,-one,
			-one,-one,one,
			-one,one,one,
			-one,one,-one,
			
	};


	 ByteBuffer  vbb  =  ByteBuffer.allocateDirect(vertices.length  *  4);
     vbb.order(ByteOrder.nativeOrder());
     mVertexBuffer  =  vbb.asIntBuffer();
     mVertexBuffer.put(vertices);
     mVertexBuffer.position(0); 
     ByteBuffer  v  =  ByteBuffer.allocateDirect(texCoord.length *4);
     v.order(ByteOrder.nativeOrder());
     nBuffer  =  v.asIntBuffer();
     nBuffer.put(texCoord);
     nBuffer.position(0);
 
     
     
	}



	ByteBuffer indices = ByteBuffer.wrap(new byte[]{
			0,1,3,2,
			4,5,7,6,
		    8,9,11,10,
		    12,13,15,14,
			16,17,19,18,
			20,21,23,22,
		
			
	});
	@Override
	public void onDrawFrame(GL10 gl)
	{
		// 清除屏幕和深度缓存
		gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
		// 重置当前的模型观察矩阵
		gl.glLoadIdentity();
		//gl.glEnable(GL10.GL_LIGHTING);
		gl.glTranslatef(0.0f, 0.0f, -5.0f);
		
		//设置3个方向的旋转
		gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f);
		gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f);
		gl.glRotatef(zrot, 0.0f, 0.0f, 1.0f);

		// 绑定纹理
		gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[i]);
		
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		
		//纹理和四边形对应的顶点
		//gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, nBuffer);
		gl.glVertexPointer(3, GL10.GL_FIXED, 0, mVertexBuffer);
		gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, nBuffer);

		//绘制
		//for(int i=0;i<6;i++){
		//	gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,i*4, 4);
		//}
		gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 24,  GL10.GL_UNSIGNED_BYTE, indices);

	    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
	    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
	    
	    xrot+=0.3f;
	    yrot+=0.6f; 
	    zrot+=0.4f; 
		//if(key){
		//	gl.glEnable(GL10.GL_BLEND);
		//	gl.glDisable(GL10.GL_DEPTH_TEST);
		//}else{
		//gl.glDisable(GL10.GL_BLEND);
			//gl.glEnable(GL10.GL_DEPTH_TEST);
		//}
	}


	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height)
	{
		float ratio = (float) width /height;
		//设置OpenGL场景的大小
		gl.glViewport(-100,-100,width+200, height+200);
		//设置投影矩阵
		gl.glMatrixMode(GL10.GL_PROJECTION);
		//重置投影矩阵
		gl.glLoadIdentity();
		// 设置视口的大小
		gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
		// 选择模型观察矩阵
		
		gl.glMatrixMode(GL10.GL_MODELVIEW);	
		// 重置模型观察矩阵
		gl.glLoadIdentity();
		
		
		
	}

	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config)
	{
		// 黑色背景
		gl.glClearColor(0.4f, 0.6f, 0.5f, 0.3f);
		
		gl.glEnable(GL10.GL_CULL_FACE);
		// 启用阴影平滑
		gl.glShadeModel(GL10.GL_SMOOTH);
		// 启用深度测试
		gl.glEnable(GL10.GL_DEPTH_TEST);
		
		//启用纹理映射
		gl.glClearDepthf(1.0f);
		//深度测试的类型
		gl.glDepthFunc(GL10.GL_LEQUAL);
		//精细的透视修正
		gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
		 float lightAmbient[] = new float[] { 0.2f, 0.2f, 0.2f, 1 };
          float lightDiffuse[] = new float[] { 1, 1, 1, 1 }; 
          float[] lightPos = new float[] { 1, 1, 1, 1 }; 
          gl.glEnable(GL10.GL_LIGHTING); 
          gl.glEnable(GL10.GL_LIGHT0); 
          gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbient, 0); 
           gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuse, 0);
           gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPos, 0);    
// 立方体的材质,这可以决定光照在它上面的效果 漫反射还是镜面反射。 58        59 
          float matAmbient[] = new float[] { 1, 1, 1, 1 }; 
          float matDiffuse[] = new float[] { 1, 1, 1, 1 }; 
        gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, matAmbient, 0);   
        gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, matDiffuse, 0);
    // 设置我们需要的各种参数 69      
		//允许2D贴图,纹理
		gl.glEnable(GL10.GL_TEXTURE_2D);
		
		IntBuffer intBuffer = IntBuffer.allocate(6);
		// 创建纹理
		gl.glGenTextures(6, intBuffer);
		//loadTexture(gl,context);
		texture = intBuffer.array();
		// 设置要使用的纹理
		gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]);		
		GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0,GLImage.mt[0], 0);
		gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
		gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
		
		gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[1]);		
		GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0,GLImage.mt[1], 0);
		gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
		gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
		
		gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[2]);		
		GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0,GLImage.mt[2], 0);
		gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
		gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
		
		gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[3]);		
		GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0,GLImage.mt[3], 0);
		gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
		gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
		
		gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[4]);		
		GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0,GLImage.mt[4], 0);
		gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
		gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
		
		gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[5]);		
		GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0,GLImage.mt[5], 0);
		gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
		gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
		gl.glEnable(GL10.GL_LIGHT0);
		
	}public boolean onTouchEvent(MotionEvent event){
		if(event.getAction()==event.ACTION_UP){
			i++;
			if(i>=6){
				i=0;
			}
		}
		if(event.getAction()==event.ACTION_MOVE){
			key=!key;
		}
		return false;
		
	}
	

}

 package com.android.first3Dlive;

import java.io.Writer;   
import java.util.ArrayList;   
   
import javax.microedition.khronos.egl.EGL10;   
import javax.microedition.khronos.egl.EGL11;   
import javax.microedition.khronos.egl.EGLConfig;   
import javax.microedition.khronos.egl.EGLContext;   
import javax.microedition.khronos.egl.EGLDisplay;   
import javax.microedition.khronos.egl.EGLSurface;   
import javax.microedition.khronos.opengles.GL;   
import javax.microedition.khronos.opengles.GL10;   
import com.android.first3Dlive.BaseConfigChooser.ComponentSizeChooser;   
import com.android.first3Dlive.BaseConfigChooser.SimpleEGLConfigChooser;  
import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.view.SurfaceHolder;

   
// Original code provided by Robert Green    
// http://www.rbgrn.net/content/354-glsurfaceview-adapted-3d-live-wallpapers    
public class GLWallpaperService extends WallpaperService {   
    private static final String TAG = "GLWallpaperService";   
   
    @Override   
    public Engine onCreateEngine() {   
        return new GLEngine();   
    }   
   
    public class GLEngine extends Engine {   
        public final static int RENDERMODE_WHEN_DIRTY = 0;   
        public final static int RENDERMODE_CONTINUOUSLY = 1;   
   
        private GLThread mGLThread;   
        private EGLConfigChooser mEGLConfigChooser;   
        private EGLContextFactory mEGLContextFactory;   
        private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory;   
        private GLWrapper mGLWrapper;   
        private int mDebugFlags;   
   
        public GLEngine() {   
            super();   
        }   
   
        @Override   
        public void onVisibilityChanged(boolean visible) {   
            if (visible) {   
                onResume();   
            } else {   
                onPause();   
            }   
            super.onVisibilityChanged(visible);   
        }   
   
        @Override   
        public void onCreate(SurfaceHolder surfaceHolder) {   
            super.onCreate(surfaceHolder);   
            // Log.d(TAG, "GLEngine.onCreate()");    
        }   
   
        @Override   
        public void onDestroy() {   
            super.onDestroy();   
            // Log.d(TAG, "GLEngine.onDestroy()");    
            mGLThread.requestExitAndWait();   
        }   
   
        @Override   
        public void onSurfaceChanged(android.view.SurfaceHolder holder, int format, int width, int height) {   
            // Log.d(TAG, "onSurfaceChanged()");    
            mGLThread.onWindowResize(width, height);   
            super.onSurfaceChanged(holder, format, width, height);   
        }   
   
        @Override   
        public void onSurfaceCreated(SurfaceHolder holder) {   
            Log.d(TAG, "onSurfaceCreated()");   
            mGLThread.surfaceCreated(holder);   
            super.onSurfaceCreated(holder);   
        }   
   
        @Override   
        public void onSurfaceDestroyed(SurfaceHolder holder) {   
            Log.d(TAG, "onSurfaceDestroyed()");   
            mGLThread.surfaceDestroyed();   
            super.onSurfaceDestroyed(holder);   
        }   
   
        /**  
         * An EGL helper class.  
         */   
        public void setGLWrapper(GLWrapper glWrapper) {   
            mGLWrapper = glWrapper;   
        }   
   
        public void setDebugFlags(int debugFlags) {   
            mDebugFlags = debugFlags;   
        }   
   
        public int getDebugFlags() {   
            return mDebugFlags;   
        }   
   
        public void setRenderer(Renderer renderer) {   
            checkRenderThreadState();   
            if (mEGLConfigChooser == null) {   
                mEGLConfigChooser = new SimpleEGLConfigChooser(true);   
            }   
            if (mEGLContextFactory == null) {   
                mEGLContextFactory = new DefaultContextFactory();   
            }   
            if (mEGLWindowSurfaceFactory == null) {   
                mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory();   
            }   
            mGLThread = new GLThread(renderer, mEGLConfigChooser, mEGLContextFactory, mEGLWindowSurfaceFactory, mGLWrapper);   
            mGLThread.start();   
        }   
   
        public void setEGLContextFactory(EGLContextFactory factory) {   
            checkRenderThreadState();   
            mEGLContextFactory = factory;   
        }   
   
        public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) {   
            checkRenderThreadState();   
            mEGLWindowSurfaceFactory = factory;   
        }   
   
        public void setEGLConfigChooser(EGLConfigChooser configChooser) {   
            checkRenderThreadState();   
            mEGLConfigChooser = configChooser;   
        }   
   
        public void setEGLConfigChooser(boolean needDepth) {   
            setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth));   
        }   
   
        public void setEGLConfigChooser(int redSize, int greenSize, int blueSize, int alphaSize, int depthSize,   
                int stencilSize) {   
            setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize, blueSize, alphaSize, depthSize,   
                    stencilSize));   
        }   
   
        public void setRenderMode(int renderMode) {   
            mGLThread.setRenderMode(renderMode);   
        }   
   
        public int getRenderMode() {   
            return mGLThread.getRenderMode();   
        }   
   
        public void requestRender() {   
            mGLThread.requestRender();   
        }   
   
        public void onPause() {   
            mGLThread.onPause();   
        }   
   
        public void onResume() {   
            mGLThread.onResume();   
        }   
   
        public void queueEvent(Runnable r) {   
            mGLThread.queueEvent(r);   
        }   
   
        private void checkRenderThreadState() {   
            if (mGLThread != null) {   
                throw new IllegalStateException("setRenderer has already been called for this instance.");   
            }   
        }   
    }   
   
    public interface Renderer {   
   
        public void onSurfaceCreated(GL10 gl, EGLConfig config);   
   
        public void onSurfaceChanged(GL10 gl, int width, int height);   
   
        public void onDrawFrame(GL10 gl);   
    }   
}   
   
class LogWriter extends Writer {   
    private StringBuilder mBuilder = new StringBuilder();   
   
    @Override   
    public void close() {   
        flushBuilder();   
    }   
   
    @Override   
    public void flush() {   
        flushBuilder();   
    }   
   
    @Override   
    public void write(char[] buf, int offset, int count) {   
        for (int i = 0; i < count; i++) {   
            char c = buf[offset + i];   
            if (c == '\n') {   
                flushBuilder();   
            } else {   
                mBuilder.append(c);   
            }   
        }   
    }   
   
    private void flushBuilder() {   
        if (mBuilder.length() > 0) {   
            Log.v("GLSurfaceView", mBuilder.toString());   
            mBuilder.delete(0, mBuilder.length());   
        }   
    }   
}   
   
// ----------------------------------------------------------------------    
   
/**  
 * An interface for customizing the eglCreateContext and eglDestroyContext calls.  
 *  
  
 * This interface must be implemented by clients wishing to call  
 * {@link GLWallpaperService#setEGLContextFactory(EGLContextFactory)}  
 */   
interface EGLContextFactory {   
    EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig);   
   
    void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context);   
}   
   
class DefaultContextFactory implements EGLContextFactory {   
   
    public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig config) {   
        return egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, null);   
    }   
   
    public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {   
        egl.eglDestroyContext(display, context);   
    }   
}   
   
/**  
 * An interface for customizing the eglCreateWindowSurface and eglDestroySurface calls.  
 *  
  
 * This interface must be implemented by clients wishing to call  
 * {@link GLWallpaperService#setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory)}  
 */   
interface EGLWindowSurfaceFactory {   
    EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config, Object nativeWindow);   
   
    void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface);   
}   
   
class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory {   
   
    public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay   
            display, EGLConfig config, Object nativeWindow) {   
        // this is a bit of a hack to work around Droid init problems - if you don't have this, it'll get hung up on orientation changes    
        EGLSurface eglSurface = null;   
        while (eglSurface == null) {   
            try {   
                eglSurface = egl.eglCreateWindowSurface(display,   
                        config, nativeWindow, null);   
            } catch (Throwable t) {   
            } finally {   
                if (eglSurface == null) {   
                    try {   
                        Thread.sleep(10);   
                    } catch (InterruptedException t) {   
                    }   
                }   
            }   
        }   
        return eglSurface;   
    }   
   
    public void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface) {   
        egl.eglDestroySurface(display, surface);   
    }   
}   
   
interface GLWrapper {   
    /**  
     * Wraps a gl interface in another gl interface.  
     *  
     * @param gl  
     * a GL interface that is to be wrapped.  
     * @return either the input argument or another GL object that wraps the input argument.  
     */   
    GL wrap(GL gl);   
}   
   
class EglHelper {   
   
    private EGL10 mEgl;   
    private EGLDisplay mEglDisplay;   
    private EGLSurface mEglSurface;   
    private EGLContext mEglContext;   
    EGLConfig mEglConfig;   
   
    private EGLConfigChooser mEGLConfigChooser;   
    private EGLContextFactory mEGLContextFactory;   
    private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory;   
    private GLWrapper mGLWrapper;   
   
    public EglHelper(EGLConfigChooser chooser, EGLContextFactory contextFactory,   
            EGLWindowSurfaceFactory surfaceFactory, GLWrapper wrapper) {   
        this.mEGLConfigChooser = chooser;   
        this.mEGLContextFactory = contextFactory;   
        this.mEGLWindowSurfaceFactory = surfaceFactory;   
        this.mGLWrapper = wrapper;   
    }   
   
    /**  
     * Initialize EGL for a given configuration spec.  
     *  
     * @param configSpec  
     */   
    public void start() {   
        // Log.d("EglHelper" + instanceId, "start()");    
        if (mEgl == null) {   
            // Log.d("EglHelper" + instanceId, "getting new EGL");    
            /*  
             * Get an EGL instance  
             */   
            mEgl = (EGL10) EGLContext.getEGL();   
        } else {   
            // Log.d("EglHelper" + instanceId, "reusing EGL");    
        }   
   
        if (mEglDisplay == null) {   
            // Log.d("EglHelper" + instanceId, "getting new display");    
            /*  
             * Get to the default display.  
             */   
            mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);   
        } else {   
            // Log.d("EglHelper" + instanceId, "reusing display");    
        }   
   
        if (mEglConfig == null) {   
            // Log.d("EglHelper" + instanceId, "getting new config");    
            /*  
             * We can now initialize EGL for that display  
             */   
            int[] version = new int[2];   
            mEgl.eglInitialize(mEglDisplay, version);   
            mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);   
        } else {   
            // Log.d("EglHelper" + instanceId, "reusing config");    
        }   
   
        if (mEglContext == null) {   
            // Log.d("EglHelper" + instanceId, "creating new context");    
            /*  
             * Create an OpenGL ES context. This must be done only once, an OpenGL context is a somewhat heavy object.  
             */   
            mEglContext = mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig);   
            if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) {   
                throw new RuntimeException("createContext failed");   
            }   
        } else {   
            // Log.d("EglHelper" + instanceId, "reusing context");    
        }   
   
        mEglSurface = null;   
    }   
   
    /*  
     * React to the creation of a new surface by creating and returning an OpenGL interface that renders to that  
     * surface.  
     */   
    public GL createSurface(SurfaceHolder holder) {   
        /*  
         * The window size has changed, so we need to create a new surface.  
         */   
        if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) {   
   
            /*  
             * Unbind and destroy the old EGL surface, if there is one.  
             */   
            mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);   
            mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface);   
        }   
   
        /*  
         * Create an EGL surface we can render into.  
         */   
        mEglSurface = mEGLWindowSurfaceFactory.createWindowSurface(mEgl, mEglDisplay, mEglConfig, holder);   
   
        if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {   
            throw new RuntimeException("createWindowSurface failed");   
        }   
   
        /*  
         * Before we can issue GL commands, we need to make sure the context is current and bound to a surface.  
         */   
        if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {   
            throw new RuntimeException("eglMakeCurrent failed.");   
        }   
   
        GL gl = mEglContext.getGL();   
        if (mGLWrapper != null) {   
            gl = mGLWrapper.wrap(gl);   
        }   
   
        /*  
         * if ((mDebugFlags & (DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS))!= 0) { int configFlags = 0; Writer log =  
         * null; if ((mDebugFlags & DEBUG_CHECK_GL_ERROR) != 0) { configFlags |= GLDebugHelper.CONFIG_CHECK_GL_ERROR; }  
         * if ((mDebugFlags & DEBUG_LOG_GL_CALLS) != 0) { log = new LogWriter(); } gl = GLDebugHelper.wrap(gl,  
         * configFlags, log); }  
         */   
        return gl;   
    }   
   
    /**  
     * Display the current render surface.  
     *  
     * @return false if the context has been lost.  
     */   
    public boolean swap() {   
        mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);   
   
        /*  
         * Always check for EGL_CONTEXT_LOST, which means the context and all associated data were lost (For instance  
         * because the device went to sleep). We need to sleep until we get a new surface.  
         */   
        return mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST;   
    }   
   
    public void destroySurface() {   
        if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) {   
            mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);   
            mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface);   
            mEglSurface = null;   
        }   
    }   
   
    public void finish() {   
        if (mEglContext != null) {   
            mEGLContextFactory.destroyContext(mEgl, mEglDisplay, mEglContext);   
            mEglContext = null;   
        }   
        if (mEglDisplay != null) {   
            mEgl.eglTerminate(mEglDisplay);   
            mEglDisplay = null;   
        }   
    }   
}   
   
class GLThread extends Thread {   
    private final static boolean LOG_THREADS = false;   
    public final static int DEBUG_CHECK_GL_ERROR = 1;   
    public final static int DEBUG_LOG_GL_CALLS = 2;   
   
    private final GLThreadManager sGLThreadManager = new GLThreadManager();   
    private GLThread mEglOwner;   
   
    private EGLConfigChooser mEGLConfigChooser;   
    private EGLContextFactory mEGLContextFactory;   
    private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory;   
    private GLWrapper mGLWrapper;   
   
    public SurfaceHolder mHolder;   
    private boolean mSizeChanged = true;   
   
    // Once the thread is started, all accesses to the following member    
    // variables are protected by the sGLThreadManager monitor    
    public boolean mDone;   
    private boolean mPaused;   
    private boolean mHasSurface;   
    private boolean mWaitingForSurface;   
    private boolean mHaveEgl;   
    private int mWidth;   
    private int mHeight;   
    private int mRenderMode;   
    private boolean mRequestRender;   
    private boolean mEventsWaiting;   
    // End of member variables protected by the sGLThreadManager monitor.    
   
    private GLWallpaperService.Renderer mRenderer;   
    private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>();   
    private EglHelper mEglHelper;   
   
    GLThread(GLWallpaperService.Renderer renderer, EGLConfigChooser chooser, EGLContextFactory contextFactory,   
            EGLWindowSurfaceFactory surfaceFactory, GLWrapper wrapper) {   
        super();   
        mDone = false;   
        mWidth = 0;   
        mHeight = 0;   
        mRequestRender = true;   
        mRenderMode = GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY;   
        mRenderer = renderer;   
        this.mEGLConfigChooser = chooser;   
        this.mEGLContextFactory = contextFactory;   
        this.mEGLWindowSurfaceFactory = surfaceFactory;   
        this.mGLWrapper = wrapper;   
    }   
   
    @Override   
    public void run() {   
        setName("GLThread " + getId());   
        if (LOG_THREADS) {   
            Log.i("GLThread", "starting tid=" + getId());   
        }   
   
        try {   
            guardedRun();   
        } catch (InterruptedException e) {   
            // fall thru and exit normally    
        } finally {   
            sGLThreadManager.threadExiting(this);   
        }   
    }   
   
    /*  
     * This private method should only be called inside a synchronized(sGLThreadManager) block.  
     */   
    private void stopEglLocked() {   
        if (mHaveEgl) {   
            mHaveEgl = false;   
            mEglHelper.destroySurface();   
            sGLThreadManager.releaseEglSurface(this);   
        }   
    }   
   
    private void guardedRun() throws InterruptedException {   
        mEglHelper = new EglHelper(mEGLConfigChooser, mEGLContextFactory, mEGLWindowSurfaceFactory, mGLWrapper);   
        try {   
            GL10 gl = null;   
            boolean tellRendererSurfaceCreated = true;   
            boolean tellRendererSurfaceChanged = true;   
   
            /*  
             * This is our main activity thread's loop, we go until asked to quit.  
             */   
            while (!isDone()) {   
                /*  
                 * Update the asynchronous state (window size)  
                 */   
                int w = 0;   
                int h = 0;   
                boolean changed = false;   
                boolean needStart = false;   
                boolean eventsWaiting = false;   
   
                synchronized (sGLThreadManager) {   
                    while (true) {   
                        // Manage acquiring and releasing the SurfaceView    
                        // surface and the EGL surface.    
                        if (mPaused) {   
                            stopEglLocked();   
                        }   
                        if (!mHasSurface) {   
                            if (!mWaitingForSurface) {   
                                stopEglLocked();   
                                mWaitingForSurface = true;   
                                sGLThreadManager.notifyAll();   
                            }   
                        } else {   
                            if (!mHaveEgl) {   
                                if (sGLThreadManager.tryAcquireEglSurface(this)) {   
                                    mHaveEgl = true;   
                                    mEglHelper.start();   
                                    mRequestRender = true;   
                                    needStart = true;   
                                }   
                            }   
                        }   
   
                        // Check if we need to wait. If not, update any state    
                        // that needs to be updated, copy any state that    
                        // needs to be copied, and use "break" to exit the    
                        // wait loop.    
   
                        if (mDone) {   
                            return;   
                        }   
   
                        if (mEventsWaiting) {   
                            eventsWaiting = true;   
                            mEventsWaiting = false;   
                            break;   
                        }   
   
                        if ((!mPaused) && mHasSurface && mHaveEgl && (mWidth > 0) && (mHeight > 0)   
                                && (mRequestRender || (mRenderMode == GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY))) {   
                            changed = mSizeChanged;   
                            w = mWidth;   
                            h = mHeight;   
                            mSizeChanged = false;   
                            mRequestRender = false;   
                            if (mHasSurface && mWaitingForSurface) {   
                                changed = true;   
                                mWaitingForSurface = false;   
                                sGLThreadManager.notifyAll();   
                            }   
                            break;   
                        }   
   
                        // By design, this is the only place where we wait().    
   
                        if (LOG_THREADS) {   
                            Log.i("GLThread", "waiting tid=" + getId());   
                        }   
                        sGLThreadManager.wait();   
                    }   
                } // end of synchronized(sGLThreadManager)    
   
                /*  
                 * Handle queued events  
                 */   
                if (eventsWaiting) {   
                    Runnable r;   
                    while ((r = getEvent()) != null) {   
                        r.run();   
                        if (isDone()) {   
                            return;   
                        }   
                    }   
                    // Go back and see if we need to wait to render.    
                    continue;   
                }   
   
                if (needStart) {   
                    tellRendererSurfaceCreated = true;   
                    changed = true;   
                }   
                if (changed) {   
                    gl = (GL10) mEglHelper.createSurface(mHolder);   
                    tellRendererSurfaceChanged = true;   
                }   
                if (tellRendererSurfaceCreated) {   
                    mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);   
                    tellRendererSurfaceCreated = false;   
                }   
                if (tellRendererSurfaceChanged) {   
                    mRenderer.onSurfaceChanged(gl, w, h);   
                    tellRendererSurfaceChanged = false;   
                }   
                if ((w > 0) && (h > 0)) {   
                    /* draw a frame here */   
                    mRenderer.onDrawFrame(gl);   
   
                    /*  
                     * Once we're done with GL, we need to call swapBuffers() to instruct the system to display the  
                     * rendered frame  
                     */   
                    mEglHelper.swap();   
                    Thread.sleep(10);   
                }   
            }   
        } finally {   
            /*  
             * clean-up everything...  
             */   
            synchronized (sGLThreadManager) {   
                stopEglLocked();   
                mEglHelper.finish();   
            }   
        }   
    }   
   
    private boolean isDone() {   
        synchronized (sGLThreadManager) {   
            return mDone;   
        }   
    }   
   
    public void setRenderMode(int renderMode) {   
        if (!((GLWallpaperService.GLEngine.RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY))) {   
            throw new IllegalArgumentException("renderMode");   
        }   
        synchronized (sGLThreadManager) {   
            mRenderMode = renderMode;   
            if (renderMode == GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY) {   
                sGLThreadManager.notifyAll();   
            }   
        }   
    }   
   
    public int getRenderMode() {   
        synchronized (sGLThreadManager) {   
            return mRenderMode;   
        }   
    }   
   
    public void requestRender() {   
        synchronized (sGLThreadManager) {   
            mRequestRender = true;   
            sGLThreadManager.notifyAll();   
        }   
    }   
   
    public void surfaceCreated(SurfaceHolder holder) {   
        mHolder = holder;   
        synchronized (sGLThreadManager) {   
            if (LOG_THREADS) {   
                Log.i("GLThread", "surfaceCreated tid=" + getId());   
            }   
            mHasSurface = true;   
            sGLThreadManager.notifyAll();   
        }   
    }   
   
    public void surfaceDestroyed() {   
        synchronized (sGLThreadManager) {   
            if (LOG_THREADS) {   
                Log.i("GLThread", "surfaceDestroyed tid=" + getId());   
            }   
            mHasSurface = false;   
            sGLThreadManager.notifyAll();   
            while (!mWaitingForSurface && isAlive() && !mDone) {   
                try {   
                    sGLThreadManager.wait();   
                } catch (InterruptedException e) {   
                    Thread.currentThread().interrupt();   
                }   
            }   
        }   
    }   
   
    public void onPause() {   
        synchronized (sGLThreadManager) {   
            mPaused = true;   
            sGLThreadManager.notifyAll();   
        }   
    }   
   
    public void onResume() {   
        synchronized (sGLThreadManager) {   
            mPaused = false;   
            mRequestRender = true;   
            sGLThreadManager.notifyAll();   
        }   
    }   
   
    public void onWindowResize(int w, int h) {   
        synchronized (sGLThreadManager) {   
            mWidth = w;   
            mHeight = h;   
            mSizeChanged = true;   
            sGLThreadManager.notifyAll();   
        }   
    }   
   
    public void requestExitAndWait() {   
        // don't call this from GLThread thread or it is a guaranteed    
        // deadlock!    
        synchronized (sGLThreadManager) {   
            mDone = true;   
            sGLThreadManager.notifyAll();   
        }   
        try {   
            join();   
        } catch (InterruptedException ex) {   
            Thread.currentThread().interrupt();   
        }   
    }   
   
    /**  
     * Queue an "event" to be run on the GL rendering thread.  
     *  
     * @param r  
     * the runnable to be run on the GL rendering thread.  
     */   
    public void queueEvent(Runnable r) {   
        synchronized (this) {   
            mEventQueue.add(r);   
            synchronized (sGLThreadManager) {   
                mEventsWaiting = true;   
                sGLThreadManager.notifyAll();   
            }   
        }   
    }   
   
    private Runnable getEvent() {   
        synchronized (this) {   
            if (mEventQueue.size() > 0) {   
                return mEventQueue.remove(0);   
            }   
   
        }   
        return null;   
    }   
   
    private class GLThreadManager {   
   
        public synchronized void threadExiting(GLThread thread) {   
            if (LOG_THREADS) {   
                Log.i("GLThread", "exiting tid=" + thread.getId());   
            }   
            thread.mDone = true;   
            if (mEglOwner == thread) {   
                mEglOwner = null;   
            }   
            notifyAll();   
        }   
   
        /*  
         * Tries once to acquire the right to use an EGL surface. Does not block.  
         *  
         * @return true if the right to use an EGL surface was acquired.  
         */   
        public synchronized boolean tryAcquireEglSurface(GLThread thread) {   
            if (mEglOwner == thread || mEglOwner == null) {   
                mEglOwner = thread;   
                notifyAll();   
                return true;   
            }   
            return false;   
        }   
   
        public synchronized void releaseEglSurface(GLThread thread) {   
            if (mEglOwner == thread) {   
                mEglOwner = null;   
            }   
            notifyAll();   
        }   
    }   
}   
   
interface EGLConfigChooser {   
    EGLConfig chooseConfig(EGL10 egl, EGLDisplay display);   
}   
   
abstract class BaseConfigChooser implements EGLConfigChooser {   
    public BaseConfigChooser(int[] configSpec) {   
        mConfigSpec = configSpec;   
    }   
   
    public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {   
        int[] num_config = new int[1];   
        egl.eglChooseConfig(display, mConfigSpec, null, 0, num_config);   
   
        int numConfigs = num_config[0];   
   
        if (numConfigs <= 0) {   
            throw new IllegalArgumentException("No configs match configSpec");   
        }   
   
        EGLConfig[] configs = new EGLConfig[numConfigs];   
        egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, num_config);   
        EGLConfig config = chooseConfig(egl, display, configs);   
        if (config == null) {   
            throw new IllegalArgumentException("No config chosen");   
        }   
        return config;   
    }   
   
    abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs);   
   
    protected int[] mConfigSpec;   
    public static class ComponentSizeChooser extends BaseConfigChooser {   
        public ComponentSizeChooser(int redSize, int greenSize, int blueSize, int alphaSize, int depthSize,   
                int stencilSize) {   
            super(new int[] { EGL10.EGL_RED_SIZE, redSize, EGL10.EGL_GREEN_SIZE, greenSize, EGL10.EGL_BLUE_SIZE,   
                    blueSize, EGL10.EGL_ALPHA_SIZE, alphaSize, EGL10.EGL_DEPTH_SIZE, depthSize, EGL10.EGL_STENCIL_SIZE,   
                    stencilSize, EGL10.EGL_NONE });   
            mValue = new int[1];   
            mRedSize = redSize;   
            mGreenSize = greenSize;   
            mBlueSize = blueSize;   
            mAlphaSize = alphaSize;   
            mDepthSize = depthSize;   
            mStencilSize = stencilSize;   
        }   
   
        @Override   
        public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs) {   
            EGLConfig closestConfig = null;   
            int closestDistance = 1000;   
            for (EGLConfig config : configs) {   
                int d = findConfigAttrib(egl, display, config, EGL10.EGL_DEPTH_SIZE, 0);   
                int s = findConfigAttrib(egl, display, config, EGL10.EGL_STENCIL_SIZE, 0);   
                if (d >= mDepthSize && s >= mStencilSize) {   
                    int r = findConfigAttrib(egl, display, config, EGL10.EGL_RED_SIZE, 0);   
                    int g = findConfigAttrib(egl, display, config, EGL10.EGL_GREEN_SIZE, 0);   
                    int b = findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0);   
                    int a = findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0);   
                    int distance = Math.abs(r - mRedSize) + Math.abs(g - mGreenSize) + Math.abs(b - mBlueSize)   
                    + Math.abs(a - mAlphaSize);   
                    if (distance < closestDistance) {   
                        closestDistance = distance;   
                        closestConfig = config;   
                    }   
                }   
            }   
            return closestConfig;   
        }   
   
        private int findConfigAttrib(EGL10 egl, EGLDisplay display, EGLConfig config, int attribute, int defaultValue) {   
   
            if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {   
                return mValue[0];   
            }   
            return defaultValue;   
        }   
   
        private int[] mValue;   
        // Subclasses can adjust these values:    
        protected int mRedSize;   
        protected int mGreenSize;   
        protected int mBlueSize;   
        protected int mAlphaSize;   
        protected int mDepthSize;   
        protected int mStencilSize;   
    }   
   
    /**  
     * This class will choose a supported surface as close to RGB565 as possible, with or without a depth buffer.  
     *  
     */   
    public static class SimpleEGLConfigChooser extends ComponentSizeChooser {   
        public SimpleEGLConfigChooser(boolean withDepthBuffer) {   
            super(4, 4, 4, 0, withDepthBuffer ? 16 : 0, 0);   
    
            mRedSize = 5;   
            mGreenSize = 6;   
            mBlueSize = 5;   
        }   
    } 
}
 
分享到:
评论

相关推荐

    Android-在Android上将您的Unity游戏作为动态壁纸运行

    在Android平台上,将Unity游戏作为动态...总的来说,将Unity游戏作为Android动态壁纸是一项技术含量较高的任务,需要对Unity和Android原生开发都有深入理解。但一旦成功,它将为用户提供一个独特且引人入胜的手机体验。

    Android 动态壁纸源码-IT计算机-毕业设计.zip

    本资源是一个关于Android动态壁纸的源码项目,非常适合计算机科学专业的学生进行毕业设计或者论文研究。下面我们将深入探讨这个源码中的关键知识点。 1. **Android开发环境**:首先,你需要了解Android Studio,这...

    Android应用案例开发大全(第3版)源码

    Android应用案例开发大全(第3版) 源码内容: 第01章 初识庐山真面目——Android简介 第02章 3D动态壁纸——百纳水族馆 第03章 掌上杭州 第04章 BN理财助手 第05章 LBS交通软件——百纳公交小助手 第06章 天气课程表...

    android应用案例开发大全(第3版)源程序.rar

    第02章"3D动态壁纸——百纳水族馆"则展示了Android壁纸开发的魅力。这一章可能会涵盖OpenGL ES的使用,用于创建3D图形效果,同时涉及动画和触摸事件的处理,让壁纸动起来。这需要开发者具备一定的图形编程基础。 第...

    android桌面壁纸2

    总的来说,"Android桌面壁纸2"是一个深入学习Android动态壁纸开发的好案例。通过研究这个项目的源码,开发者可以了解到如何创建自定义的壁纸服务,如何使用OpenGL ES或Canvas制作动画,以及如何实现与用户的交互。这...

    Android源码——动态壁纸源码.7z

    【标题】"Android源码——动态壁纸源码.7z" 涉及的主要知识点是Android平台上的动态壁纸开发。动态壁纸是Android操作系统提供的一种增强用户界面的方式,它允许开发者创建交互式的背景图像,使手机桌面更加生动有趣...

    Android应用案例开发大全( 第4版)源码1-6章

    通过创建3D动态壁纸,开发者将学习如何在Android中实现三维渲染,理解视图和场景的构建,以及如何利用动画效果来提升用户体验。同时,也会涉及到服务和服务与壁纸组件的交互。 **第03章 掌上杭州** 这一章主要讲解...

    Android动态壁纸源码

    Android动态壁纸源码是开发Android应用的一个特殊领域,它允许用户自定义主屏幕背景,使其具有交互性和动画效果。对于想要提升Android开发技能的小白来说,深入研究动态壁纸的源码是一个很好的学习途径。这份源码...

    Android 使用opengl写动态壁纸的类库-IT计算机-毕业设计.zip

    在Android平台上,OpenGL(Open ...总之,这个项目涵盖了Android应用开发、OpenGL编程和毕业设计论文写作等多个方面,对提升你的Android开发技能和理论知识大有裨益。仔细研究源码,动手实践,你将收获丰富的经验。

    Android 使用opengl写动态壁纸的类库.zip

    总之,`GLWallpaperService` 提供了一种高效且直观的方式,让开发者可以利用OpenGL ES的强大功能来设计Android动态壁纸。尽管需要一定的图形编程知识,但一旦掌握,你就能创造出令人惊叹的个性化壁纸,提升用户的...

    android应用案例开发.pdf

    通过这些案例,你可以深入理解Android应用开发的各个环节,从基础的环境配置到复杂的3D图形和网络编程,再到用户界面设计和数据管理。每个案例都是一个独立的学习单元,帮助你在实践中积累经验,逐步成长为一名熟练...

    好看的3D壁纸程序

    在IT行业中,3D壁纸程序是一种能够为用户电脑或移动...总结来说,"好看的3D壁纸程序"涵盖了3D图像创作、软件开发、性能优化、交互设计等多个IT领域的知识,是技术和艺术的结合体,为用户提供了一种创新的桌面美化方式。

    android开发资料大全

    Android3D游戏开发付费视频教程共享(更新第四集) 史上最全示例Android教学视频,非常值得观看 Android游戏开发系列源码+CHM+书籍截图+目录】 Android developer guide中文翻译文档 Android开发开发技巧之 EditText...

    andorid 动态壁纸细节研究

    以上就是关于Android动态壁纸开发的一些基础知识和技术要点。通过本篇文章的学习,相信你已经对Android动态壁纸有了较为全面的认识。无论是作为初学者还是有一定经验的开发者,都能从中获得启发和帮助。未来,随着...

    Android 樱花漂落的动态壁纸-IT计算机-毕业设计.zip

    这篇文档将深入解析《Android 樱花漂落的动态壁纸》这个项目,它是一个Android应用源码开发的Demo,适合于毕业设计学习。通过分析这个项目,我们可以了解到Android应用程序开发的基本流程,以及如何实现动态壁纸功能...

    安卓Android源码——OpenGL3D01_3_漂亮的金字塔.zip

    在安卓Android平台上,开发3D图形应用通常会涉及到OpenGL ES(OpenGL for Embedded Systems)的使用。OpenGL ES是OpenGL的一个轻量级版本,专为嵌入式设备如智能手机和平板电脑设计,支持创建复杂的3D图形。这个...

    超级炫的一个Android效果

    8. **Android Studio集成开发环境**:使用Android Studio进行项目开发,调试和测试3D特效。 9. **NDK和JNI**:如果涉及到C++的3D库,那么了解Native Development Kit (NDK)和Java Native Interface (JNI)将有助于在...

    移动应用Android 使用opengl写动态壁纸的类库.rar

    本资源"移动应用Android 使用opengl写动态壁纸的类库.rar"显然提供了一个专门用于构建OpenGL驱动的Android动态壁纸的应用程序开发库。 **OpenGL基础知识** OpenGL是一个跨语言、跨平台的编程接口,用于渲染高质量...

    ANDROID_2.0游戏开发实战宝典.part1.

    根据提供的文件信息,“ANDROID_2.0游戏开发实战宝典.part1.”主要聚焦于基于Android 2.0操作系统的移动游戏开发技术与实践。虽然给定的部分内容并未包含实际的技术细节,但从标题、描述以及标签来看,我们可以推断...

Global site tag (gtag.js) - Google Analytics