2012-02-07 4 views
2

Итак, вчера я написал загрузчик 3D-моделей WaveFront .obj, который теперь отлично работает (не поддерживает все tho), поэтому я написал простой тест, чтобы нарисовать любую 3D-модель на экране, которая все работала нормально, пока я не добавлял освещение на сцене. Появился свет, но, похоже, нормали все еще находятся в состоянии по умолчанию. Я очень не уверен, что я должен использовать в качестве цели при создании буферов (как Theres GL_NORMAL_ARRAY, GL_ARRAY_BUFFER и т.д.) для нормалей, как я не мог найти любой учебник о том, что с помощью объектов буфера для тех, кто:Android openGL ES normals

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

+0

Да, нормали экспортируются и загружаются из файла .obj, я сам сам проверяю, загружали ли нормали, и они были. – Ruuhkis

+0

это не мой вопрос; Я уверен, что вы загружаете нормали объектов. Я спрашиваю: нормализуются ли они? Другими словами: их длина 1? Если это не так, вы не можете сделать правильное освещение. – Erik

ответ

1

Чтобы объяснить свой комментарий на ваш вопрос чуть дальше:

НУ должны убедиться, что ваши нормалей «нормализуется», это означает, что их величина (длина) должна быть 1. Некоторые .obj экспортеров сделать это для вас, но это хорошая вещь, чтобы сделать это самостоятельно

Цитируется: http://www.fundza.com/vectors/normalize/index.html

Учитывая вектор «а» (или нормальный «а»): а [3 1 2]. (So: ax = 3, ay = 1, az = 2)

Величина (leng th) вектора: | a | = SQRT ((ах * ах) + (ау * ау) + (аз * аз))

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

Спасибо за объяснение этого и для попытки, но похоже, что это не проблема. Я использую blender, который автоматически их нормализует. И, как я уже писал в своем комментарии к вашему сообщению, их значения от -1 до ~ 1.2, просто чтобы убедиться, что они нормализованы. : P – Ruuhkis

+0

Это не может быть прав; длина должна быть * точно * 1 (не -1, а не 1.2). Или ... если вы имеете в виду под «значениями» компоненты xyz, то это тоже неправильно. Компоненты xyz могут быть отрицательными или положительными, но всегда между -1 и 1. – Erik

+0

В любом случае, если вы уверены, что ваши нормали верны, вы должны опубликовать изображение и объяснить, что не так с освещением. Я пытаюсь помочь тебе, но ты не облегчишь меня. – Erik