我有以下纹理:
我正在尝试让纹理中的每个骰子面在OpenGL ES中呈现在立方体的每个面上。但是,使用我当前的代码,它呈现如下:
我知道我需要为每个面部获得纹理坐标,但每次我尝试扩展纹理坐标数组时,它都会破坏我的代码。
最终,如何在纹理文件中获取骰子的每个面部,在3D立方体的面上绘制?
这是3D立方体对象类:
public class Dice3D {
private FloatBuffer vertexBuffer; // Buffer for vertex-array
private FloatBuffer texBuffer; // Buffer for texture-coords-array (NEW)
private float[] vertices = { // Vertices for a face
-1.0f, -1.0f, 0.0f, // 0. left-bottom-front
1.0f, -1.0f, 0.0f, // 1. right-bottom-front
-1.0f, 1.0f, 0.0f, // 2. left-top-front
1.0f, 1.0f, 0.0f // 3. right-top-front
};
float[] texCoords = { // Texture coords for the above face (NEW)
0.0f, 1.0f, // A. left-bottom (NEW)
1.0f, 1.0f, // B. right-bottom (NEW)
0.0f, 0.0f, // C. left-top (NEW)
1.0f, 0.0f // D. right-top (NEW)
};
int[] textureIDs = new int[1]; // Array for 1 texture-ID (NEW)
// Constructor - Set up the buffers
public Dice3D(Context context) {
// Setup vertex-array buffer. Vertices in float. An float has 4 bytes
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4 * 6);
vbb.order(ByteOrder.nativeOrder()); // Use native byte order
vertexBuffer = vbb.asFloatBuffer(); // Convert from byte to float
for (int face = 0; face < 6; face++) {
vertexBuffer.put(vertices);
}
vertexBuffer.position(0);
/*vertexBuffer.put(vertices); // Copy data into buffer
vertexBuffer.position(0); // Rewind*/
// Setup texture-coords-array buffer, in float. An float has 4 bytes (NEW)
ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4);
tbb.order(ByteOrder.nativeOrder());
texBuffer = tbb.asFloatBuffer();
texBuffer.put(texCoords);
texBuffer.position(0);
}
// Draw the shape
public void draw(GL10 gl) {
gl.glFrontFace(GL10.GL_CCW); // Front face in counter-clockwise orientation
gl.glEnable(GL10.GL_CULL_FACE); // Enable cull face
gl.glCullFace(GL10.GL_BACK); // Cull the back face (don't display)
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // Enable texture-coords-array (NEW)
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // Define texture-coords buffer (NEW)
// front
gl.glPushMatrix();
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
// left
gl.glPushMatrix();
gl.glRotatef(270.0f, 0.0f, 1.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
// back
gl.glPushMatrix();
gl.glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
// right
gl.glPushMatrix();
gl.glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
// top
gl.glPushMatrix();
gl.glRotatef(270.0f, 1.0f, 0.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
// bottom
gl.glPushMatrix();
gl.glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // Disable texture-coords-array (NEW)
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisable(GL10.GL_CULL_FACE);
}
// Load an image into GL texture
public void loadTexture(GL10 gl, Context context) {
gl.glGenTextures(1, textureIDs, 0); // Generate texture-ID array
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[0]); // Bind to texture ID
// Set up texture filters
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
// Allocate texture buffer
ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4 * 6);
tbb.order(ByteOrder.nativeOrder());
texBuffer = tbb.asFloatBuffer();
// All the 6 faces have the same texture coords, repeat 6 times
for (int face = 0; face < 6; face++) {
Log.i("Face", String.valueOf(face));
float[] texCoords = { // Texture coords for the above face (NEW)
0.0f, (5.0f-face)/6.0f, // A. left-bottom (NEW)
1.0f, (5.0f-face)/6.0f, // B. right-bottom (NEW)
0.0f, (6.0f-face)/6.0f, // C. left-top (NEW)
1.0f, (6.0f-face)/6.0f // D. right-top (NEW)
};
texBuffer.put(texCoords);
}
texBuffer.position(0); // Rewind
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer);
for (int face = 0; face < 6; face++) {
// Render each face in TRIANGLE_STRIP using 4 vertices
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, face*4, 4);
}
// Construct an input stream to texture image "res\drawable\nehe.png"
InputStream istream = context.getResources().openRawResource(R.drawable.completetexture);
Bitmap bitmap;
try {
// Read and decode input as bitmap
bitmap = BitmapFactory.decodeStream(istream);
} finally {
try {
istream.close();
} catch(IOException e) { }
}
// Build Texture from loaded bitmap for the currently-bind texture ID
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
}
}
答案 0 :(得分:1)
您必须分离多维数据集每个面的纹理坐标。立方体的每个部分沿垂直方向占据纹理的六分之一。
面部的纹理坐标为:
这意味着你可以为这样的面部调整纹理coordiantes:
for (int face = 0; face < 6; face++) {
float[] texCoords = { // Texture coords for the above face (NEW)
0.0f, (5.0f-face)/6.0f, // A. left-bottom (NEW)
1.0f, (5.0f-face)/6.0f, // B. right-bottom (NEW)
0.0f, (6.0f-face)/6.0f, // C. left-top (NEW)
1.0f, (6.0f-face)/6.0f // D. right-top (NEW)
};
texBuffer.put(texCoords);
}
当然,您还必须为每个面添加顶点坐标:
private float[] vertices = { // Vertices for a face
-1.0f, -1.0f, 0.0f, // 0. left-bottom-front
1.0f, -1.0f, 0.0f, // 1. right-bottom-front
-1.0f, 1.0f, 0.0f, // 2. left-top-front
1.0f, 1.0f, 0.0f // 3. right-top-front
};
for (int face = 0; face < 6; face++) {
vertexBuffer.put(vertices);
}
你必须为每个面绘制顶点数组的正确部分:
// front
gl.glPushMatrix();
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
// left
gl.glPushMatrix();
gl.glRotatef(270.0f, 0.0f, 1.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);
gl.glPopMatrix();
// back
gl.glPushMatrix();
gl.glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);
gl.glPopMatrix();
// right
gl.glPushMatrix();
gl.glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);
gl.glPopMatrix();
// top
gl.glPushMatrix();
gl.glRotatef(270.0f, 1.0f, 0.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);
gl.glPopMatrix();
// bottom
gl.glPushMatrix();
gl.glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);
gl.glPopMatrix();
请注意,您可以放弃所有矩阵旋转和平移操作,如果为每个面生成单独的顶点坐标,则可以通过单次调用gl.glDrawArrays
绘制整个多维数据集:
float[] vertices = { // Vertices for a face
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f
};
indices [] = {
0, 1, 2, 3, // front
4, 0, 6, 2, // left
5, 4, 7, 6, // back
1, 5, 3, 7, // right
2, 3, 6, 7, // top
4, 5, 0, 1 // bottom
}
for (int i = 0; i < 24; i++) {
int vi = indices[i]*3;
vertexBuffer.put(vertices[vi + 0]);
vertexBuffer.put(vertices[vi + 1]);
vertexBuffer.put(vertices[vi + 2]);
}
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 24);