扩展AndEngine渲染3D模型的问题
对于我在AndEngine游戏开发中写的一本书,我正在尝试开发一个示例AndEngine应用程序,演示如何导入和渲染3D模型。 为了导入,我使用了我为Android成功编译的Assimp库,并通过一个基于NDK的小型包装器在C ++中使用。
我正在导入的模型是使用其OBJ导出器从3DS Max 2013导出的基本茶壶模型。 在Java调试器中,得到的顶点,普通和uv数组数据看起来很好。 我遇到的问题是在AndEngine应用程序中实际显示模型。 OpenGL ES 2.0相关的代码遍布在AndEngine代码中,使得很难查看到底是什么以及按什么顺序。 在这一点上,我交替地看到模型没有呈现,或只是以下输出:
为了显示模型,我扩展了一些AndEngine类。 首先,我创建了一个只包含数据数组的ModelData类。 这被传递给一个类似Sprite从Shape派生的类。 在当前,凌乱的Sprite派生的时尚,它看起来像这样:
public class Model extends Shape {
public static final int VERTEX_INDEX_X = 0;
public static final int VERTEX_INDEX_Y = Model.VERTEX_INDEX_X + 1;
public static final int COLOR_INDEX = Model.VERTEX_INDEX_Y + 1;
public static final int TEXTURECOORDINATES_INDEX_U = Model.COLOR_INDEX + 1;
public static final int TEXTURECOORDINATES_INDEX_V = Model.TEXTURECOORDINATES_INDEX_U + 1;
public static final int VERTEX_SIZE = 2 + 1 + 2;
public static final int VERTICES_PER_SPRITE = 4;
public static final int SPRITE_SIZE = Model.VERTEX_SIZE * Model.VERTICES_PER_SPRITE;
public static final int POSITION_ATTRIBUTE_ID = 0;
public static final int NORMAL_ATTRIBUTE_ID = 1;
public static final int TEXTURE_COORDINATE_ATTRIBUTE_ID = 2;
public static final VertexBufferObjectAttributes VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT =
new VertexBufferObjectAttributesBuilder(3)
.add(POSITION_ATTRIBUTE_ID, "Position", 3, GLES20.GL_FLOAT, false)
.add(NORMAL_ATTRIBUTE_ID, "Normal", 3, GLES20.GL_FLOAT, true)
.add(TEXTURE_COORDINATE_ATTRIBUTE_ID, "Texture_Coordinate", 2,
GLES20.GL_FLOAT, false).build();
protected final ModelData mModelData;
protected final ITextureRegion mTextureRegion;
protected final HighPerformanceModelVertexBufferObject mModelVertexBufferObject;
//private int mMVPMatrixHandle;
private float[] mVMatrix = new float[16];
private float[] mProjMatrix = new float[16];
//private float[] mMVPMatrix = new float[16];
private float[] mInterleavedArray;
//private FloatBuffer interleavedBuffer;
// --- CONSTRUCTOR ---
public Model(final float pX, final float pY, final ITextureRegion pTextureRegion,
ModelData pModelData, VertexBufferObjectManager pVertexBufferObjectManager) {
super(pX, pY, ModelShaderProgram.getInstance());
mTextureRegion = pTextureRegion;
mInterleavedArray = pModelData.getInterleavedArray();
mModelVertexBufferObject = new HighPerformanceModelVertexBufferObject(
pVertexBufferObjectManager, mInterleavedArray, DrawType.STATIC,
true, Model.VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT);
mModelData = pModelData;
//mMVPMatrixHandle = GLES20.glGetUniformLocation(
// ((ModelShaderProgram) mShaderProgram).getProgramId(), "uMVPMatrix");
}
// --- GET VERTEX BUFFER OBJECT ---
@Override
public IVertexBufferObject getVertexBufferObject() {
return mModelVertexBufferObject;
}
// --- ON SURFACE CHANGED ---
public void onSurfaceChanged(GLState pGLState, int pWidth, int pHeight) {
// onSurfaceChanged
float ratio = (float) pWidth / pHeight;
// create a projection matrix from device screen geometry
Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 37);
// Create a camera view matrix
Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
/*int[] buffers = new int[2];
GLES20.glGenBuffers(2, buffers, 0);
int rectVerts = buffers[0];
//int rectInds = buffers[1];
interleavedBuffer = FloatBuffer.wrap(mInterleavedArray);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, rectVerts);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, mInterleavedArray.length,
interleavedBuffer, GLES20.GL_STATIC_DRAW);*/
/*GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, rectInds);
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER,
(rectIndices.limit()*4), rectIndices, GLES20.GL_STATIC_DRAW);*/
}
// --- PREDRAW ---
@Override
protected void preDraw(GLState pGLState, Camera pCamera) {
super.preDraw(pGLState, pCamera);
//this.mTextureRegion.getTexture().bind(pGLState); // TODO
this.mModelVertexBufferObject.bind(pGLState, this.mShaderProgram);
}
// --- DRAW ---
@Override
protected void draw(GLState pGLState, Camera pCamera) {
// Combine the projection and camera view matrices
//Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
// Apply the combined projection and camera view transformations
//GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
// Draw the model
//GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount); // TODO
this.mModelVertexBufferObject.draw(GLES20.GL_TRIANGLES,
mInterleavedArray.length);
}
// --- POST-DRAW ---
@Override
protected void postDraw(GLState pGLState, Camera pCamera) {
this.mModelVertexBufferObject.unbind(pGLState, this.mShaderProgram);
super.postDraw(pGLState, pCamera);
}
// --- ON UPDATE VERTICES ---
@Override
protected void onUpdateVertices() {
this.mModelVertexBufferObject.onUpdateVertices(this);
}
// --- ON UPDATE COLOR ---
@Override
protected void onUpdateColor() {
this.mModelVertexBufferObject.onUpdateColor(this);
}
// --- ON UPDATE TEXTURE COORDINATES ---
protected void onUpdateTextureCoordinates() {
this.mModelVertexBufferObject.onUpdateTextureCoordinates(this);
}
}
HighPerformanceModelVertexBufferObject类如下所示:
public class HighPerformanceModelVertexBufferObject extends
HighPerformanceVertexBufferObject {
ModelShaderProgram mModelShaderProgram;
public HighPerformanceModelVertexBufferObject(
VertexBufferObjectManager pVertexBufferObjectManager,
final float[] pBufferData, DrawType pDrawType, boolean pAutoDispose,
VertexBufferObjectAttributes pVertexBufferObjectAttributes) {
super(pVertexBufferObjectManager, pBufferData, pDrawType, pAutoDispose,
pVertexBufferObjectAttributes);
}
// --- SET VERTEX DATA ---
/*public void setVertexData(float[] va) {
mBufferData = va;
}*/
@Override
public void bind(final GLState pGLState, final ShaderProgram pShaderProgram) {
mModelShaderProgram = (ModelShaderProgram) pShaderProgram;
super.bind(pGLState, pShaderProgram);
}
@Override
public void draw(final int pPrimitiveType, final int pCount) {
GLES20.glDrawArrays(pPrimitiveType, 0, pCount);
//GLES20.glDrawElements(pPrimitiveType, pCount, GLES20.GL_UNSIGNED_SHORT, mByteBuffer);
}
public void onUpdateColor(final Model pModel) {
//
}
public void onUpdateVertices(final Model pModel) {
//
}
public void onUpdateTextureCoordinates(final Model pModel) {
//
}
}
最后,包含顶点和片段着色器的ModelShaderProgram类:
public class ModelShaderProgram extends ShaderProgram {
private static ModelShaderProgram INSTANCE;
public static final String VERTEXSHADER =
"attribute vec3 positionAttrib; n" +
"attribute vec3 normalAttrib; n" +
"attribute vec2 uvAttrib; n" +
// This matrix member variable provides a hook to manipulate
// the coordinates of objects that use this vertex shader.
"uniform mat4 uMVPMatrix; n" +
"void main() {n" +
// The matrix must be included as part of gl_Position
// Note that the uMVPMatrix factor *must be first* in order
// for the matrix multiplication product to be correct.
"gl_Position = uMVPMatrix * vec4(positionAttrib, 1.0); n" +
"}";
public static final String FRAGMENTSHADER =
"void main() {n" +
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); n" +
"}";
public static int sUniformModelViewPositionMatrixLocation = -1;
public static int sUniformTexture0Location = -1;
private ModelShaderProgram() {
super(ModelShaderProgram.VERTEXSHADER, ModelShaderProgram.FRAGMENTSHADER);
}
public static ModelShaderProgram getInstance() {
if (ModelShaderProgram.INSTANCE == null) {
ModelShaderProgram.INSTANCE = new ModelShaderProgram();
}
return ModelShaderProgram.INSTANCE;
}
@Override
protected void link(final GLState pGLState) throws ShaderProgramLinkException {
GLES20.glBindAttribLocation(this.mProgramID, 0, "positionAttrib");
GLES20.glBindAttribLocation(this.mProgramID, 1, "normalAttrib");
GLES20.glBindAttribLocation(this.mProgramID, 2, "uvAttrib");
super.link(pGLState);
ModelShaderProgram.sUniformModelViewPositionMatrixLocation =
this.getUniformLocation("uMVPMatrix");
//ModelShaderProgram.sUniformTexture0Location =
// this.getUniformLocation(ShaderProgramConstants.UNIFORM_TEXTURE_0);
}
@Override
public void bind(final GLState pGLState, final VertexBufferObjectAttributes pVertexBufferObjectAttributes) {
super.bind(pGLState, pVertexBufferObjectAttributes);
GLES20.glUniformMatrix4fv(ModelShaderProgram.sUniformModelViewPositionMatrixLocation, 1, false, pGLState.getModelViewProjectionGLMatrix(), 0);
//GLES20.glUniform1i(ModelShaderProgram.sUniformTexture0Location, 0);
}
}
正如你在片段着色器中看到的那样,它应该将任何片段着色为红色,但是这显然不会发生。 怪异的外形图也非常好奇。 在集成这些代码时是否存在一些错误? 我是否想要重写AndEngine的代码中的某些内容,我应该一个人留下?
提前感谢您提供任何提示/建议。 随意索取更多信息等。
更新一位同事指出,我正在使用的模型已编入索引。 使用glDrawElements而不是glDrawArray切换到索引图形。
链接地址: http://www.djcxy.com/p/68961.html