Нормы Android openGL ES

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

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);
    }
}

введите здесь описание изображения

Итак, нормали по умолчанию 0, 0, -1 или 0, 0, 1, а камера по умолчанию смотрит на -5, и когда модель вращается, свет просто исчезает, как если бы нормалей не было. получил что-то похожее на эту работу с компьютером, но я не использовал VBO и т. д., поэтому я не могу сравнить код, я почти уверен, что что-то не так с загрузкой обычного буфера или его привязкой! :( Помоги мне! :(


person Ruuhkis    schedule 07.02.2012    source источник
comment
Просто быстрое предположение: нормализованы ли экспортированные нормали? Если нет, нормализуете ли вы их в какой-то момент (потому что я не смог найти доказательства этого в вашем коде после беглого просмотра)?   -  person Erik    schedule 08.02.2012
comment
Ага, нормали экспортируются и загружаются из .obj файла, я тоже сам проверял, загружаются ли нормали, и они были.   -  person Ruuhkis    schedule 09.02.2012
comment
это не мой вопрос; Я уверен, что вы загружаете нормали объектов. Я спрашиваю: они нормализованы? Другими словами: равна ли их длина 1? Если это не так, вы не сможете сделать правильное освещение.   -  person Erik    schedule 09.02.2012
comment
Ой извините.. Английский точно не мой родной язык. В любом случае, да, их длина равна 1, я только что проверил, и их значения находятся в диапазоне от -1 до 1,2~   -  person Ruuhkis    schedule 09.02.2012


Ответы (1)


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

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

Цитата из: http://www.fundza.com/vectors/normalize/index.html< /а>

Для вектора «а» (или нормального «а»): а[3 1 2] (Итак: ах = 3, ау = 1, аз = 2)

Величина (длина) вектора: |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

Вам нужно применить это к нормалям перед созданием буфера, чтобы получить правильное освещение.

person Erik    schedule 09.02.2012
comment
Спасибо за объяснение и за попытку, но похоже, что проблема не в этом. Я использую блендер, который нормализует их автоматически. И, как я уже говорил в своем комментарии к вашему сообщению ранее, их значения от -1 до ~ 1,2, просто чтобы убедиться, что они нормализованы. :П - person Ruuhkis; 09.02.2012
comment
Это не может быть правильным; длина должна быть точно 1 (не -1, не 1,2). Или... если вы имеете в виду компоненты xyz, то это тоже неверно. Компоненты xyz могут быть отрицательными или положительными, но всегда между -1 и 1. - person Erik; 10.02.2012
comment
В любом случае, если вы уверены, что ваши нормали верны, вы должны опубликовать изображение и объяснить, что не так с освещением. Я пытаюсь помочь тебе, но ты не облегчаешь мне задачу. - person Erik; 10.02.2012
comment
длина равна 1, но значения находятся в диапазоне от -1 до 1,2, я выложу изображения, подождите! :) - person Ruuhkis; 10.02.2012