参考:contentprovider的学习实例总结 http://www.cnblogs.com/chenglong/articles/1892029.html
Android学习十九:ContentProvider初步 http://blog.sina.com.cn/s/blog_5688414b0100xagp.html
android 自定义 Content Provider示例 http://byandby.iteye.com/blog/837466
实例源码下载:http://download.csdn.net/detail/yang_hui1986527/4430639
Profile.java
package com.snowdream.contentprovider; import android.net.Uri; public class Profile { /** * 表格名称 */ public static final String TABLE_NAME = "profile"; /** * 列表一,_ID,自动增加 */ public static final String COLUMN_ID = "_id"; /** * 列表二,名称 */ public static final String COLUMN_NAME = "name"; public static final String AUTOHORITY = "com.snowdream.provider"; public static final int ITEM = 1; public static final int ITEM_ID = 2; public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.snowdream.profile"; public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.snowdream.profile"; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTOHORITY + "/profile"); }
package com.snowdream.contentprovider; import android.content.Context; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class DBHelper extends SQLiteOpenHelper { /** * 数据库名称 */ private static final String DATABASE_NAME = "test.db"; /** * 数据库版本 */ private static final int DATABASE_VERSION = 1; public DBHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) throws SQLException { //创建表格 db.execSQL("CREATE TABLE IF NOT EXISTS "+ Profile.TABLE_NAME + "("+ Profile.COLUMN_ID +" INTEGER PRIMARY KEY AUTOINCREMENT," + Profile.COLUMN_NAME +" VARCHAR NOT NULL);"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) throws SQLException { //删除并创建表格 db.execSQL("DROP TABLE IF EXISTS "+ Profile.TABLE_NAME+";"); onCreate(db); } }
MyProvider.java
package com.snowdream.contentprovider; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; public class MyProvider extends ContentProvider { DBHelper mDbHelper = null; SQLiteDatabase db = null; private static final UriMatcher mMatcher; static{ mMatcher = new UriMatcher(UriMatcher.NO_MATCH); mMatcher.addURI(Profile.AUTOHORITY,Profile.TABLE_NAME, Profile.ITEM); mMatcher.addURI(Profile.AUTOHORITY, Profile.TABLE_NAME+"/#", Profile.ITEM_ID); } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // TODO Auto-generated method stub return 0; } @Override public String getType(Uri uri) { switch (mMatcher.match(uri)) { case Profile.ITEM: return Profile.CONTENT_TYPE; case Profile.ITEM_ID: return Profile.CONTENT_ITEM_TYPE; default: throw new IllegalArgumentException("Unknown URI"+uri); } } @Override public Uri insert(Uri uri, ContentValues values) { // TODO Auto-generated method stub long rowId; if(mMatcher.match(uri)!=Profile.ITEM){ throw new IllegalArgumentException("Unknown URI"+uri); } rowId = db.insert(Profile.TABLE_NAME,null,values); if(rowId>0){ Uri noteUri=ContentUris.withAppendedId(Profile.CONTENT_URI, rowId); getContext().getContentResolver().notifyChange(noteUri, null); return noteUri; } throw new SQLException("Failed to insert row into " + uri); } @Override public boolean onCreate() { // TODO Auto-generated method stub mDbHelper = new DBHelper(getContext()); db = mDbHelper.getReadableDatabase(); return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // TODO Auto-generated method stub Cursor c = null; switch (mMatcher.match(uri)) { case Profile.ITEM: c = db.query(Profile.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder); break; case Profile.ITEM_ID: c = db.query(Profile.TABLE_NAME, projection,Profile.COLUMN_ID + "="+uri.getLastPathSegment(), selectionArgs, null, null, sortOrder); break; default: throw new IllegalArgumentException("Unknown URI"+uri); } c.setNotificationUri(getContext().getContentResolver(), uri); return c; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // TODO Auto-generated method stub return 0; } }
MainActivity.java
package com.snowdream.contentprovider; import com.snowdream.contentprovider.R; import android.app.ListActivity; import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.os.Bundle; import android.view.Menu; import android.widget.SimpleCursorAdapter; public class MainActivity extends ListActivity { private SimpleCursorAdapter adapter= null; private Cursor mCursor = null; private ContentResolver mContentResolver = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initData(); initAdapter(); } public void initData(){ mContentResolver = getContentResolver(); //填充数据 for (int i = 0; i < 100; i++) { ContentValues values = new ContentValues(); values.put(Profile.COLUMN_NAME, "张三"+i); mContentResolver.insert(Profile.CONTENT_URI, values); } } public void initAdapter(){ //查询表格,并获得Cursor //查询全部数据 mCursor = mContentResolver.query(Profile.CONTENT_URI, new String[]{Profile.COLUMN_ID,Profile.COLUMN_NAME}, null, null, null); //查询部分数据 //String selection = Profile.COLUMN_ID + " LIKE '%1'"; //mCursor = mContentResolver.query(Profile.CONTENT_URI, new String[]{Profile.COLUMN_ID,Profile.COLUMN_NAME}, selection, null, null); //查询一个数据 //Uri uri = ContentUris.withAppendedId(Profile.CONTENT_URI, 50); //mCursor = mContentResolver.query(uri, new String[]{Profile.COLUMN_ID,Profile.COLUMN_NAME}, null, null, null); startManagingCursor(mCursor); //设置adapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2, mCursor, new String[]{Profile.COLUMN_ID,Profile.COLUMN_NAME}, new int[]{android.R.id.text1,android.R.id.text2}); setListAdapter(adapter); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
预览效果:
当我们渲染一个完全封闭的物体的时候,多边形的背面都是隐藏的,我们无法看见。但是如果这个物体有一些空洞,那么一些背面就可以被看见了。然而因为这些多边形的法向量的方向在这个时候不是正确的,所以会渲染出错误的结果。为了合理的渲染这些背面,我们必须反转法向量,然后基于这些反转的法向量来计算光照。
下图显示了一个采用Phong光照模型绘制茶壶使用双面渲染与否的结果对比:
图一 使用双面渲染与不使用的效果对比
一、固定管线OpenGL实现双面渲染
在固定管线中,我们需要用一个函数来启用双面光照:
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
这样,OpenGL将会反转表面的法线的方向,表示背面多边形的法线。
实例:
void GLWidget::initLight() { GLfloat light_ambient[]={0.7,0.8,0.9,1.0}; GLfloat light_diffuse[]={1.0,1.0,1.0,1.0}; GLfloat light_specular[]={1.0,1.0,1.0,1.0}; GLfloat light_position[]={2.0,2.0,2.0,0.0}; GLfloat mat_diffuse[]={0.8,0.8,0.8,1.0}; glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient); glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse); glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular); glLightfv(GL_LIGHT0,GL_POSITION,light_position); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_AUTO_NORMAL); glEnable(GL_NORMALIZE); //glEnable(GL_CULL_FACE); //启用双面光照 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE); glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,mat_diffuse); }效果:
二、可编程管线OpenGL实现双面渲染
假设我们的光照(采用Phong光照模型)计算是基于顶点的。在顶点着色器中,我们需要为每个顶点分别计算两次:front face和back face。两次计算采用的法向量不同。
#version 400 layout (location = 0) in vec3 VertexPosition; layout (location = 1) in vec3 VertexNormal; out vec3 FrontColor; out vec3 BackColor; struct LightInfo{ vec4 Position; vec3 La; vec3 Ld; vec3 Ls; }; uniform LightInfo Light; struct MaterialInfo{ vec3 Ka; vec3 Kd; vec3 Ks; float Shininess; }; uniform MaterialInfo Material; uniform mat4 ModelViewMatrix; uniform mat3 NormalMatrix; uniform mat4 ProjectionMatrix; uniform mat4 MVP; //转化到视空间 void getEyeSpace(out vec3 tnorm,out vec4 eyeCoords) { //convert normal and position to eye coords tnorm = normalize(NormalMatrix * VertexNormal); eyeCoords = ModelViewMatrix * vec4(VertexPosition,1.0); } //计算Phong光照模型 vec3 phongModel(vec4 eyeCoords,vec3 tnorm) { vec3 s = normalize(vec3(Light.Position - eyeCoords)); vec3 v = normalize(-eyeCoords.xyz); vec3 r = reflect(-s,tnorm); vec3 ambient = Light.La * Material.Ka; float sDotN = max(dot(s,tnorm),0.0); vec3 diffuse = Light.Ld * Material.Kd * sDotN; vec3 specular = vec3(0.0); if(sDotN > 0) specular = Light.Ls * Material.Ks * pow(max(dot(r,v),0.0),Material.Shininess); return (ambient + diffuse + specular); } void main() { vec3 tnorm; vec4 eyeCoords; getEyeSpace(tnorm,eyeCoords); FrontColor = phongModel(eyeCoords,tnorm); BackColor = phongModel(eyeCoords,-tnorm); gl_Position = MVP * vec4(VertexPosition,1.0); }在片断着色器中,我们根据关键字gl_FrontFacing的值来为片断赋予颜色值。
gl_FrontFacing是GLSL内置的关键字,它代表图元是面向光源还是背向光源。
片断着色器 twosided.frag:
#version 400 in vec3 FrontColor; in vec3 BackColor; layout (location = 0) out vec4 FragColor; void main() { if(gl_FrontFacing) { FragColor = vec4(FrontColor,1.0); } else { FragColor = vec4(BackColor,1.0); } }
//The font information include: //Ex, 4E00 is the chinese character “一” bbw=16, bbh=16, bbx=0, bby=0, width=16 //Comments: we can image the screen is big area, a font will take a rectangular //which have start coordination< x,y >, with and height. the font are a series binary data which 1 is //showing a point in current screen, 0 is showing nothing on the screen on the 16X16 screen erea. 0x0000, //16 bit size 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfffe, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, u4E00_4E5A_font_offset.h //Just include the value of a series font offset from 0X4E00~0X4E5A. // Ex, 11904, /* (0x4e00) */ ..... 0 /* (0x4e5a) */ “乙” u4E00_4E5A_font_width.h //Just include the value of a series font with 16, /* (0x4e00) */ ...... 8 /* (0x4e5a) */ “乙”
T_FontBmInfo MMI_lcd_get_font_Bm_data(UINT16 wUnicode) { UINT8 i = 0; INT32 wOffset = -1; INT32 wLocalOffset = -1; T_FontBmInfo tFontBmInfo; //Please add the detail comments at here!! for (i = 0; g_tFontTable[i].bCodeType != 0xFF ; i++) { //Please add the detail comments at here!! if (wUnicode >= g_tFontTable[i].bCodeStart && wUnicode <= g_tFontTable[i].bCodeEnd) { //Please add the detail comments at here!! wOffset = wUnicode - g_tFontTable[i].bCodeStart; if(g_tFontTable[i].bdwOffset[wOffset]) //check all table until find it. { break; } else { //Please add the detail comments at here!! wOffset = -1; } } else { //Please add the detail comments at here!! wOffset = -1; } } if (-1 == wOffset) { wOffset = 32; i = 0; } wLocalOffset = g_tFontTable[i].bdwOffset[wOffset]-g_tFontTable[i].bdwOffset[0]; tFontBmInfo.bWidth = g_tFontTable[i].baWidth[wOffset]; tFontBmInfo.pwFontBm = (UINT16 *)(&g_tFontTable[i].baFontRowData[wLocalOffset]); tFontBmInfo.bHeight = LCD_DEFAULT_FONT_HEIGHT; return tFontBmInfo; }
void MMI_lcd_show_font_Bm(UINT16 wShowPos, T_FontBmInfo *ptFontBmInfo, UINT16 wFwdColor, UINT16 wBackColor) { UINT8 bLoopHeight = 0; UINT8 bLoopWidth = 0; UINT8 i = 0; UINT16 wFontword; UINT16 wOffset = 0; UINT16 wLcdPointIndex = wShowPos; T_ALLCDRect tRect; //write font bitmap to lcd //Please add the detail comments at here!! for (bLoopHeight = 0; bLoopHeight < ptFontBmInfo->bHeight; bLoopHeight++) { //Please add the detail comments at here!! for (bLoopWidth = 0; bLoopWidth < ptFontBmInfo->bWidth; bLoopWidth+=16) { //Please add the detail comments at here!! wFontword = ptFontBmInfo->pwFontBm[wOffset]; //Please add the detail comments at here!! for (i = 0; i < min(16, ptFontBmInfo->bWidth-bLoopWidth); i++) { //Please add the detail comments at here!! if (((wLcdPointIndex) > (AL_PLCD_MAX_WIDTH * AL_PLCD_MAX_HEIGHT - 1)) || (wLcdPointIndex < 0)) { return; } if (wFontword & 0x8000)//Please add the detail comments at here!! { g_waLcdPanelBuf[wLcdPointIndex] = wFwdColor; } else { if (wFwdColor != wBackColor) { g_waLcdPanelBuf[wLcdPointIndex] = wBackColor; } } wFontword <<= 1; wLcdPointIndex++; }// for (i = 0; i < min(16, ptFontBmInfo->bWidth-bLoopWidth); i++) wOffset++; }// for (bLoopWidth = 0; bLoopWidth < ptFontBmInfo->bWidth; bLoopWidth+=16) wLcdPointIndex += (AL_PLCD_MAX_WIDTH - ptFontBmInfo->bWidth); }// for (bLoopHeight = 0; bLoopHeight < ptFontBmInfo->bHeight; bLoopHeight++) //Please add the detail comments at here!! Mmi_lcd_request_refresh(tRect); }