2016-09-07 3 views
0

Я загружаю файл .obj и выношу его в эмулятор android. Хотя сторонние зрители .obj показывают модель правильно (open3mod), когда я запускаю ее на эмуляторе Android, это выглядит странно. Не могли бы вы объяснить, почему в модели эмулятора неправильно перерисовывается?OpenGL ES 1.0 - Неверный отрисовка

import android.content.Context; 
import android.opengl.GLSurfaceView; 
import android.opengl.GLU; 
import java.util.Hashtable; 
import java.util.ArrayList; 
import java.io.InputStreamReader; 
import java.io.BufferedReader; 
import java.nio.FloatBuffer; 
import java.nio.ByteBuffer; 
import java.nio.ByteOrder; 
import javax.microedition.khronos.egl.EGLConfig; 
import javax.microedition.khronos.opengles.GL10; 

public class MyGLSurfaceView extends GLSurfaceView implements GLSurfaceView.Renderer 
{ 
    private Context context; 
    private Hashtable<String, ArrayList<Float>> obj; 

    public MyGLSurfaceView(Context context) 
    { 
     super(context); 
     setRenderer(this); 
     this.context = context; 
    } 

    public void onSurfaceCreated(GL10 gl, EGLConfig config) 
    { 
     obj = new Hashtable<String, ArrayList<Float>>(); 

     try 
     { 
      BufferedReader reader = new BufferedReader(
       new InputStreamReader(context.getAssets().open("calculator.obj"))); 

      ArrayList<Float> vertex = new ArrayList<Float>(); 

      String name = null; 
      String line = null; 
      while ((line = reader.readLine()) != null) 
      { 
       if (line.startsWith("v ")) 
       { 
        String[] parts = line.substring(2).trim().split("\\s+"); 

        vertex.add(Float.valueOf(Float.valueOf(parts[0]).floatValue()/2f)); // scale to smaller twice 
        vertex.add(Float.valueOf(Float.valueOf(parts[1]).floatValue()/2f)); // scale to smaller twice 
        vertex.add(Float.valueOf(Float.valueOf(parts[2]).floatValue()/2f)); // scale to smaller twice 
       } 

       if (line.startsWith("f ")) 
       { 
        String[] parts = line.substring(2).trim().split("\\s+"); 

        obj.get(name).add(vertex.get(Integer.valueOf(parts[0]).intValue() - 1)); 
        obj.get(name).add(vertex.get(Integer.valueOf(parts[1]).intValue() - 1)); 
        obj.get(name).add(vertex.get(Integer.valueOf(parts[2]).intValue() - 1)); 
       } 

       if (line.startsWith("g ")) 
       { 
        name = line.substring(2).trim(); 

        obj.put(name, new ArrayList<Float>()); 
       } 
      } 

      reader.close(); 
     } 
     catch (Exception e) 
     { 
      System.exit(0); 
     } 
    } 

    public void onSurfaceChanged(GL10 gl, int width, int height) 
    { 
     gl.glViewport(0, 0, width, height); 
    } 

    public void onDrawFrame(GL10 gl) 
    { 
     gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
     gl.glClearDepthf(1.0f); 

     int i; 

     ByteBuffer fByteBuffer = ByteBuffer.allocateDirect(obj.get("calculator").size() * 4); 
     fByteBuffer.order(ByteOrder.nativeOrder()); 
     FloatBuffer faces = fByteBuffer.asFloatBuffer(); 
     for (i = 0; i < obj.get("calculator").size(); i++) 
      faces.put(obj.get("calculator").get(i).floatValue());    
     faces.position(0); 

     gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 
     gl.glVertexPointer(3, GL10.GL_FLOAT, 0, faces); 

     gl.glDrawArrays(GL10.GL_TRIANGLES, 0, faces.capacity()/3); 
    } 
} 

+0

Можно попробовать простейший OBJ-файл и включить как obj-файл, так и список с плавающей точкой, которые вы передаете API в свой вопрос. Сложно понять, что происходит, – solidpixel

+0

Проблема в том, что список плавающих также отображается неправильно. Я написал скрипт obj2java и импортировал его в основной класс - результат тот же –

+0

Несомненно, что, вероятно, означает, что вы не читаете файл правильно, но не видя как файл, так и то, что делает ваш скрипт, трудно сказать .. – solidpixel

ответ

0

OBJ файлы представляют собой индексированный формат геометрия (это то, что линии элементов лиц начинаются с «е» кодирует - они говорят вам, какие вершины в массиве вершин составляют каждый треугольник).

Ваш текущий код декодирует значения индекса, но полностью игнорирует их, когда дело доходит до рендеринга. Вам нужно использовать glDrawElements, используя буфер индекса, чтобы выбрать, какие вершины внести вклад в какие треугольники.

EDIT Я пропустил тот факт, что вы вручную переупаковываете данные вершин при загрузке. Вам не нужно это делать - API поддерживает индексированный рендеринг изначально (и он намного эффективнее, поскольку разделяемые вершины обрабатываются только один раз).

+0

Я пробовал 'glDrawElements' - тот же результат, потому что .obj-файл не содержит индексов, и я вынужден индексировать треугольники просто от 0 до подсчета вершин. –

+0

'вы вручную переупаковываете данные вершин при загрузке' - пожалуйста, очистите. –

+0

"... потому что .obj-файл не содержит информации об индексах". Да, да. Как вы думаете, строки, начинающиеся с «f»? Вы уже декодируете их и используете их в качестве индексов ... – solidpixel

Смежные вопросы