2012年11月26日 星期一
Android: View Bitmap Canvas與Drawable
View:Android顯示畫面的容器,可以是內建任何繼承View的元件,像是ImageView GridView Button等,也可以是自建繼承View的類別
Bitmap:可視為儲存圖片畫素內容的物件,它可以將許多不同格式的圖片轉換成串流(0與1)讓系統可以看得懂
Canvas:可視為畫布或是小畫家工具,你可以在上面話一條線,一個圓或是任何東西,畫完之後再將他奘到容器裡顯示,通常是在自建的View中顯示,然後當程式執行時便會呼叫這個新類別的onDraw()方法自動繪製
Drawable:Android提供了許多不同框架的Drawable物件可供使用,像BitmapDrawable, ScaleDrawable, ShapeDrawable等等等...使用方法通常是直接將Drawable直接設定給容器即可(像是ImageView)
Android: Reflection效果
View:Android顯示畫面的容器,可以是內建任何繼承View的元件,像是ImageView GridView Button等,也可以是自建繼承View的類別
Bitmap:可視為儲存圖片畫素內容的物件,它可以將許多不同格式的圖片轉換成串流(0與1)讓系統可以看得懂
Canvas:可視為畫布或是小畫家工具,你可以在上面話一條線,一個圓或是任何東西,畫完之後再將他奘到容器裡顯示,通常是在自建的View中顯示,然後當程式執行時便會呼叫這個新類別的onDraw(Canvas canvas)方法自動繪製
Drawable:Android提供了許多不同框架的Drawable物件可供使用,像BitmapDrawable, ScaleDrawable, ShapeDrawable等等等...使用方法通常是直接將Drawable直接設定給容器即可(像是ImageView)
這個例子特別的點是在, 通常我們為了達到彈性需求(不想用內建的容器像ImageView、GridView、ListView、Button、EditText...
所以會是利用一個類別繼承View來當成容器,然後利用Canvas畫完之後,再將他裝到自建的容器中顯示,通常的做法是在@override中的onDraw(Canvas canvas)中,這個參數傳進來的canvas可視為一張撲滿螢幕的大畫布利用各式的Drawable物件將Canvas給畫出
package com.briview.reflection;
import ...
public class MainActivity extends Activity {
private ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.imageView1);
Bitmap bmp = ((BitmapDrawable) getResources().getDrawable(R.drawable.a))
.getBitmap();
imageView.setImageBitmap(createReflectedImage(bmp));
}
/*
* public static Bitmap createBitmap (Bitmap source, int x, int y, int
* width, int height, Matrix m, boolean filter) 須注意以下規則 x + width <=
* bmp.getWidth(); y + height <= bmp.getHeight();
*/
private Bitmap createReflectedImage(Bitmap originalImage) {
int width = originalImage.getWidth();
int height = originalImage.getHeight();
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
/*
* create bitmap object
*/
Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,
height / 2, width, height / 2, matrix, false);
// 創建總圖片(原圖片 + 倒影圖片)
Bitmap finalReflection = Bitmap.createBitmap(width,
(height + height / 2), Config.ARGB_8888);
Paint shaderPaint = new Paint();
// 創建線性漸變LinearGradient物件
LinearGradient shader = new LinearGradient(0,
originalImage.getHeight(), 0, finalReflection.getHeight() + 1,
0x70ffffff, 0x00ffffff, TileMode.MIRROR);
shaderPaint.setShader(shader);
// 漸層效果!!
shaderPaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
// 畫布畫出反轉圖片大小區域,然後把漸變效果加到其中,就出現了圖片的倒
影效果。
/*
* draw on the canvas
*/
// 創建畫布
Canvas canvas = new Canvas(finalReflection);
canvas.drawBitmap(originalImage, 0, 0, null);
canvas.drawBitmap(reflectionImage, 0, height + 1, null);
canvas.drawRect(0, height + 1, width, finalReflection.getHeight(),
shaderPaint);
return finalReflection;
}
}
標籤:Android
Android,
Android UI
2012年11月21日 星期三
Android:[轉]OpenGL 投影方式
Ref: http://fansofjava.iteye.com/blog/1499991
关于android的投影矩阵,一般有两种,一种是矩阵投影,另一种是透视投影。
矩阵投影主要用于2D画面,但指定此投影的方式却有多种方式,而且对于初入门的人来说,也不容易理解,可以使用glOrthof,此方法使用方式大概如下:
上面的glOrthof最后两个参数用于设置Z轴坐标,在2D画面中使用1与-1即可。
除了这种方式外,还可以通过一个叫GLU的工具类来指定投影的显示,用法如下:
上面的gluOrtho2D方法相对来说简化了一下。
在3D的画面中,也有两种方式,一种是使用glFrustumf方法,用法如下:
这个ratio表示宽度与高度的比,glFrustumf方法的前两个参数分别代表左右方向,因为高度与宽度不一样,所以这个ratio是为了限制场景宽度而必须存在的。第三四个参数分别代表Y的下上方向,而最后两个参数则代表Z轴的近远方向。这个近与远不是很好理解的话请看下图:
上面这个图也把Viewport与场景区分开了。
除了使用glFrustumf外,也可以使用工具类GLU里面的方法gluPerspective,此方法参数如下:
其中第二个参数表示角度,即视图的角度。而aspect则表示宽度与高度比,即与上面的ratio一样。但这些参数最好还是配上一个图,下面的图来自最后链接文章,个人觉得很形象的说明了这些参数的意思。
我们观察平面的裁剪窗口的大小和屏幕的大小可以一致,也可以有差别. 但为了使得最终的效果基本一致,所以,一般设置成它们具有相同的 aspect(横纵比 w/h), 从而它们的转换关系就是等比例的放大或者缩小,而不会产生扭曲.
对于3D图形来说,除了设置视图投影以外,还得设置整个游戏模型的浏览角度,这个会涉及到一个很重要的方法GLU.gluLookAt,这个方法的参数形式如下:
参数很多,但参数作用主要分为三部分(gl不算)。
eye系列坐标用于设置整个视野所参照的原点坐标。
center系列坐标用于设置浏览游戏角色的方向,这个方向坐标就是相对于eye系统坐标的。
up系列坐标则用于设置浏览者(镜头)相对于原点(eye系列)的坐标。
下图可供参考:
因此在3D环境中,整个游戏的视图设置大概就像下面这样,先设置投影矩阵下整个游戏的面板的显示,再设置为模型矩阵,显示3D模型的轮廓:
关于android的投影矩阵,一般有两种,一种是矩阵投影,另一种是透视投影。
矩阵投影主要用于2D画面,但指定此投影的方式却有多种方式,而且对于初入门的人来说,也不容易理解,可以使用glOrthof,此方法使用方式大概如下:
- GL10 gl = glGraphics.getGL();
- gl.glViewport(0, 0, glGraphics.getWidth(), glGraphics.getHeight());
- gl.glMatrixMode(GL10.GL_PROJECTION);
- gl.glLoadIdentity();
- //以左下角为原点
- gl.glOrthof(0, //left
- width, //right
- 0, //bottom
- height, //top
- 1, -1);
- gl.glMatrixMode(GL10.GL_MODELVIEW);
- gl.glLoadIdentity();
上面的glOrthof最后两个参数用于设置Z轴坐标,在2D画面中使用1与-1即可。
除了这种方式外,还可以通过一个叫GLU的工具类来指定投影的显示,用法如下:
- gl.glViewport(0, 0, glGraphics.getWidth(), glGraphics.getHeight());
- gl.glMatrixMode(GL10.GL_PROJECTION);
- gl.glLoadIdentity();
- GLU.gluOrtho2D(gl, left, right, bottom, top);
- gl.glMatrixMode(GL10.GL_MODELVIEW);
- gl.glLoadIdentity();
上面的gluOrtho2D方法相对来说简化了一下。
在3D的画面中,也有两种方式,一种是使用glFrustumf方法,用法如下:
- gl.glViewport(0, 0, width, height);
- float ratio = (float) width / height;
- gl.glMatrixMode(GL10.GL_PROJECTION);
- gl.glLoadIdentity();
- gl.glFrustumf(-ratio, ratio, -1, 1, 1, 20);
这个ratio表示宽度与高度的比,glFrustumf方法的前两个参数分别代表左右方向,因为高度与宽度不一样,所以这个ratio是为了限制场景宽度而必须存在的。第三四个参数分别代表Y的下上方向,而最后两个参数则代表Z轴的近远方向。这个近与远不是很好理解的话请看下图:
上面这个图也把Viewport与场景区分开了。
除了使用glFrustumf外,也可以使用工具类GLU里面的方法gluPerspective,此方法参数如下:
其中第二个参数表示角度,即视图的角度。而aspect则表示宽度与高度比,即与上面的ratio一样。但这些参数最好还是配上一个图,下面的图来自最后链接文章,个人觉得很形象的说明了这些参数的意思。
引用
我们观察平面的裁剪窗口的大小和屏幕的大小可以一致,也可以有差别. 但为了使得最终的效果基本一致,所以,一般设置成它们具有相同的 aspect(横纵比 w/h), 从而它们的转换关系就是等比例的放大或者缩小,而不会产生扭曲.
对于3D图形来说,除了设置视图投影以外,还得设置整个游戏模型的浏览角度,这个会涉及到一个很重要的方法GLU.gluLookAt,这个方法的参数形式如下:
- void android.opengl.GLU.gluLookAt(GL10 gl, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)
参数很多,但参数作用主要分为三部分(gl不算)。
eye系列坐标用于设置整个视野所参照的原点坐标。
center系列坐标用于设置浏览游戏角色的方向,这个方向坐标就是相对于eye系统坐标的。
up系列坐标则用于设置浏览者(镜头)相对于原点(eye系列)的坐标。
下图可供参考:
因此在3D环境中,整个游戏的视图设置大概就像下面这样,先设置投影矩阵下整个游戏的面板的显示,再设置为模型矩阵,显示3D模型的轮廓:
- public void setMatrices(GL10 gl) {
- gl.glMatrixMode(GL10.GL_PROJECTION);
- gl.glLoadIdentity();
- GLU.gluPerspective(gl, fieldOfView, aspectRatio, near, far);
- gl.glMatrixMode(GL10.GL_MODELVIEW);
- gl.glLoadIdentity();
- GLU.gluLookAt(gl, position.x, position.y, position.z, lookAt.x, lookAt.y, lookAt.z, up.x, up.y, up.z);
- }
標籤:Android
轉載,
Android(OpenGL)
Eclipse:Android專案匯入問題 gen already exists but is not a source folder. Convert to a source folder or rename it"
Try this, it helped me:
- Right click on the project and go to "Properties"
- Select "Java Build Path" on the left
- Open "Source" tab
- Click "Add Folder..."
- Check "gen" folder and click Ok and Ok again
- Again right click on the project and in the "Andriod Tools" click on "Fix Project Properties"
2012年11月19日 星期一
Android:OpenGL Cube
package com.example.opengltest2;
import ...
public class Cube {
// 頂點座標
float cubeVtx[] = { -1.0f, 1.0f, -1.0f, // v0
-1.0f, 1.0f, 1.0f, // v1
1.0f, 1.0f, 1.0f, // v2
1.0f, 1.0f, -1.0f, // v3
-1.0f, -1.0f, -1.0f, // v4
-1.0f, -1.0f, 1.0f, // v5
1.0f, -1.0f, 1.0f, // v6
1.0f, -1.0f, -1.0f }; // v7
private float colors[] = {
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
1.0f, 0.5f, 0.0f, 1.0f,
1.0f, 0.5f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f
};
// 頂點索引
short cubeInx[] = { 0, 1, 2, // Top_Face1
0, 2, 3, // Top_Face2
4, 6, 5, // Bottom_Face1
4, 7, 6, // Bottom_Face2
2, 6, 7, // Left_face1
2, 7, 3, // Left_Face2
0, 4, 1, // Right_Face1
1, 4, 5, // Right_Face2
1, 5, 6, // Front_Face1
1, 6, 2, // Front_Face2
0, 3, 4, // Back_Face1
3, 7, 4 }; // Back_Face2
// 點的緩衝區
private FloatBuffer vertexBuffer;
//顏色的緩衝區
private FloatBuffer colorBuffer;
// 索引值緩衝區
private ShortBuffer indexBuffer;
public cube() {
// 初始化頂點緩衝
ByteBuffer bb = ByteBuffer.allocateDirect(cubeVtx.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(cubeVtx);
vertexBuffer.position(0);
//初始化顏色資料緩衝
ByteBuffer cb = ByteBuffer.allocateDirect(colors.length * 4);
cb.order(ByteOrder.nativeOrder());
colorBuffer = cb.asFloatBuffer();
colorBuffer.put(colors);
colorBuffer.position(0);
// 初始化索引緩衝
ByteBuffer ib = ByteBuffer.allocateDirect(cubeInx.length * 2);
ib.order(ByteOrder.nativeOrder());
indexBuffer = ib.asShortBuffer();
indexBuffer.put(cubeInx);
indexBuffer.position(0);
}
public void draw(GL10 gl) {
// 逆時鐘
gl.glFrontFace(GL10.GL_CCW);
// 啟動CULL_FACE
gl.glEnable(GL10.GL_CULL_FACE);
// 刪除多邀形的背景
gl.glCullFace(GL10.GL_BACK);
// 啟動點的緩衝區
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
// 為畫筆指定頂點位置和資料格式
//啟動顏色的緩衝區
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
//為畫筆指定頂點顏色資料
gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
// 以三點劃出三角形
gl.glDrawElements(GL10.GL_TRIANGLES, cubeInx.length,
GL10.GL_UNSIGNED_SHORT, indexBuffer);
}
}
public class OpenGLRenderer implements Renderer {
Cube cube;
public OpenGLRenderer() {
// 初始化
cube1=new cube();
}
@Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
// 清除螢幕和深度緩衝區
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// 以單位矩陣取代目前的矩陣
gl.glLoadIdentity();
// Z軸轉置 10單位
gl.glTranslatef(0, 0, -10);
//可以加上這段讓Cube不斷旋轉
long time = SystemClock.uptimeMillis()% 4000L;
float angle = 0.090f * ((int)time);
gl.glRotatef(angle, 1.0f, 0.0f, 0.0f);
gl.glRotatef(angle, 0.0f, 1.0f, 0.0f);
gl.glRotatef(angle, 0.0f, 0.0f, 1.0f);
cube1.draw(gl);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
// 設定新視域視窗的大小
gl.glViewport(0, 0, width, height);
// 選擇投射的陣列模式
gl.glMatrixMode(GL10.GL_PROJECTION);
// 重設投射陣
gl.glLoadIdentity();
// 計算視窗的寬高比率
GLU.gluPerspective(gl, 45.0f, (float) width / (float) height, 0.1f,
100.0f);
//float ratio=(float)width/height;//比例大小
//gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);//設定投影模式
// 選擇MODELVIEW陣列
gl.glMatrixMode(GL10.GL_MODELVIEW);
// 重設MODELVIEW陣列
gl.glLoadIdentity();
}
註;可以透過openGL Transformation函式或是投影操作, 讓Cube效果更顯著
標籤:Android
Android(OpenGL)
2012年11月13日 星期二
Android:OpenGL 座標變換
*注意要領*
- 注意glPushMatrix以及glPopMatrix的交互使用配合以建構出設想的模式
- glTranslatef (float x, float y, float z) 平移座標軸
- glRotatef(float angle, float x, float y, float z) 旋轉座標軸
- glScalef (float x, float y, float z) 縮大或放小
- 可以透過不斷的改變角度或其他參數來達到動態的效果
OpenGLRenderer
package com.example.opengltest2;
import ...
public class OpenGLRenderer implements Renderer {
private Square square;
private float angle=0;
public OpenGLRenderer() {
// 初始化
square = new Square();
}
@Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
// 清除螢幕和深度緩衝區
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// 以單位矩陣取代目前的矩陣
gl.glLoadIdentity();
gl.glTranslatef(0, 0, -10);//Z軸轉置10單位
//第一個方形,儲存目前陣列
gl.glPushMatrix();
//逆時鐘旋轉
gl.glRotatef(angle, 0, 0, 1);
//畫出第一個方形
square.draw(gl);
//復原回最後的矩陣
gl.glPopMatrix();
//第二個方形,儲存目前陣列
gl.glPushMatrix();
//先旋轉再移動,旋轉時讓第二個方形繞著第一個方形旋轉
gl.glRotatef(-angle, 0, 0, 1);
gl.glTranslatef(2, 0, 0);
//調整大小為第一個方型的一半
gl.glScalef(.5f, .5f, .5f);
square.draw(gl);
// 第三個方形
// 存儲目前陣列
gl.glPushMatrix();
// 讓第三個方形圍繞著第二個方形旋轉
gl.glRotatef(-angle, 0, 0, 1);
// 移動第三個方形
gl.glTranslatef(2, 0, 0);
// 調整其大小為第二個方形的一半
gl.glScalef(.5f, .5f, .5f);
// 以自己為中心旋轉,12倍目的是為了自轉比較快的效果
gl.glRotatef(angle * 12, 0, 0, 1);
// 畫出第三個方形.
square.draw(gl);
// 復原成第三個方形前的矩陣
gl.glPopMatrix();
// 復原成第二個方形前的矩陣
gl.glPopMatrix();
angle++;//讓圖形不斷的旋轉
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
// 設定新視域視窗的大小
gl.glViewport(0, 0, width, height);
// 選擇投射的陣列模式
gl.glMatrixMode(GL10.GL_PROJECTION);
// 重設投射陣
gl.glLoadIdentity();
// 計算視窗的寬高比率
GLU.gluPerspective(gl, 45.0f, (float) width / (float) height, 0.1f,
100.0f);
//float ratio=(float)width/height;//比例大小
//gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);//設定投影模式
// 選擇MODELVIEW陣列
gl.glMatrixMode(GL10.GL_MODELVIEW);
// 重設MODELVIEW陣列
gl.glLoadIdentity();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
// 設定背景顏色為黑色, 格式是RGBA
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
// 設定流暢的陰影模式
gl.glShadeModel(GL10.GL_SMOOTH);
// 深度緩區的設定
gl.glClearDepthf(1.0f);
// 啟動深度的測試
gl.glEnable(GL10.GL_DEPTH_TEST);
// GL_LEQUAL深度函式測試
gl.glDepthFunc(GL10.GL_LEQUAL);
// 設定很好的角度計算模式
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
}
}
標籤:Android
Android(OpenGL)
Android:OpenGL 加上顏色
package com.example.opengltest2;
import ...
public class Square {
// 點的陣列
private float vertices[] = { -1.0f, 1.0f, 0.0f, // 0, 左上角
-1.0f, -1.0f, 0.0f, // 1, 左下角
1.0f, -1.0f, 0.0f, // 2, 右下角
1.0f, 1.0f, 0.0f, // 3, 右上角
};
// 顏色的陣列(RGBA)
float[] color=new float[]{
1.0f,0.0f,0.0f,1.0f,//左上角
0.0f,1.0f,0.0f,1.0f,//左下角
0.0f,0.0f,1.0f,1.0f,//右下角
1.0f,1.0f,0.0f,1.0f //右上角
};
// 連接點的次序
private short[] indices = { 0, 1, 2, 0, 2, 3 };
// 點的緩衝區
private FloatBuffer vertexBuffer;
// 顏色的緩衝區
private FloatBuffer colorBuffer;
// 索引值緩衝區
private ShortBuffer indexBuffer;
public Square() {
//初始化頂點座標暫存
// 浮點數是4位元組因此需要把點陣列長度乘以4
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());//設定為本機平台的位元組順序
vertexBuffer = vbb.asFloatBuffer();//轉換為float形式的緩衝,並建立實例
vertexBuffer.put(vertices);//將頂點座標陣列放進緩衝
vertexBuffer.position(0);////設定緩衝區的起始位置
//初始化座標顏色暫存,浮點數是4位元組因此需要把點陣列長度乘以4
ByteBuffer cbb=ByteBuffer.allocateDirect(color.length*4);
cbb.order(ByteOrder.nativeOrder());
colorBuffer=cbb.asFloatBuffer();
colorBuffer.put(color);
colorBuffer.position(0);
////初始化構造索引資料緩衝
// 短整數是2位元組因此需要把點陣列長度乘以2
ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
ibb.order(ByteOrder.nativeOrder());
indexBuffer = ibb.asShortBuffer();
indexBuffer.put(indices);
indexBuffer.position(0);
}
/**
* 畫圖函式
*
* @param gl
*/
public void draw(GL10 gl) {
// 逆時鐘
gl.glFrontFace(GL10.GL_CCW);
// 啟動CULL_FACE
gl.glEnable(GL10.GL_CULL_FACE);
// 刪除多邀形的背景
gl.glCullFace(GL10.GL_BACK);
// 啟動點的緩衝區
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
// 為畫筆指定頂點位置和資料格式
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
//啟動顏色的緩衝區
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
//為畫筆指定頂點顏色資料
gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
// 以三點劃出三角形
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length,
GL10.GL_UNSIGNED_SHORT, indexBuffer);
// 除能點的緩衝區
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
// 除能CULL_FACE
gl.glDisable(GL10.GL_CULL_FACE);
}
}
標籤:Android
Android(OpenGL)
訂閱:
文章 (Atom)



