2012-02-07 181 views
2

所以昨天我写的波阵面的obj 3D模型加载器现在正常工作(不支持一切寿),所以我写了简单的测试得出,所有工作得很好屏幕上的任何3D模型,直到我加入照明到现场。光线出现,但似乎法线仍处于默认状态。我非常不确定生成缓冲区时法线(如那里有GL_NORMAL_ARRAY,GL_ARRAY_BUFFER等)有关使用缓冲区对象为那些它,因为我无法找到任何教程为目标我应该怎么用:Android的OpenGL ES的法线

package com.Ruuhkis.opengl; 

import static javax.microedition.khronos.opengles.GL10.GL_COLOR_BUFFER_BIT; 
import static javax.microedition.khronos.opengles.GL10.GL_VERTEX_ARRAY; 

import java.nio.ByteBuffer; 
import java.nio.ByteOrder; 
import java.nio.FloatBuffer; 
import java.nio.ShortBuffer; 

import javax.microedition.khronos.egl.EGLConfig; 
import javax.microedition.khronos.opengles.GL10; 
import javax.microedition.khronos.opengles.GL11; 

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.BitmapFactory.Options; 
import android.opengl.GLSurfaceView.Renderer; 
import android.opengl.GLU; 
import android.opengl.GLUtils; 
import android.util.Log; 

import com.Ruuhkis.opengl.model.Indices; 
import com.Ruuhkis.opengl.model.Loader; 
import com.Ruuhkis.opengl.model.Model; 
import com.Ruuhkis.opengl.model.Polygon; 
import com.Ruuhkis.opengl.model.Vertex; 

public class TextureRenderer implements Renderer { 

    private FloatBuffer vertexBuffer, normalBuffer; 
    private ShortBuffer indexBuffer; 
    private int attribVBO, attribIBO, attribNBO; 
    private Context context; 
    private float rotation = 0; 
    private float[] vertices = 
     {-0.8f, -0.8f, 0f, 
     0.8f, -0.8f, 0f, 
     0.8f, 0.8f, 0f, 
     -0.8f, 0.8f, 0f}; 

    private float[] normals = 
     {0f}; 

    private short[] indices = 
     {0, 3, 2, 
     0, 2, 1}; 

    public TextureRenderer(Context context) { 
     this.context = context; 

     Model model = Loader.loadModel(context.getAssets(), "test.txt"); 

     vertices = new float[model.getVerticeList().size() * 3]; 

     int i = 0; 

     for(Vertex v: model.getVerticeList()) { 
      vertices[i++] = v.getX(); 
      vertices[i++] = v.getY(); 
      vertices[i++] = v.getZ(); 
      //Log.v("vertice", v.toString() + " sa"); 
     } 

     i = 0; 

     indices = new short[model.getPolygonList().size() * 3]; 
     normals = new float[model.getPolygonList().size() * 3]; 

     for(Polygon p: model.getPolygonList()) { 
      for(Indices in: p.getIndiceList()) { 
       normals[i] = vertices[in.getNormalIndex()]; 
       indices[i++] = (short) in.getVertexIndex();   
      } 
     } 

     ByteBuffer buffer = ByteBuffer.allocateDirect(vertices.length * 4); 
     buffer.order(ByteOrder.nativeOrder()); 
     vertexBuffer = buffer.asFloatBuffer(); 
     vertexBuffer.put(vertices); 
     vertexBuffer.flip(); 

     buffer = ByteBuffer.allocateDirect(normals.length * 4); 
     buffer.order(ByteOrder.nativeOrder()); 
     normalBuffer = buffer.asFloatBuffer(); 
     normalBuffer.put(normals); 
     normalBuffer.flip(); 

     buffer = ByteBuffer.allocateDirect(indices.length * 2); 
     buffer.order(ByteOrder.nativeOrder()); 
     indexBuffer = buffer.asShortBuffer(); 
     indexBuffer.put(indices); 
     indexBuffer.flip(); 


    } 

