zoukankan      html  css  js  c++  java
  • Opengl ES 1.x NDK实例开发之七:旋转的纹理立方体

    开发框架介绍请參见:Opengl ES NDK实例开发之中的一个:搭建开发框架

    本章在第六章(Opengl ES 1.x NDK实例开发之六:纹理贴图)的基础上绘制一个旋转的纹理立方体,原理和纹理贴图一样,须要注意的是定好正方体的顶点数组。

    【实例解说】

    本实例加入了一个显示fps的小功能,在java层实现,原理是统计一分钟内屏幕刷新的次数


    【实例源代码】

    [GLJNIActivity.java]

    /*
     * Copyright (C) 2007 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     * 
     * author: mnorst@foxmail.com
     */
    
    package com.android.gljni;
    
    import java.text.DecimalFormat;
    
    import com.android.gljni.GLJNIView;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.view.ViewGroup.LayoutParams;
    import android.widget.TextView;
    
    public class GLJNIActivity extends Activity {
    	GLJNIView mView;
    	TextView mTextView;
    
    	@Override
    	protected void onCreate(Bundle icicle) {
    		super.onCreate(icicle);
    		mView = new GLJNIView(getApplication());
    		setContentView(mView);
    		
    		mView.setHandler(new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    
                    // 显示fps
                    mTextView.setText("fps:"+msg.what);
                }
            }
            );
    		
    		mTextView = new TextView(this);
    		mTextView.setText("fps:0");
    		addContentView(mTextView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
    	}
    
    	@Override
    	protected void onPause() {
    		super.onPause();
    		mView.onPause();
    	}
    
    	@Override
    	protected void onResume() {
    		super.onResume();
    		mView.onResume();
    	}
    }
    

    [GLJNIView.java]

    /*
     * Copyright (C) 2007 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     * 
     * author: mnorst@foxmail.com
     */
    
    package com.android.gljni;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    import javax.microedition.khronos.egl.EGLConfig;
    import javax.microedition.khronos.opengles.GL10;
    
    import com.android.gljni.GLJNILib;
    import com.android.gljnidemo07.R;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.opengl.GLSurfaceView;
    import android.opengl.GLUtils;
    import android.os.Handler;
    import android.util.Log;
    
    /**
     * A simple GLSurfaceView sub-class that demonstrate how to perform
     * OpenGL ES 1.x rendering into a GL Surface.
     */
    public class GLJNIView extends GLSurfaceView {
    
    	private static final String LOG_TAG = GLJNIView.class.getSimpleName();
    
    	private Renderer renderer;
    
    	public GLJNIView(Context context) {
    		super(context);
    
    		// setEGLConfigChooser会对fps产生影响
    		setEGLConfigChooser(8, 8, 8, 8, 16, 0);
    
    		renderer = new Renderer(context);
    		setRenderer(renderer);
    	}
    	
    	public void setHandler( Handler handler){
    		renderer.setHandler(handler);
    	}
    
    	private static class Renderer implements GLSurfaceView.Renderer {
    		//用于纹理映射的绑定,并把绑定后的ID传递给C++代码。供其调用
    		private int[] mTexture = new int[2];
    		//用于载入Bitmap的context
    		private Context mContext;
    		
    		// 统计fps
    		private Handler mHandler;
    		private long mStartMili;			
    		private long mEndMili;
    		private int mFps = 0;
    		
    		public Renderer(Context ctx) {
    			mContext = ctx;
    			mStartMili =System.currentTimeMillis();
    		}
    		
    		public void setHandler( Handler handler){
    			mHandler = handler;
    		}
    
    		public void onDrawFrame(GL10 gl) {
    			
    			GLJNILib.step();
    			
    			// 以一分钟绘制的帧数来统计fps
    			mEndMili = System.currentTimeMillis();
    			if( mEndMili - mStartMili > 1000 ){
    				mHandler.sendEmptyMessageDelayed(mFps, 100);
    				mStartMili = mEndMili;
    				mFps = 0;
    			}
    			mFps++;
    		}
    
    		public void onSurfaceChanged(GL10 gl, int width, int height) {
    			GLJNILib.resize(width, height);
    		}
    
    		public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    			//用来绑定Bitmap纹理
    			genTexture(gl, mContext);
    			//调用本地setTexture方法。把纹理绑定的ID传递给C++代码,以供其调用
    			GLJNILib.setTexture(mTexture);
    			GLJNILib.init();
    		}
    		
    		/**
    		 * 载入Bitmap的方法,
    		 * 用来从res中载入Bitmap资源
    		 * */
    		private Bitmap loadBitmap(Context context, int resourceId) {
    			InputStream is = context.getResources().openRawResource(resourceId);
    			Bitmap bitmap = null;
    			try {
    
    				// 利用BitmapFactory生成Bitmap
    				bitmap = BitmapFactory.decodeStream(is);
    			} finally {
    				try {
    
    					// 关闭流
    					is.close();
    					is = null;
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    
    			}
    			return bitmap;
    
    		}
    		
    		/**
    		 * 绑定Bitmap纹理
    		 * */
    
    		private void genTexture(GL10 gl, Context context) {
    			//生成纹理
    			gl.glGenTextures(2, mTexture, 0);
    			//载入Bitmap
    			Bitmap bitmap = loadBitmap(context, R.drawable.logo);
    			if (bitmap != null) {
    				//假设bitmap载入成功,则生成此bitmap的纹理映射
    				gl.glBindTexture(GL10.GL_TEXTURE_2D, mTexture[0]);
    				//设置纹理映射的属性
    				gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
    						GL10.GL_NEAREST);
    				gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
    						GL10.GL_NEAREST);
    				//生成纹理映射
    				GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
    				//释放bitmap资源
    				bitmap.recycle();
    			}
    
    		}
    	}
    
    }
    
    [GLJNILib.java]
    /*
     * Copyright (C) 2007 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     * 
     * author: mnorst@foxmail.com
     */
    
    package com.android.gljni;
    
    //Wrapper for native library
    public class GLJNILib {
    	
    	static {
    		System.loadLibrary("gljni");
    	}
    
    	/**
         * @param width the current view width
         * @param height the current view height
         */
    	public static native void resize(int width, int height); 
    	
    	/**
    	 * render 
    	 */
        public static native void step();  
        
        /**
         * init
         */
        public static native void init();  
        
        /**
         * set the texture
         * @param texture	texture id
         */
        public static native void setTexture(int[] texture);
    }
    

    [[gl_code.cpp]

    /*
     * Copyright (C) 2007 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     * 
     * author: 	mnorst@foxmail.com
     * created:	2014/10/27
     * purpose:	旋转的纹理立方体
     */
    
    // OpenGL ES 1.x code
    
    #include <jni.h>
    #include <android/log.h>
    
    #include <GLES/gl.h>
    #include <GLES/glext.h>
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    /************************************************************************/
    /*                             定义                                     */
    /************************************************************************/
    
    #define  LOG_TAG    "libgljni"
    #define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
    #define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
    
    //初始化纹理数组
    GLuint *gTexture = 0;
    
    // 定义π
    const GLfloat PI = 3.1415f;
    
    // 定义顶点坐标
    #define pos 1.0f
    
    // 定义顶点坐标
    // 一个正方体有8个顶点,6个面
    #define one 1.0f
    static GLfloat gVertices[] = {
    	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 
    };
    
    // 定义纹理坐标
    // 纹理坐标原点会因不同系统环境而有所不同。
    // 比方在iOS以及Android上,纹理坐标原点(0, 0)是在左上角
    // 而在OS X上,纹理坐标的原点是在左下角
    static GLfloat gTexCoords[] = {   
    	0, one,                 
    	one, one, 
    	0, 0, 
    	one, 0, 
    
    	0, one,                 
    	one, one, 
    	0, 0, 
    	one, 0, 
    
    	0, one,                 
    	one, one, 
    	0, 0, 
    	one, 0, 
    
    	0, one,                 
    	one, one, 
    	0, 0, 
    	one, 0, 
    
    	0, one,                 
    	one, one, 
    	0, 0, 
    	one, 0, 
    
    	0, one,                 
    	one, one, 
    	0, 0, 
    	one, 0, 
    
    
    }; 
    
    // 旋转角度
    static GLfloat gAngle = 0.0f;
    /************************************************************************/
    /*                             C++代码                                  */
    /************************************************************************/
    
    static void printGLString(const char *name, GLenum s) {
    	const char *v = (const char *) glGetString(s);
    	LOGI("GL %s = %s
    ", name, v);
    }
    
    static void checkGlError(const char* op) {
    	for (GLint error = glGetError(); error; error = glGetError()) {
    			LOGI("after %s() glError (0x%x)
    ", op, error);
    	}
    }
    
    bool init() {
    	printGLString("Version", GL_VERSION);
    	printGLString("Vendor", GL_VENDOR);
    	printGLString("Renderer", GL_RENDERER);
    	printGLString("Extensions", GL_EXTENSIONS);
    
    	// 启用阴影平滑
    	glShadeModel(GL_SMOOTH);
    
    	// 黑色背景	
    	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);	
    
    	// 设置深度缓存	
    	glClearDepthf(1.0f);
    
    	// 启用深度測试
    	glEnable(GL_DEPTH_TEST);	
    
    	// 所作深度測试的类型	
    	glDepthFunc(GL_LEQUAL);	
    
    	// 对透视进行修正	
    	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	
    
    	return true;
    }
    
    static void _gluPerspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar)
    {
    	GLfloat top = zNear * ((GLfloat) tan(fovy * PI / 360.0));
    	GLfloat bottom = -top;
    	GLfloat left = bottom * aspect;
    	GLfloat right = top * aspect;
    	glFrustumf(left, right, bottom, top, zNear, zFar);
    }
    
    void resize(int width, int height)
    {
    	// 防止被零除
    	if (height==0)								
    	{
    		height=1;
    	}
    
    	// 重置当前的视口
    	glViewport(0, 0, width, height);	
    	// 选择投影矩阵	
    	glMatrixMode(GL_PROJECTION);	
    	// 重置投影矩阵	
    	glLoadIdentity();							
    
    	// 设置视口的大小
    	_gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
    
    	// 选择模型观察矩阵
    	glMatrixMode(GL_MODELVIEW);	
    
    	// 重置模型观察矩阵
    	glLoadIdentity();							
    }
    
    void renderFrame() {
    	// 清除屏幕和深度缓存
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    	// 重置当前的模型观察矩阵
    	glLoadIdentity();
    
    	glTranslatef(0,0,-10.0f);
    	glRotatef(gAngle, 0, 1.0F, 0);
    	glRotatef(gAngle, 0, 0, 1.0F);
    
    	// 启用顶点数组
    	glEnableClientState(GL_VERTEX_ARRAY);
    	//glEnableClientState(GL_COLOR_ARRAY);
    	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    
    	// 启用纹理映射
    	glEnable(GL_TEXTURE_2D); 
    
    	// 选择纹理
    	glBindTexture(GL_TEXTURE_2D, gTexture[0]); 
    
    	// 绘制正方体的六个面
    	glVertexPointer(3,GL_FLOAT,0,gVertices);
    	glTexCoordPointer(2, GL_FLOAT, 0, gTexCoords);
    
    	for (int i = 0; i < 6; i++) {
    		glDrawArrays(GL_TRIANGLE_STRIP, i * 4, 4);
    	} 
    
    	// 关闭顶点数组
    	glDisableClientState(GL_VERTEX_ARRAY);
    	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    	//glDisableClientState(GL_OLOR_ARRAY);
    
    	gAngle += 5.f;
    }
    
    /************************************************************************/
    /*                          JNI代码                                     */
    /************************************************************************/
    
    extern "C" {
    	JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_resize(JNIEnv * env, jobject obj,  jint width, jint height);
    	JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_step(JNIEnv * env, jobject obj);
    	JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_init(JNIEnv * env, jobject obj);
    	JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_setTexture(JNIEnv * env, jclass obj, jintArray tex);
    };
    
    JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_resize(JNIEnv * env, jobject obj,  jint width, jint height)
    {
    	resize(width, height);
    }
    
    JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_step(JNIEnv * env, jobject obj)
    {
    	renderFrame();
    }
    
    JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_init(JNIEnv * env, jobject obj)
    {
    	init();
    }
    
    JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_setTexture(JNIEnv * env, jclass obj, jintArray tex)
    {
    	gTexture = (GLuint *)env->GetIntArrayElements(tex,0);
    }
    

    源代码project:http://download.csdn.net/detail/mnorst/8123375

  • 相关阅读:
    数据库连接池
    批量插入数据库数据,有则更新,无则追加
    初识gensim
    Python pip install之SSL异常处理
    使用Fiddler和夜神浏览器对搜狐推荐新闻的抓取
    使用Fiddler抓取夜神模拟器上的包
    教你如何用GatherProxy,自己找SOCKS代理
    logging.Formatter 日期格式
    由于找不到MSVCR120.dll,无法继续执行代码.重新安装程序可能会解决此问题。
    beautifulsoup的简单使用
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/7137329.html
Copyright © 2011-2022 走看看