编写GeoView.java:
public class GeoView extends View {
private Paint mPaint = null;
public GeoView(Context context) {
super(context);
mPaint = new Paint();
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
//设置画布颜色
canvas.drawColor(Color.WHITE);
//取消锯齿效果
mPaint.setAntiAlias(true);
//设置画笔格式为空心
mPaint.setStyle(Paint.Style.STROKE);
//创建外面大口
Rect bigRect = new Rect();
bigRect.left = 10;
bigRect.top = 10;
bigRect.right = 90;
bigRect.bottom = 100;
mPaint.setColor(Color.RED);
canvas.drawRect(bigRect, mPaint);
//画左边撇
canvas.drawLine( 15,40,40,10, mPaint);
//画右边捺
canvas.drawLine(60, 10, 85, 40, mPaint);
//创建里面小口
Rect smallRect = new Rect();
smallRect.left = 25;
smallRect.top = 60;
smallRect.right = 75;
smallRect.bottom = 95;
canvas.drawRect(smallRect, mPaint);
}
编写GeoFigureActivity.java,通过该类创建并显示一个GeoView控件:
public class GeoFigureActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeoView geoView = new GeoView(this);
setContentView(geoView);
}
}
编写main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<com.sharpandroid.geofigure.GeoView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
编写GeoFigureActivity.java:
public class GeoFigureActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
编写MatrixActivity.java:
package com.sharpandroid.matrix;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
public class MatrixActivity extends Activity {
private MatrixView matrixView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
matrixView = new MatrixView(this);
setContentView(matrixView);
}
public boolean onKeyUp(int keyCode, KeyEvent event) {
super.onKeyUp(keyCode, event);
return true;
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (matrixView == null) {
return false;
}
if (keyCode == KeyEvent.KEYCODE_BACK) {
this.finish();
return true;
}
//将按键事件传递给matrixView处理
return matrixView.onKeyDown(keyCode, event);
}
public class MatrixView extends View implements Runnable {
// 声明Bitmap对象
Bitmap bicycle = null;
int bicycleWidth = 0;
int bicycleHeight = 0;
float angle = 0.0f;
float scale = 1.0f;
// 构建Matrix对象
Matrix mMatrix = new Matrix();
public MatrixView(Context context) {
super(context);
//装载资源
bicycle = ((BitmapDrawable) getResources().getDrawable
(R.drawable.bicycle))
.getBitmap();
// 得到图片的宽度和高度
bicycleWidth = bicycle.getWidth();
bicycleHeight = bicycle.getHeight();
// 开启线程
new Thread(this).start();
}
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 重置mMatrix
mMatrix.reset();
// 设置旋转
mMatrix.setRotate(angle);
// 设置缩放比例
mMatrix.postScale(scale, scale);
// 按mMatrix的变形要求构建新的Bitmap
Bitmap mbicycle2 = Bitmap.createBitmap(bicycle, 0, 0,
bicycleWidth,
bicycleHeight, mMatrix, true);
//绘制变形之后的图片
drawImage(canvas, mbicycle2, 10, 10);
mbicycle2 = null;
}
// 按键按下事件
public boolean onKeyDown(int keyCode, KeyEvent event) {
// 左方向键
if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
angle = angle - 20;
}
// 右方向键
else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
angle = angle + 20;
}
// 左方向键
else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
if (scale > 0.5) {
scale = scale - 0.2f;
}
}
// 右方向键
else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
if (scale < 2.0) {
scale = scale + 0.2f;
}
}
return true;
}
/**
* 线程处理,不断刷新界面
*/
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 使用postInvalidate可以直接在线程中更新界面
postInvalidate();
}
}
/**
* 绘制一个Bitmap
*
* @param canvas
* 画布
* @param bitmap
* 图片
* @param x
* 屏幕上的x坐标
* @param y
* 屏幕上的y坐标
*/
public void drawImage(Canvas canvas, Bitmap bitmap, int x, int y) {
/* 绘制图像 */
canvas.drawBitmap(bitmap, x, y, null);
}
}
}
1.通过Java代码实现Tween指令完成动画
编写TweenActivity.java:
package com.sharpandroid.tween;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
public class TweenActivity extends Activity {
private View mBicycleView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBicycleView = new BicycleView(this);
setContentView(mBicycleView);
}
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (mBicycleView == null) {
return false;
}
mBicycleView.onKeyUp(keyCode, event);
return true;
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (mBicycleView == null) {
return false;
}
if (keyCode == KeyEvent.KEYCODE_BACK) {
this.finish();
return true;
}
return super.onKeyDown(keyCode, event);
}
public class BicycleView extends View {
// 定义一个Alpha动画
private Animation mAnimationAlpha = null;
// 定义一个Scale动画
private Animation mAnimationScale = null;
// 定义一个Translate动画
private Animation mAnimationTranslate = null;
// 定义一个Rotate动画
private Animation mAnimationRotate = null;
// 定义一个AnimationSet对象,该对象可以同时完成几种动画效果
private AnimationSet as= null;
// 定义Bitmap对象
Bitmap mBicycle = null;
public BicycleView(Context context) {
super(context);
// 加载图片
mBicycle = ((BitmapDrawable) getResources().getDrawable(
R.drawable.bicycle)).getBitmap();
// 创建Alpha动画
mAnimationAlpha = new AlphaAnimation(0.1f, 1.0f);
// 设置动画持续的时间
mAnimationAlpha.setDuration(1000*4);
// 创建Scale动画
mAnimationScale = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f,
Animation.RELATIVE_TO_SELF, 0.7f,
Animation.RELATIVE_TO_SELF, 0.7f);
// 设置动画持续的时间
mAnimationScale.setDuration(1000*6);
// 创建Translate动画
mAnimationTranslate = new TranslateAnimation(5, 200, 4, 150);
// 设置动画持续的时间
mAnimationTranslate.setDuration(1000*6);
// 创建Rotate动画
mAnimationRotate = new RotateAnimation(0.0f, +360.0f,
Animation.RELATIVE_TO_SELF, 0.3f,
Animation.RELATIVE_TO_SELF, 0.3f);
// 设置动画持续的时间
mAnimationRotate.setDuration(1000*4);
// 创建一个AnimationSet对象,该对象可以同时完成几种动画效果
as = new AnimationSet(true);
as.addAnimation(mAnimationAlpha);
as.addAnimation(mAnimationRotate);
as.addAnimation(mAnimationScale);
as.addAnimation(mAnimationTranslate);
// 设置动画持续的时间
as.setDuration(1000*4);
}
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 绘制图片
canvas.drawBitmap(mBicycle, 0, 0, null);
}
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
// 开始播放动画
this.startAnimation(mAnimationScale);
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
// 开始播放动画
this.startAnimation(mAnimationTranslate);
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
// 开始播放动画
this.startAnimation(mAnimationAlpha);
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
// 开始播放动画
this.startAnimation(mAnimationRotate);
break;
case KeyEvent.KEYCODE_DPAD_CENTER:
this.startAnimation(as);
break;
}
return true;
}
}
}
2.通过XML定义Tween指令完成动画
(1)alpha_animation.xml。
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<alpha
android:fromAlpha="0.1"
android:toAlpha="1.0"
android:duration="4000"
/>
</set>
(2)rotate_animation.xml。
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
android:fromDegrees="0"
android:toDegrees="+360"
android:pivotX="30%"
android:pivotY="30%"
android:duration="4000" />
</set>
(3)scale_animation.xml。
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:fromXScale="0.0"
android:toXScale="1.0"
android:fromYScale="0.0"
android:toYScale="1.0"
android:pivotX="70%"
android:pivotY="70%"
android:fillAfter="false"
android:duration="6000" />
</set>
(4)translate_animation.xml。
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="5"
android:toXDelta="200"
android:fromYDelta="4"
android:toYDelta="150"
android:duration="6000"
/>
</set>
(5)com.xml。
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:fromAlpha="0.1"
android:toAlpha="1.0"
android:duration="4000"/>
<rotate
android:fromDegrees="0"
android:toDegrees="+360"
android:pivotX="30%"
android:pivotY="30%"
android:duration="4000"/>
<scale
android:fromXScale="0.0"
android:toXScale="1.0"
android:fromYScale="0.0"
android:toYScale="1.0"
android:pivotX="70%"
android:pivotY="70%"
android:fillAfter="false"
android:duration="6000" />
<translate
android:fromXDelta="5"
android:toXDelta="200"
android:fromYDelta="4"
android:toYDelta="150"
android:duration="6000"/>
</set>
编写TweenByXmlActivity.java类:
package com.sharpandroid.tweenbyxml;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
public class TweenByXmlActivity extends Activity {
private View mBicycleView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBicycleView = new BicycleView(this);
setContentView(mBicycleView);
}
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (mBicycleView == null) {
return false;
}
mBicycleView.onKeyUp(keyCode, event);
return true;
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (mBicycleView == null) {
return false;
}
if (keyCode == KeyEvent.KEYCODE_BACK) {
this.finish();
return true;
}
return super.onKeyDown(keyCode, event);
}
public class BicycleView extends View {
// 定义一个Alpha动画
private Animation mAnimationAlpha = null;
// 定义一个Scale动画
private Animation mAnimationScale = null;
// 定义一个Translate动画
private Animation mAnimationTranslate = null;
// 定义一个Rotate动画
private Animation mAnimationRotate = null;
// 定义一个AnimationSet对象,该对象可以同时完成几种动画效果
private AnimationSet as= null;
// 定义Bitmap对象
Bitmap mBicycle = null;
public BicycleView(Context context) {
super(context);
// 加载图片
mBicycle = ((BitmapDrawable) getResources().getDrawable(
R.drawable.bicycle)).getBitmap();
// 加载Alpha动画
mAnimationAlpha = AnimationUtils.loadAnimation
(TweenByXmlActivity.this,R.anim.alpha_animation);
// 设置动画持续的时间
mAnimationAlpha.setDuration(1000*4);
// 加载Scale动画
mAnimationScale = AnimationUtils.loadAnimation
(TweenByXmlActivity.this,R.anim.scale_animation);
// 设置动画持续的时间
mAnimationScale.setDuration(1000*6);
// 加载Translate动画
mAnimationTranslate = AnimationUtils.loadAnimation
(TweenByXmlActivity.this,R.anim.translate_animation);
// 设置动画持续的时间
mAnimationTranslate.setDuration(1000*6);
// 加载Rotate动画
mAnimationRotate = AnimationUtils.loadAnimation
(TweenByXmlActivity.this,R.anim.rotate_animation);
// 设置动画持续的时间
mAnimationRotate.setDuration(1000*4);
// 加载一个AnimationSet对象,该对象可以同时完成几种动画效果
as = (AnimationSet) AnimationUtils.loadAnimation
(TweenByXmlActivity.this,R.anim.com);
}
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 绘制图片
canvas.drawBitmap(mBicycle, 0, 0, null);
}
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
// 开始播放动画
this.startAnimation(mAnimationScale);
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
// 开始播放动画
this.startAnimation(mAnimationTranslate);
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
// 开始播放动画
this.startAnimation(mAnimationAlpha);
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
// 开始播放动画
this.startAnimation(mAnimationRotate);
break;
case KeyEvent.KEYCODE_DPAD_CENTER:
this.startAnimation(as);
break;
}
return true;
}
}
}
1.通过Java代码实现Frame动画
编写FrameActivity.java类:
package com.sharpandroid.frame;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
public class FrameActivity extends Activity {
private FrameView birdView;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
birdView = new FrameView(this);
setContentView(birdView);
}
public boolean onKeyUp(int keyCode, KeyEvent event)
{
if ( birdView == null )
{
return false;
}
birdView.onKeyUp(keyCode,event);
return true;
}
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if ( birdView == null )
{
return false;
}
if ( keyCode == KeyEvent.KEYCODE_BACK)
{
this.finish();
return true;
}
return super.onKeyDown(keyCode, event);
}
public class FrameView extends View
{
// 定义AnimationDrawable动画
private AnimationDrawable frameAnimation = null;
Context mContext = null;
// 定义一个Drawable对象
Drawable birdItem = null;
public FrameView(Context context)
{
super(context);
mContext = context;
//实例化AnimationDrawable对象
frameAnimation = new AnimationDrawable();
//装载资源
//这里用一个循环了装载所有名字类似的资源
//如"bird1…5.png"的图片,5张图片鸟的翅膀从上到下
//之后再从bird4…1.png倒序,翅膀从下往上
//共循环9次,完成翅膀"上-下-上"的整个循环
for (int i = 1; i <= 9; i++)
{
int j=0;
//这样完成从4-1倒序一遍
if(i <= 5)
{
j = i;
}else{
j = 10 - i;
}
//根据给定的资源名称返回一个资源标识符,即其在R文件中对应的常量的值
//第一个参数表示给定的资源的名称
//第二个参数表示需要获取的资源类型,本例为"drawable"型
//第三个参数表示应用包的路径
int id = getResources().getIdentifier("bird" + j,
"drawable", mContext.getPackageName());
birdItem = getResources().getDrawable(id);
//为动画添加一帧
//参数birdItem是该帧的图片内容
//参数300/j是该帧所显示的毫秒数,由于j是一个先增大后边小的过程
//因此,每幅图片显示的时间会先减小后增大
//也即切换图片的速度先增大后减小
frameAnimation.addFrame(birdItem, 300/j);
}
// 设置播放模式是否只播放一次,false表示重复播放,而true表示只播放一次
frameAnimation.setOneShot(false);
//设置将要显示的动画
this.setBackgroundDrawable(frameAnimation);
}
public void onDraw(Canvas canvas)
{
super.onDraw(canvas);
}
public boolean onKeyUp(int keyCode, KeyEvent event)
{
switch ( keyCode )
{
case KeyEvent.KEYCODE_DPAD_UP:
// 开始播放动画
frameAnimation.start();
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
//停止播放动画
frameAnimation.stop();
break;
}
return true;
}
}
}
2.通过XML定义Frame完成动画
编写fram.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/bird1" android:duration="300" />
<item android:drawable="@drawable/bird2" android:duration="150" />
<item android:drawable="@drawable/bird3" android:duration="100" />
<item android:drawable="@drawable/bird4" android:duration="75" />
<item android:drawable="@drawable/bird5" android:duration="60" />
<item android:drawable="@drawable/bird4" android:duration="75" />
<item android:drawable="@drawable/bird3" android:duration="100" />
<item android:drawable="@drawable/bird2" android:duration="150" />
<item android:drawable="@drawable/bird1" android:duration="300" />
</animation-list>
编写FrameByXMLActivity.java:
package com.sharpandroid.framebyxml;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.widget.ImageView;
public class FrameByXMLActivity extends Activity {
private FrameView birdView;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
birdView = new FrameView(this);
setContentView(birdView);
}
public boolean onKeyUp(int keyCode, KeyEvent event)
{
if ( birdView == null )
{
return false;
}
birdView.onKeyUp(keyCode,event);
return true;
}
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if ( birdView == null )
{
return false;
}
if ( keyCode == KeyEvent.KEYCODE_BACK)
{
this.finish();
return true;
}
return super.onKeyDown(keyCode, event);
}
public class FrameView extends View
{
// 定义AnimationDrawable逐帧动画
private AnimationDrawable frameAnimation = null;
Context mContext = null;
public FrameView(Context context)
{
super(context);
mContext = context;
//定义一个ImageView用来存放动画
ImageView img = new ImageView(mContext);
//将定义的frame.xml文件传入img作为其背景
img.setBackgroundResource(R.anim.frame);
//通过ImageView的getBackground方法获取到Frame动画
frameAnimation = (AnimationDrawable) img.getBackground();
//将该动画指定为屏幕的背景
this.setBackgroundDrawable(frameAnimation);
}
public void onDraw(Canvas canvas)
{
super.onDraw(canvas);
}
public boolean onKeyUp(int keyCode, KeyEvent event)
{
switch ( keyCode )
{
case KeyEvent.KEYCODE_DPAD_UP:
// 开始播放动画
frameAnimation.start();
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
//停止播放动画
frameAnimation.stop();
break;
}
return true;
}
}
}
43.3.3 代码详解
在Android中专门提供了GLSurfaceView类,用来显示3D视图,在GLSurfaceView中有一个Renderer接口,GLSurfaceView.Renderer是一个通用的接口。使用setContentView()方法直接载入GLSurfaceView类的实例,而不用载入main.xml,代码如下:
OpenglActivity.java
package com.sharpandroid.opengl;
import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
public class OpenglActivity extends Activity {
/** Called when the activity is first created. */
MyRnderer render=new MyRnderer();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GLSurfaceView glView = new GLSurfaceView(this);
glView.setRenderer(render);
setContentView(glView);
}
}
43.3.5 颜色测试
MyRnderer的整体代码如下:
MyRnderer.java
public class MyRnderer implements Renderer {
int one=0x10000;
private IntBuffer pointers =IntBuffer.wrap(new int[]{ //顶点
one,one,0, //顶点A
-one,one,0, //顶点B
one,-one,0, //顶点D
-one,-one,0}); //顶点C
private IntBuffer colors = IntBuffer.wrap(new int[]{//颜色
one,0,0,one,
0,one,0,one,
0,0,one,one,
0,one,one,0
});
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
gl.glTranslatef(1.5f, 0.0f, -6.0f);
gl.glColorPointer(4, GL10.GL_FIXED, 0, colors);//定义颜色
gl.glVertexPointer(3, GL10.GL_FIXED, 0, pointers);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glDisableClientState(GL10.GL_COLOR_ARRAY);//取消定义颜色
// 取消顶点设置
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
float ratio = (float) width / height;
//设置OpenGL场景的大小
gl.glViewport(0, 0, width, height);
//设置投影矩阵
gl.glMatrixMode(GL10.GL_PROJECTION);
//重置投影矩阵
gl.glLoadIdentity();
// 设置视口的大小
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
// 选择模型观察矩阵
gl.glMatrixMode(GL10.GL_MODELVIEW);
// 重置模型观察矩阵
gl.glLoadIdentity();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glShadeModel(GL10.GL_SMOOTH); //设置阴影模式
gl.glClearColor(0, 0, 1, 0); // 蓝色背景
gl.glClearDepthf(1.0f); // 设置深度缓存
gl.glEnable(GL10.GL_DEPTH_TEST); // 开启深度测试
gl.glDepthFunc(GL10.GL_LEQUAL); // 深度测试的类型
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
//对透视进行修正
}
}
43.3.7 正方体测试
在SquareRenderer中加入构建的八个顶点的坐标,代码如下:
int one = 0x10000;
IntBuffer pointers = IntBuffer.wrap(new int[]{
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,
});
设置3D环境和正方形的一样,但是在绘制正方体的时候有所不同,正方体有六个面组成,要分别绘制出六个正方形,组成之后就是所要的正方体。代码如下:
package com.sharpandroid.opengl;
import java.nio.IntBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLSurfaceView.Renderer;
public class SquareRenderer implements Renderer {
float rotateTri, rotateQuad;
int texture = -1;
int one = 0x10000;
IntBuffer pointers = IntBuffer.wrap(new int[]{
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,
});
public void onDrawFrame(GL10 gl)
{
// 清除屏幕
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// 重置
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, -5.0f);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
//设置旋转
gl.glRotatef(1.0f, rotateQuad, 0.0f, 0.0f);
//设置和绘制正方形
gl.glVertexPointer(3, GL10.GL_FIXED, 0, pointers);
for(int i=0; i<6; i++)
{
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, i*4, 4);
}
//绘制正方形结束
gl.glFinish();
//取消顶点数组
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
rotateQuad += 0.5f;
//改变旋转的角度
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height)
{
// TODO Auto-generated method stub
float ratio = (float) width / height;
//设置OpenGL场景的大小
gl.glViewport(0, 0, width, height);
//设置投影矩阵
gl.glMatrixMode(GL10.GL_PROJECTION);
//重置投影矩阵
gl.glLoadIdentity();
// 设置视口的大小
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
// 选择模型观察矩阵
gl.glMatrixMode(GL10.GL_MODELVIEW);
// 重置模型观察矩阵
gl.glLoadIdentity();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
// 启用阴影平滑
gl.glShadeModel(GL10.GL_SMOOTH);
// 蓝色背景
gl.glClearColor(0, 0, 1, 0);
gl.glClearDepthf(1.0f);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthFunc(GL10.GL_LEQUAL);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
}
}
43.3.8 纹理映射测试
TestTexture的代码如下:
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLUtils;
import android.opengl.GLSurfaceView.Renderer;
public class TestTexture implements Renderer {
float x, y, z;
int texture = -1;
int one = 0x10000;
IntBuffer pointers = IntBuffer.wrap(new int[]{
-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,
});
IntBuffer texCoords = IntBuffer.wrap(new int[]{
one,0,0,0,0,one,one,one,
0,0,0,one,one,one,one,0,
one,one,one,0,0,0,0,one,
0,one,one,one,one,0,0,0,
0,0,0,one,one,one,one,0,
one,0,0,0,0,one,one,one,
});
ByteBuffer indices = ByteBuffer.wrap(new byte[]{
0,1,3,2,
4,5,7,6,
8,9,11,10,
12,13,15,14,
16,17,19,18,
20,21,23,22,
});
@Override
public void onDrawFrame(GL10 gl)
{
// 清除屏幕和深度缓存
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// 重置当前的模型观察矩阵
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, -5.0f);
gl.glRotatef(x, 1.0f, 0.0f, 0.0f);
gl.glRotatef(y, 0.0f, 1.0f, 0.0f);
gl.glRotatef(z, 0.0f, 0.0f, 1.0f);
// 绑定纹理
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//纹理和四边形对应的顶点
gl.glVertexPointer(3, GL10.GL_FIXED, 0, pointers);
gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, texCoords);
//绘制
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 24, GL10.GL_UNSIGNED_
BYTE, indices);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
x-=0.5f;
y-=0.5f;
z-=0.5f;
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height)
{
float ratio = (float) width / height;
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
// 蓝色背景
gl.glClearColor(0, 0, 1, 0);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glEnable(GL10.GL_DEPTH_TEST);
//启用纹理映射
gl.glClearDepthf(1.0f);
gl.glDepthFunc(GL10.GL_LEQUAL);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
//允许2D贴图,纹理
gl.glEnable(GL10.GL_TEXTURE_2D);
IntBuffer intBuffer = IntBuffer.allocate(1);
// 创建纹理
gl.glGenTextures(1, intBuffer);
texture = intBuffer.get();
// 设置要使用的纹理
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);
//生成纹理
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.bitmap, 0);
// 线形滤波
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_
FILTER, GL10.GL_LINEAR);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_
FILTER, GL10.GL_LINEAR);
}
}
43.3.9 光照测试
TestLight代码如下:
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLUtils;
import android.opengl.GLSurfaceView.Renderer;
public class TestLight implements Renderer {
float x, y, z;
int texture = -1;
int one = 0x10000;
//环境光
FloatBuffer light1 = FloatBuffer.wrap(new float[]{0.5f,0.5f,0.5f,
1.0f});
//漫射光
FloatBuffer light2 = FloatBuffer.wrap(new float[]{1.0f,1.0f,1.0f,
1.0f});
//光源位置
FloatBuffer lightPosition = FloatBuffer.wrap(new float[]{0.0f,
0.0f,2.0f,1.0f});
IntBuffer pointers = IntBuffer.wrap(new int[]{
-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,
});
IntBuffer texCoords = IntBuffer.wrap(new int[]{
one,0,0,0,0,one,one,one,
0,0,0,one,one,one,one,0,
one,one,one,0,0,0,0,one,
0,one,one,one,one,0,0,0,
0,0,0,one,one,one,one,0,
one,0,0,0,0,one,one,one,
});
ByteBuffer indices = ByteBuffer.wrap(new byte[]{
0,1,3,2,
4,5,7,6,
8,9,11,10,
12,13,15,14,
16,17,19,18,
20,21,23,22,
});
@Override
public void onDrawFrame(GL10 gl)
{
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_
BIT);
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, -5.0f);
gl.glRotatef(x, 1.0f, 0.0f, 0.0f);
gl.glRotatef(y, 0.0f, 1.0f, 0.0f);
gl.glRotatef(z, 0.0f, 0.0f, 1.0f);
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glVertexPointer(3, GL10.GL_FIXED, 0, pointers);
gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, texCoords);
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 24, GL10.GL_
UNSIGNED_BYTE, indices);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
x+=0.5f;
y+=0.5f;
gl.glEnable(GL10.GL_LIGHT1); // 启用一号光源
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height)
{
float ratio = (float) width / height;
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
gl.glClearColor(0, 0, 1, 0);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glClearDepthf(1.0f);
gl.glDepthFunc(GL10.GL_LEQUAL);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_
NICEST);
gl.glEnable(GL10.GL_TEXTURE_2D);
IntBuffer intBuffer = IntBuffer.allocate(1);
gl.glGenTextures(1, intBuffer);
texture = intBuffer.get();
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.bitmap, 0);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_
MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_
MAG_FILTER, GL10.GL_LINEAR);
//设置环境光
gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, light1);
//设置漫射光
gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, light2);
//设置光源的位置
gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, lightPosition);
//启用一号光源
gl.glEnable(GL10.GL_LIGHT1);
}
}