Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 718|回复: 0

基于 Android NDK 进行 OpenGL ES开发-  Android学习

[复制链接]

该用户从未签到

发表于 2011-10-24 14:27:26 | 显示全部楼层 |阅读模式
NDK 简介
Android SDK 提供了一套 OpenGL ES 接口,该接口是基于 java 的,速度非常 慢,往往很难满足需要。
NDK 提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动 将 so和 java 应用一起打包成 apk。使用 NDK,我们可以将要求高性能的应用 逻辑使用C开发,从而提高应用程序的执行效率。如 OpenGL ES 的程序。2
JNI
对于 NDK,在 Java 代码中调用 C/C++ 代码是通过 JNI 实现的。
Java Native Interface(JNI)是 Java 语言的本地编程接口,在java程序中, 我们可以通过 JNI 实现一些用 java 语言不便实现的功能。通常有以下几种情 况我们需要使用 JNI 来实现:
java 类库没有提供你的应用程序所需要的功能,通常这些功能是平台相关的;
你希望使用一些已经有的类库或者应用程序,而他们并非用java语言编写的;
程序的某些部分对速度要求比较苛刻,你选择用汇编或者 c 语言来实现并在 java 语言中调用他们。

注意,不到万不得已不要使用 JNI 技术,一方面它需要你把握更多的知识才可 以驾驭,一方面使用了 JNI 你的程序就会丧失可移植性。
我们可以把 JNI 想象为本地代码和 java 代码的粘合剂,关系如下图所示3:

OpenGL ESJava 端核心代码如下所示: public class DemoAct extends Activity {



    private GLSurfaceView mGLView;



    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);



        mGLView = new DemoGLSurfaceView(this);

        setContentView(mGLView);

    }



    ... ...



    static {

        System.loadLibrary("sanangeles");

    }



}





class DemoGLSurfaceView extends GLSurfaceView {



    DemoRenderer mRenderer;



    public DemoGLSurfaceView(Context context) {

        super(context);



        mRenderer = new DemoRenderer();

        setRenderer(mRenderer);

    }



class DemoRenderer implements GLSurfaceView.Renderer {



    private static native void nativeInit();

    private static native void nativeResize(int w, int h);

    private static native void nativeRender();

    private static native void nativeDone();



    public void onSurfaceCreated(GL10 gl, EGLConfig config) {

        nativeInit();

    }



    public void onSurfaceChanged(GL10 gl, int w, int h) {



        nativeResize(w, h);

    }



    public void onDrawFrame(GL10 gl) {

        nativeRender();

    }






复制代码
注意:EGL Context Lost
There are situations where the EGL rendering context will be lost. This typically happens when device wakes up after going to sleep. When the EGL context is lost, all OpenGL resources (such as textures) that are associated with that context will be automatically deleted. In order to keep rendering correctly, a renderer must recreate any lost resources that it still needs. The onSurfaceCreated(GL10, EGLConfig) method is a convenient place to do this.
JNI 代码如下所示: #include <jni.h>

...



/* Call to initialize the graphics state */

void

Java_com_example_AndMii_DemoRenderer_nativeInit( JNIEnv*  env )

{

    appInit();

}





/* Call to finalize the graphics state */

void

Java_com_example_AndMii_DemoRenderer_nativeDone( JNIEnv*  env )

{

    free objects.

}



/* Call to render the next GL frame */

void

Java_com_example_AndMii_DemoRenderer_nativeRender( JNIEnv*  env )

{

    curTime = ...

    appRender(curTime, sWindowWidth, sWindowHeight);



}
复制代码C 语言端 void appInit()

{



    glEnable(GL_NORMALIZE);

    glEnable(GL_DEPTH_TEST);

    glDisable(GL_CULL_FACE);

    glShadeModel(GL_FLAT);



    glEnable(GL_LIGHTING);

    glEnable(GL_LIGHT0);

    glEnable(GL_LIGHT1);

    glEnable(GL_LIGHT2);



    glEnableClientState(GL_VERTEX_ARRAY);

    glEnableClientState(GL_COLOR_ARRAY);



}







// Called from the app framework.

/* The tick is current time in milliseconds, width and height

* are the image dimensions to be rendered.

*/

void appRender(long tick, int width, int height)

{



    // Prepare OpenGL ES for rendering of the frame.

    prepareFrame(width, height);



    // Configure environment.

    configureLightAndMaterial();



    // Draw all the models normally.

    drawModels(1);



}



static void prepareFrame(int width, int height)

{

    glViewport(0, 0, width, height);



    glClearColorx((GLfixed)(0.1f * 65536),

                  (GLfixed)(0.2f * 65536),

                  (GLfixed)(0.3f * 65536), 0x10000);

    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);



    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