    @Override 
    public void onDrawFrame(GL10 gl) { 

     gl.glColor4f(1f, 0f, 0f, 1f); 
     gl.glClear(GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 

     gl.glLoadIdentity(); 
     gl.glPushMatrix(); 
     gl.glTranslatef(0f, 0f, -10f); 
     rotation += 1f; 
     gl.glRotatef(rotation, 1f, 1f, 0f); 
     gl.glEnableClientState(GL_VERTEX_ARRAY); 
     gl.glEnableClientState(GL11.GL_NORMAL_ARRAY); 

     GL11 gl11 = (GL11) gl; 

     gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, attribVBO); 
     gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, attribIBO); 
     gl11.glBindBuffer(GL11.GL_NORMAL_ARRAY, attribNBO); 
     gl11.glVertexPointer(3, GL10.GL_FLOAT, 0, 0); 
     gl11.glNormalPointer(3, GL10.GL_FLOAT, 0); 
     gl11.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, 0); 

     gl.glDisableClientState(GL11.GL_NORMAL_ARRAY); 
     gl.glDisableClientState(GL_VERTEX_ARRAY); 
     gl.glPopMatrix(); 
     gl.glFlush(); 
    } 

    @Override 
    public void onSurfaceChanged(GL10 gl, int width, int height) { 
     gl.glViewport(0, 0, width, height); 
     gl.glMatrixMode(GL10.GL_PROJECTION); 
     gl.glLoadIdentity(); 
     GLU.gluPerspective(gl, 45f, (float)width/(float)height, 1f, 100f); 
     gl.glMatrixMode(GL10.GL_MODELVIEW); 
     gl.glEnable(GL10.GL_DEPTH_TEST); 
     //gl.glEnable(GL10.GL_LIGHTING); 
     gl.glEnable(GL10.GL_LIGHTING); 
     gl.glEnable(GL10.GL_LIGHT1); 
     gl.glEnable(GL10.GL_COLOR_MATERIAL); 
     gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, FloatBuffer.wrap(new float[]{0f, 0f, 0f, 1f})); 
     gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, FloatBuffer.wrap(new float[]{1f, 1f, 1f, 1f})); 
     gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_SPECULAR, FloatBuffer.wrap(new float[]{1f, 1f, 1f, 1f})); 

     gl.glMaterialfv(GL10.GL_FRONT, GL10.GL_SPECULAR, FloatBuffer.wrap(new float[]{1f, 1f, 1f, 1f})); 
     gl.glMaterialf(GL11.GL_FRONT, GL11.GL_SHININESS,128f); 
     gl.glShadeModel(GL10.GL_SMOOTH); 
    } 

    @Override 
    public void onSurfaceCreated(GL10 gl, EGLConfig config) { 
     gl.glClearColor(0.8f, 0.8f, 0.8f, 1f); 
     GL11 gl11 = (GL11) gl; 
     int[] buffer = new int[1]; 
     gl11.glGenBuffers(1, buffer, 0); 
     attribVBO = buffer[0]; 
     gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, attribVBO); 
     gl11.glBufferData(GL11.GL_ARRAY_BUFFER, vertices.length * 4, vertexBuffer, GL11.GL_STATIC_DRAW); 
     gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, -1); 

     gl11.glGenBuffers(1, buffer, 0); 
     attribIBO = buffer[0]; 
     gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, attribIBO); 
     gl11.glBufferData(GL11.GL_ELEMENT_ARRAY_BUFFER, indices.length * 2, indexBuffer, GL11.GL_STATIC_DRAW); 
     gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, -1); 

     gl11.glGenBuffers(1, buffer, 0); 
     attribNBO = buffer[0]; 
     gl11.glBindBuffer(GL11.GL_NORMAL_ARRAY, attribNBO); 
     gl11.glBufferData(GL11.GL_NORMAL_ARRAY, normals.length * 4, normalBuffer, GL11.GL_STATIC_DRAW); 
     gl11.glBindBuffer(GL11.GL_NORMAL_ARRAY, -1); 
    } 
} 

enter image description here

所以,默认法线0,0,-1或0,0,1,默认相机看-5,并作为模型旋转光刚刚消失,就像它是在世界上没有法线,我有类似于这项工作与计算机的东西,但我没有使用VBOs等,所以我不能比较代码,我很确定上传普通缓冲区或绑定它有问题吗? :(帮我:(

+0

只是一个快速猜测:导出的法线是否归一化?如果不是的话,你是否在某个时候对它们进行了标准化(因为我无法在快速浏览后在你的代码中找到证据)? – Erik 2012-02-07 20:09:03

+0

是的,法线从.obj文件导出和加载,我也检查法线是否加载,他们是。 – Ruuhkis 2012-02-09 12:12:52

+0

这不是我的问题;我相信你会加载对象法线。我问的是:他们是否正常化?换句话说:他们的长度是1?如果情况并非如此,则无法进行正确的照明。 – Erik 2012-02-09 12:38:36

回答

1

为了解释我对你的问题稍远一点评论:

OU需要确保你的法线“正常化”,这意味着它们的大小(长度)必须1.一些.OBJ出口商为你做这个,但它是该自己做的好事

引自:http://www.fundza.com/vectors/normalize/index.html

给定一个向量 “A”(或正常的 “A”):[3 1 2]。 (所以:AX = 3,AY = 1,AZ = 2)

幅度(楞th)的矢量是:| a | =开方((AX * AX)+(AY * AY)+(AZ * AZ))

length = sqrt((ax * ax) + (ay * ay) + (az * az)) 
length = sqrt(9 + 1 + 4) = 3.742 

为了归矢量 “一”,我们除以长度:

x = ax/|a|; 
y = ay/|a|; 
z = az/|a|; 

x = 3.0/3.742 = 0.802 
y = 1.0/3.742 = 0.267 
z = 2.0/3.742 = 0.534 

您需要在之前将此应用于您的法线您将创建缓冲区以获得正确的照明。

+0

感谢您解释这一点,对于尝试,但似乎这不是问题。我正在使用搅拌器自动对其进行标准化。正如我在之前对你的帖子发表评论时所说的,它们的值从-1到〜1.2,只是为了确保它们正常化。 :P – Ruuhkis 2012-02-09 18:00:54

+0

这不可能是正确的;长度必须*精确* 1(不是-1;不是1.2)。或者..如果你的意思是“值”xyz组件,那么这也是错误的。 xyz分量可以是负值也可以是正值,但总是在-1和1之间。 – Erik 2012-02-10 15:12:42

+0

无论如何,如果您确信您的法线是正确的,那么您应该张贴图像并解释照明有什么问题。我试图帮助你,但是你对我来说并不容易。 – Erik 2012-02-10 15:15:34