【发布时间】:2020-10-25 15:26:41
【问题描述】:
这是我的 OBJ 文件加载器
我是用 opengles 做的
我正在尝试完全制作 obj loader
但结果是纹理混乱
我认为问题在于顶点位置归一化问题
然后最终我的纹理结果程序搞砸了
我很失望
如何在android中制作纹理
有什么问题?
这个 obj 加载器类
[1]: https://i.stack.imgur.com/bOsFv.png
for (String line : object) {
if (line.startsWith("v") && !line.contains("t") && !line.contains("n")) {
String[] data = line.split("\\s+");
for (int i = 0; i < data.length; i++) {
if (!data[i].contains("v")) {
vertice[vstep++] = Float.parseFloat(data[i]);
if (max < Float.parseFloat(data[i]))
max = Float.parseFloat(data[i]);
}
}
}
}
vstep = 0;
for (String line : object) {
if (line.startsWith("v") && !line.contains("t") && !line.contains("n")) {
String[] data = line.split("\\s+");
for (int i = 0; i < data.length; i++) {
if (!data[i].contains("v"))
vertice[vstep++] = Float.parseFloat(data[i]) / max;
}
}
}
for (String line : object) {
if (line.startsWith("vt")) {
String[] data = line.split("\\s+");
temptexcoord[tstep][0] = Float.parseFloat(data[1]);
step][1] = 1 - Float.parseFloat(data[2]);
tstep++;
}
}
int count = 0;
int tcount = 0;
for (String line : object) {
if (line.startsWith("f")) {
String[] data = line.split("\\s+");
String[] info;
int step = 0;
if (data.length == 4) {
info = data[1].split("/");
face[count++] = (short) (Short.parseShort(info[0]) - (short) 1);
info = data[2].split("/");
face[count++] = (short) (Short.parseShort(info[0]) - (short) 1);
info = data[3].split("/");
face[count++] = (short) (Short.parseShort(info[0]) - (short) 1);
}
if (data.length == 5) {
//first triangle
info = data[1].split("/");
face[count++] = (short) (Short.parseShort(info[0]) - (short) 1);
info = data[2].split("/");
face[count++] = (short) (Short.parseShort(info[0]) - (short) 1);
info = data[3].split("/");
face[count++] = (short) (Short.parseShort(info[0]) - (short) 1);
//second triangle
info = data[1].split("/");
face[count++] = (short) (Short.parseShort(info[0]) - (short) 1);
info = data[3].split("/");
face[count++] = (short) (Short.parseShort(info[0]) - (short) 1);
info = data[4].split("/");
face[count++] = (short) (Short.parseShort(info[0]) - (short) 1);
}
}
}
for (String line : object) {
if (line.startsWith("f")) {
String[] data = line.split("\\s+");
String[] info;
int step = 0;
if (data.length == 4) {
info = data[1].split("/");
step = Integer.parseInt(info[1]) - 1;
texcoord[tcount++] = temptexcoord[step][0];
texcoord[tcount++] = temptexcoord[step][1];
info = data[2].split("/");
step = Integer.parseInt(info[1]) - 1;
texcoord[tcount++] = temptexcoord[step][0];
texcoord[tcount++] = temptexcoord[step][1];
info = data[3].split("/");
step = Integer.parseInt(info[1]) - 1;
texcoord[tcount++] = temptexcoord[step][0];
texcoord[tcount++] = temptexcoord[step][1];
}
if (data.length == 5) {
//first triangle
info = data[1].split("/");
step = Integer.parseInt(info[1]) - 1;
texcoord[tcount++] = temptexcoord[step][0];
texcoord[tcount++] = temptexcoord[step][1];
info = data[2].split("/");
step = Integer.parseInt(info[1]) - 1;
texcoord[tcount++] = temptexcoord[step][0];
texcoord[tcount++] = temptexcoord[step][1];
info = data[3].split("/");
step = Integer.parseInt(info[1]) - 1;
texcoord[tcount++] = temptexcoord[step][0];
texcoord[tcount++] = temptexcoord[step][1];
//second triangle
info = data[1].split("/");
step = Integer.parseInt(info[1]) - 1;
texcoord[tcount++] = temptexcoord[step][0];
texcoord[tcount++] = temptexcoord[step][1];
info = data[3].split("/");
step = Integer.parseInt(info[1]) - 1;
texcoord[tcount++] = temptexcoord[step][0];
texcoord[tcount++] = temptexcoord[step][1];
info = data[4].split("/");
step = Integer.parseInt(info[1]) - 1;
texcoord[tcount++] = temptexcoord[step][0];
texcoord[tcount++] = temptexcoord[step][1];
}
}//if end
}
}
}
这个 opengles 渲染类
public class model {
public float[] mModelMatrix = new float[16];
private FloatBuffer vertexBuffer;
private ShortBuffer indexBuffer;
private FloatBuffer textureBuffer;
static int COORDS_PER_VERTEX=3;
private int vertexStride=COORDS_PER_VERTEX*4;
static int COORDS_PER_TEXTURE=2;
private int textureStride=COORDS_PER_TEXTURE*4;
static public int colors;
private int mProgram;
private String vertexShadeCode=
"uniform mat4 uMVPMatrix;"+
"attribute vec3 vPosition;" +
"attribute vec2 a_TexCoordinate;" +
"varying vec2 v_TexCoordinate;" +
"void main() {" +
" v_TexCoordinate = a_TexCoordinate;" +
" gl_Position = uMVPMatrix*vec4(vPosition,1.0);" +
"}";
private String fragmentShadeCode= "precision highp float;" +
"uniform vec4 vColor;" +
"uniform sampler2D u_Texture;" +
"varying vec2 v_TexCoordinate;" +
"void main() {" +
"vec4 texturecolor=texture2D(u_Texture, v_TexCoordinate);"+
" gl_FragColor =texturecolor;" +
"}";
private int mMVPMatrixHandle;
private int mPositionHandle;
private int mColorHandle;
private int textureDataHandle;
private int textureUniformHandle;
private int textureCoordinateHandle;
private float[] vertices;
private short[] indices;
float[] previewTexturCoordinateData;
public model(Context context)
{
int Imgwidth,ImgHeight;
textureDataHandle = loadTexture(context, R.drawable.dog);
Objectloader obj=new Objectloader(R.raw.dog,context);
vertices=obj.vertice;
indices=obj.face;
previewTexturCoordinateData=obj.texcoord;
Matrix.setIdentityM(mModelMatrix, 0);
ByteBuffer bf=ByteBuffer.allocateDirect(vertices.length*4);
bf.order(ByteOrder.nativeOrder());
vertexBuffer=bf.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
indexBuffer= ByteBuffer.allocateDirect(indices.length *2).order(ByteOrder.nativeOrder()).asShortBuffer();
indexBuffer.put(indices).position(0);
ByteBuffer texCoordinates = ByteBuffer.allocateDirect(previewTexturCoordinateData.length * 4);
texCoordinates.order(ByteOrder.nativeOrder());
textureBuffer = texCoordinates.asFloatBuffer();
textureBuffer.put(previewTexturCoordinateData);
textureBuffer.position(0);
int vertexShader=MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER,
vertexShadeCode);
int fragmentshade=MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER,
fragmentShadeCode);
mProgram=GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram,vertexShader);
GLES20.glAttachShader(mProgram,fragmentshade);
GLES20.glLinkProgram(mProgram);
}
private int loadTexture(Context context,int ResourceID)
{
final int[] textureHandle = new int[1];
GLES20.glGenTextures(1, textureHandle, 0);
if (textureHandle[0] != 0)
{
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
// Read in the resource
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),ResourceID,options);
// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
// Set filtering
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap,0);
// Recycle the bitmap, since its data has been loaded into OpenGL.
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
bitmap.recycle();
}
if (textureHandle[0] == 0)
{
throw new RuntimeException("Error loading texture.");
}
return textureHandle[0];
}
public void draw(float[] mMVPMatrix)
{
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glUseProgram(mProgram);
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
textureCoordinateHandle = GLES20.glGetAttribLocation(mProgram, "a_TexCoordinate");
GLES20.glEnableVertexAttribArray(textureCoordinateHandle);
GLES20.glVertexAttribPointer(textureCoordinateHandle,COORDS_PER_TEXTURE, GLES20.GL_FLOAT, false,
textureStride, textureBuffer);
textureUniformHandle = GLES20.glGetUniformLocation(mProgram, "u_Texture");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureDataHandle);
GLES20.glUniform1i(textureUniformHandle, 0);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
// GLES20.GL_TRIANGLES : 삼각형채우기,
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_SHORT,indexBuffer);
// GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0,indices.length);
GLES20.glFlush();
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
【问题讨论】:
标签: android parsing opengl-es textures loader