为了便于观察魔方扭转时各方块的所在位置,就在每个方块的面上贴了一个数字的图片。
由于手机程序在运行时经常会切换到其它的程序中运行如接电话,所以将生成数字图片的方法放到Render类的onSurfaceChanged方法中。
生成数字图片代码为:
int imgSize = 64;
int fontSize = 20;
Bitmap bitmap = Bitmap.createBitmap(imgSize, imgSize, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
//设置画布背景为透明,这样我们的纹理就只显示文字,而没有颜色背景
canvas.drawColor(Color.TRANSPARENT);
Paint p = new Paint();
//设置字体、字体大小和字体颜色
String familyName = "Times New Roman";
Typeface font = Typeface.create(familyName, Typeface.NORMAL);
p.setColor(Color.WHITE);
p.setTypeface(font);
p.setTextSize(fontSize);
//在Bitmap上绘制文字
String text = cube.id;
float textWidth = p.measureText(text);
canvas.drawText(cube.id,(imgSize - textWidth)/2,imgSize - fontSize, p);
cube.loadBitmap(bitmap);
将图片生成后,在onDrawFrame运行时:
if (bInitTexture) {
bInitTexture = false;
int[] textures = new int[1];
//生成纹理编号
gl.glGenTextures(1, textures, 0);
mTextureId = textures[0];
//绑定到GL10.GL_TEXTURE_2D
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);
/*
下一步需要给Texture填充设置参数,用来渲染的Texture可能比要渲染的区域大或者缩小,这是需要设置Texture需要放大或是缩小时OpenGL的模式:需要比较清晰的图像使用GL10.GL_NEAREST
*/
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR);
/*
如何去渲染这些不存在的Texture部分
有两种设置
GL_REPEAT 重复Texture。
GL_CLAMP_TO_EDGE 只靠边线绘制一次
*/
//水平方向靠边
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,GL10.GL_CLAMP_TO_EDGE);
//垂直方向重复
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,GL10.GL_REPEAT);
//纹理贴图和材质混合的方式,如果选择GL10.REPLACE则只显示纹理
gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,GL10.GL_MODULATE);
//然后是将Bitmap资源和Texture绑定起来
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mBitmap, 0);
}
//设置面的背景色
gl.glColor4f(color.red, color.green, color.blue, color.alpha);
//如果面的背景色不为黑色则贴图,黑色面为不可见区域:
if (!color.equals(GLColor.BLACK)) {
gl.glEnable(GL10.GL_TEXTURE_2D);
//启用纹理坐标数组
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// 每次绘图时都需要绑定
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);
// 获取纹理的UV坐标数组
FloatBuffer textureBuffer = getTextureBuffer();
textureBuffer.position(0);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
}
ShortBuffer indicesBuffer = getIndicesBuffer();
indicesBuffer.position(0);
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP,4, GL10.GL_UNSIGNED_SHORT, indicesBuffer);
if (!color.equals(GLColor.BLACK)) {
gl.glDisable(GL10.GL_TEXTURE_2D);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
UV Mapping
告知OpenGL库如何将Bitmap的像素映射到Mesh上。这可以分为两步来完成:
UV Mapping指将Bitmap的像素映射到Mesh上的顶点。UV坐标定义为左上角(0,0),右下角(1,1)(因为使用的2D Texture),下图坐标显示了UV坐标,右边为我们需要染色的平面的顶点顺序:
为了能正确的匹配,需要把UV坐标中的(0,1)映射到顶点0,(1,1)映射到顶点1等等。
float textureCoordinates[] = {0,1 , 1,1 , 1,0 , 0,0};
在本项目中由于顶点全部写到mVertexList中,所以设置UV坐标时要设置8个点,在贴图时不属于该面的点设为0,0即可。
如:
设定正面为逆时针方向
bottomFace.setIndices(new short[] { 4, 0, 5, 1, });
bottomFace.setTextureCoordinates(new float[] { 0,1 , 1,1, 0,0, 0,0, 0,0, 1,0, 0,0, 0,0});