    gluPerspective(45, (float)width / height, 0.5f, 150);



    glMatrixMode(GL_MODELVIEW);



    glLoadIdentity();

}



static void configureLightAndMaterial()

{

    static GLfixed light0Position[] = { -0x40000, 0x10000, 0x10000, 0 };

    static GLfixed light0Diffuse[] = { 0x10000, 0x6666, 0, 0x10000 };

    static GLfixed light1Position[] = { 0x10000, -0x20000, -0x10000, 0 };

    static GLfixed light1Diffuse[] = { 0x11eb, 0x23d7, 0x5999, 0x10000 };

    static GLfixed light2Position[] = { -0x10000, 0, -0x40000, 0 };

    static GLfixed light2Diffuse[] = { 0x11eb, 0x2b85, 0x23d7, 0x10000 };

    static GLfixed materialSpecular[] = { 0x10000, 0x10000, 0x10000, 0x10000 };



    glLightxv(GL_LIGHT0, GL_POSITION, light0Position);

    glLightxv(GL_LIGHT0, GL_DIFFUSE, light0Diffuse);

    glLightxv(GL_LIGHT1, GL_POSITION, light1Position);

    glLightxv(GL_LIGHT1, GL_DIFFUSE, light1Diffuse);

    glLightxv(GL_LIGHT2, GL_POSITION, light2Position);

    glLightxv(GL_LIGHT2, GL_DIFFUSE, light2Diffuse);

    glMaterialxv(GL_FRONT_AND_BACK, GL_SPECULAR, materialSpecular);



    glMaterialx(GL_FRONT_AND_BACK, GL_SHININESS, 60 << 16);

    glEnable(GL_COLOR_MATERIAL);

}





static void drawModels(float zScale)

{



    glVertexPointer(......);

    glColorPointer(......);



    if (normalArray != NULL)

    {

        glNormalPointer(GL_FIXED, 0, normalArray);

        glEnableClientState(GL_NORMAL_ARRAY);

    }

    else

        glDisableClientState(GL_NORMAL_ARRAY);



    glDrawArrays(GL_TRIANGLES, 0, object->count);







}
复制代码
调试
要想在 jni native 代码中看打印信息,printf 是不行的,需使用 __android_log_print,如下所示。

__android_log_print(ANDROID_LOG_INFO, &quotrojectName", "I am : %d\n", n);
复制代码
该函数与 printf 用法相似,使用格式字符。打印的结果通过 logcat 查看。注意,使用时需要将头文件 android/log.h 包含进来。为方便使用,往往定义一些宏 #include <android/log.h>



#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "ProjectName", __VA_ARGS__)

#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG  , "ProjectName", __VA_ARGS__)

#define LOGI(...) __android_log_print(ANDROID_LOG_INFO   , "ProjectName", __VA_ARGS__)

#define LOGW(...) __android_log_print(ANDROID_LOG_WARN   , "ProjectName", __VA_ARGS__)

#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR  , "ProjectName", __VA_ARGS__)
复制代码
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2025-1-11 11:00 , Processed in 0.384221 second(s), 46 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表