It is interesting to create rich client application using eclipse platform. After you create your project using eclipse PDE, you would like to export your application as native application. In this recipe, i will show how i do it in my local environment.
First of all, we need to create plugin to hook production and application extension point. In the plugin,xml, it should have following entry sets.
<extension id="product" point="org.eclipse.core.runtime.products"> <product application="org.eclipse.trader.platform.application" name="RCP Product"> <property name="aboutText" value="RCP Mail template created by PDE"> </property> <property name="windowImages" value="icons/sample2.gif"> </property> <property name="aboutImage" value="product_lg.gif"> </property> <property name="appName" value="RCP Product"> </property> </product> </extension>
<extension id="application" point="org.eclipse.core.runtime.applications"> <application> <run class="org.eclipse.trader.platform.Application"> </run> </application> </extension>After those typical extension point, it is also necessary to include the common eclipse UI extension points: perspective, view, preference,commands, editor and etc. Your custom business logic can be build on those extension points.
Finally, product configuration has to be created to describe your rich client application and eclipse embeds "export" function to support product configuration file.It is easy to export your rich client application based on the product description.
<product name="RCP Product" id="org.eclipse.trader.platform.product" application="org.eclipse.trader.platform.application" version="1.0.0.qualifier" useFeatures="false" includeLaunchers="true"> <aboutInfo> <image path="product_lg.gif"/> <text> RCP Mail template created by PDE </text> </aboutInfo> <configIni use="default"> </configIni> <launcherArgs> <vmArgsMac>-XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts</vmArgsMac> </launcherArgs> <windowImages i16="icons/sample2.gif"/> <plugins> <plugin id="com.ibm.icu"/> <plugin id="javax.annotation"/> <plugin id="javax.inject"/> <plugin id="org.apache.batik.css"/> <plugin id="org.apache.batik.util"/> <plugin id="org.apache.batik.util.gui"/> <plugin id="org.eclipse.core.commands"/> <plugin id="org.eclipse.core.contenttype"/> <plugin id="org.eclipse.core.databinding"/> <plugin id="org.eclipse.core.databinding.observable"/> <plugin id="org.eclipse.core.databinding.property"/> <plugin id="org.eclipse.core.expressions"/> <plugin id="org.eclipse.core.jobs"/> <plugin id="org.eclipse.core.runtime"/> <plugin id="org.eclipse.core.runtime.compatibility.registry" fragment="true"/> <plugin id="org.eclipse.e4.core.commands"/> <plugin id="org.eclipse.e4.core.contexts"/> <plugin id="org.eclipse.e4.core.di"/> <plugin id="org.eclipse.e4.core.di.extensions"/> <plugin id="org.eclipse.e4.core.services"/> <plugin id="org.eclipse.e4.ui.bindings"/> <plugin id="org.eclipse.e4.ui.css.core"/> <plugin id="org.eclipse.e4.ui.css.swt"/> <plugin id="org.eclipse.e4.ui.css.swt.theme"/> <plugin id="org.eclipse.e4.ui.di"/> <plugin id="org.eclipse.e4.ui.model.workbench"/> <plugin id="org.eclipse.e4.ui.services"/> <plugin id="org.eclipse.e4.ui.widgets"/> <plugin id="org.eclipse.e4.ui.workbench"/> <plugin id="org.eclipse.e4.ui.workbench.renderers.swt"/> <plugin id="org.eclipse.e4.ui.workbench.swt"/> <plugin id="org.eclipse.e4.ui.workbench3"/> <plugin id="org.eclipse.emf.common"/> <plugin id="org.eclipse.emf.ecore"/> <plugin id="org.eclipse.emf.ecore.change"/> <plugin id="org.eclipse.emf.ecore.xmi"/> <plugin id="org.eclipse.equinox.app"/> <plugin id="org.eclipse.equinox.common"/> <plugin id="org.eclipse.equinox.ds"/> <plugin id="org.eclipse.equinox.event"/> <plugin id="org.eclipse.equinox.preferences"/> <plugin id="org.eclipse.equinox.registry"/> <plugin id="org.eclipse.equinox.util"/> <plugin id="org.eclipse.help"/> <plugin id="org.eclipse.jface"/> <plugin id="org.eclipse.jface.databinding"/> <plugin id="org.eclipse.osgi"/> <plugin id="org.eclipse.osgi.services"/> <plugin id="org.eclipse.swt"/> <plugin id="org.eclipse.swt.win32.win32.x86" fragment="true"/> <plugin id="org.eclipse.trader.platform"/> <plugin id="org.eclipse.ui"/> <plugin id="org.eclipse.ui.workbench"/> <plugin id="org.w3c.css.sac"/> <plugin id="org.w3c.dom.smil"/> <plugin id="org.w3c.dom.svg"/> </plugins> </product>
之前在学习Android的时候有写过如果在Android中使用OpenGL,当时完全都是用java语言来实现的,现在我们用NDK来实现一次。
实现的思路就是将渲染器中的onDrawFrame,onSurfaceChanged,onSurfaceCreated分别在C中实现,然后将C编译成.so文件之后在Java中直接调用相应的函数就可以了。
步骤就不详细叙述了,代码贴一下。
主Activity:
package com.empty.ndkgl; import com.example.ndkgl.R; import android.opengl.GLSurfaceView; import android.os.Bundle; import android.app.Activity; import android.view.Menu; public class NdkGlActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); GLSurfaceView surface = new GLSurfaceView(this); surface.setRenderer(new NdkGlRender()); setContentView(surface); } static { //load library System.loadLibrary("NdkGLRenderer"); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_ndkgl, menu); return true; } }
Render类代码:
package com.empty.ndkgl; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.opengl.GLSurfaceView.Renderer; public class NdkGlRender implements Renderer{ //declare native function native private void onNdkSurfaceCreated (); native private void onNdkSurfaceChanged (int width, int height); native private void onNdkDrawFrame(); @Override public void onDrawFrame(GL10 arg0) { // TODO Auto-generated method stub onNdkDrawFrame (); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { // TODO Auto-generated method stub onNdkSurfaceChanged (width, height); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { // TODO Auto-generated method stub onNdkSurfaceCreated (); } }
在工程目录下创建jni文件夹,用下面的命令生成.h文件。
javah -classpath bin/classes -d jni com.empty.ndkgl.NdkGlRender
根据头文件来创建.c文件。
注:虽然生产的 .h文件在编译的时候并没有什么作用,但还是建议做这一步,因为.c文件中的函数名一定要和.h文件中的函数名一致,最后的程序才能正常运行,不然会出现如
java.lang.UnsatisfiedLinkError的bug。
#include <jni.h> #include <GLES/gl.h> unsigned int vbo[2]; float positions[12] = {1,-1,0, 1,1,0, -1,-1,0, -1,1,0}; short indices [4] = {0,1,2,3}; JNIEXPORT void JNICALL Java_com_empty_ndkgl_NdkGlRender_onNdkSurfaceCreated (JNIEnv* env, jobject obj) { //生成两个缓存区对象 glGenBuffers (2, vbo); //绑定第一个缓存对象 glBindBuffer (GL_ARRAY_BUFFER, vbo[0]); //创建和初始化第一个缓存区对象的数据 glBufferData (GL_ARRAY_BUFFER, 4*12, positions, GL_STATIC_DRAW); //绑定第二个缓存对象 glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, vbo[1]); //创建和初始化第二个缓存区对象的数据 glBufferData (GL_ELEMENT_ARRAY_BUFFER, 2*4, indices, GL_STATIC_DRAW); } JNIEXPORT void JNICALL Java_com_empty_ndkgl_NdkGlRender_onNdkSurfaceChanged(JNIEnv* env, jobject obj, jint width, jint height) { //图形最终显示到屏幕的区域的位置、长和宽 glViewport (0,0,width,height); //指定矩阵 glMatrixMode (GL_PROJECTION); //将当前的矩阵设置为glMatrixMode指定的矩阵 glLoadIdentity (); glOrthof(-2, 2, -2, 2, -2, 2); } JNIEXPORT void JNICALL Java_com_empty_ndkgl_NdkGlRender_onNdkDrawFrame (JNIEnv* env, jobject obj) { //启用顶点设置功能,之后必须要关闭功能 glEnableClientState (GL_VERTEX_ARRAY); //清屏 glClearColor (0,0,1,1); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode (GL_MODELVIEW); glLoadIdentity (); glBindBuffer (GL_ARRAY_BUFFER, vbo[0]); //定义顶点坐标 glVertexPointer (3, GL_FLOAT, 0, 0); glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, vbo[1]); //按照参数给定的值绘制图形 glDrawElements (GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0); //关闭顶点设置功能 glDisableClientState(GL_VERTEX_ARRAY); }
编写Android.mk
#FileName:Android.mk #Description:makefile of NdkGl LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := NdkGLRenderer LOCAL_SRC_FILES := com_empty_ndkgl_NdkGlRender.c LOCAL_LDLIBS := -lGLESv1_CM include $(BUILD_SHARED_LIBRARY)
编译库
$NDK_ROOT/ndk-build
在Eclipse中运行程序
通过修改.c的实现,我们就可以绘制不同的图形。
比如网格圆球:
#include <jni.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <math.h> #include <GLES/gl.h> typedef unsigned char byte; typedef struct { GLfloat x,y,z; } XYZ; float rotateQuad; #define PI 3.14159265 #define DTOR PI/180 static byte indices[8]={0,1,1,2,2,3,3,0}; //索引数组 void CreateUnitSphere(int dtheta,int dphi) { int n; int theta,phi; XYZ p[4]; for (theta=-90;theta<=90-dtheta;theta+=dtheta) { for (phi=0;phi<=360-dphi;phi+=dphi) { n = 0; p[n].x = cos(theta*DTOR) * cos(phi*DTOR); p[n].y = cos(theta*DTOR) * sin(phi*DTOR); p[n].z = sin(theta*DTOR); n++; p[n].x = cos((theta+dtheta)*DTOR) * cos(phi*DTOR); p[n].y = cos((theta+dtheta)*DTOR) * sin(phi*DTOR); p[n].z = sin((theta+dtheta)*DTOR); n++; p[n].x = cos((theta+dtheta)*DTOR) * cos((phi+dphi)*DTOR); p[n].y = cos((theta+dtheta)*DTOR) * sin((phi+dphi)*DTOR); p[n].z = sin((theta+dtheta)*DTOR); n++; if (theta >=-90 && theta <= 90) { p[n].x = cos(theta*DTOR) * cos((phi+dphi)*DTOR); p[n].y = cos(theta*DTOR) * sin((phi+dphi)*DTOR); p[n].z = sin(theta*DTOR); n++; } /* Do something with the n vertex facet p */ glVertexPointer(3, GL_FLOAT, 0, p); glDrawElements(GL_LINES, 8, GL_UNSIGNED_BYTE, indices); } } } JNIEXPORT void JNICALL Java_com_empty_ndkgl_NdkGlRender_onNdkSurfaceCreated (JNIEnv* env, jobject obj) { // 启用阴影平滑 glShadeModel(GL_SMOOTH); // 黑色背景 glClearColor(0, 0, 0, 0); // 设置深度缓存 glClearDepthf(1.0f); // 启用深度测试 glEnable(GL_DEPTH_TEST); // 所作深度测试的类型 glDepthFunc(GL_LEQUAL); // 告诉系统对透视进行修正 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);} JNIEXPORT void JNICALL Java_com_empty_ndkgl_NdkGlRender_onNdkSurfaceChanged(JNIEnv* env, jobject obj, jint width, jint height) { //图形最终显示到屏幕的区域的位置、长和宽 glViewport (0,0,width,height); //指定矩阵 glMatrixMode (GL_PROJECTION); //将当前的矩阵设置为glMatrixMode指定的矩阵 glLoadIdentity (); glOrthof(-2, 2, -2, 2, -2, 2); } JNIEXPORT void JNICALL Java_com_empty_ndkgl_NdkGlRender_onNdkDrawFrame (JNIEnv* env, jobject obj) { //启用顶点设置功能,之后必须要关闭功能 glEnableClientState (GL_VERTEX_ARRAY); //清屏 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode (GL_MODELVIEW); glLoadIdentity (); glFrontFace(GL_CW); glRotatef(rotateQuad, 1.0f, 1.0f, 0.0f);//旋转效果 CreateUnitSphere(10,10); //关闭顶点设置功能 glDisableClientState(GL_VERTEX_ARRAY); rotateQuad -= 1.5f; }
立方体
#include <jni.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <math.h> #include <GLES/gl.h> #define col 1.0f #define pos 1.0f #define PI 3.14159265 static GLfloat vertex[] = { -pos,-pos,-pos, /*0*/ -pos,-pos,pos, /*1*/ pos,-pos,pos, /*2*/ pos,-pos,-pos, /*3*/ -pos,pos,-pos, /*4*/ -pos,pos,pos, /*5*/ pos,pos,pos, /*6*/ pos,pos,-pos, /*7*/ }; static GLfloat colors[] = { col,0,0,col, 0,col,0,col, 0,0,col,col, col,col,0,col, col,0,col,col, 0,col,col,col, 0,0,0,col, col,col,col,col, }; static GLubyte mindex[] = { 0,2,1, 0,3,2, 5,1,6, 6,1,2, 6,2,7, 7,2,3, 0,4,3, 4,7,3, 4,0,1, 4,1,5, 4,5,6, 4,6,7, }; static GLfloat angle = 0.0f; JNIEXPORT void JNICALL Java_com_empty_ndkgl_NdkGlRender_onNdkSurfaceCreated (JNIEnv* env, jobject obj) { // 启用阴影平滑 glShadeModel(GL_SMOOTH); // 黑色背景 glClearColor(0, 0, 0, 0); // 设置深度缓存 glClearDepthf(1.0f); // 启用深度测试 glEnable(GL_DEPTH_TEST); // 所作深度测试的类型 glDepthFunc(GL_LEQUAL); // 告诉系统对透视进行修正 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); } 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); } JNIEXPORT void JNICALL Jav
<style type="text/css" >
.wdqy
{
background-image: url(/images/Common/common.png);
background-repeat: no-repeat;
background-position: -35px -694px;
padding-right: 15px;
}
.wdqy:hover
{
background-image: url(/images/Common/common.png);
background-repeat: no-repeat;
background-position: -35px -753px;
padding-right: 15px;
}
</style>
当你用a标签 的时候 要写a:hover属性 那么 请加上 href属性 才会生效
<a href=/blog_article/"/index.html class="wdqy">aaa</a>