2016-12-07 19 views
13

Tôi cố gắng để tải một file .obj vào ứng dụng Android của tôi và hiển thị nó sử dụng OpenGL 2.Làm thế nào để tải và hiển thị .obj tập tin trong Android với OpenGL-ES 2

Bạn có thể tìm thấy các tập tin ở đây: EDIT: Tôi loại bỏ các tập tin, bạn có thể sử dụng bất kỳ tập tin .obj có chứa các giá trị đề cập dưới đây để thử nghiệm.

Có rất nhiều câu hỏi tương tự trên stackoverflow nhưng tôi không tìm thấy một giải pháp đơn giản mà không yêu cầu một số thư viện lớn.

Các tập tin chỉ chứa các loại giá trị sau:

  • g
  • v
  • vt
  • vn
  • f

tôi đã cố gắng libgdx, mà làm việc ok, nhưng nó là một chút overkill cho những gì tôi cần.

Tôi đã thử oObjLoader https://github.com/seanrowens/oObjLoader mà không có LWJGL. Việc phân tích cú pháp dường như hoạt động, nhưng làm cách nào tôi có thể hiển thị các giá trị trong một cảnh đơn giản?

Bước tiếp theo là đính kèm hình ảnh làm kết cấu cho đối tượng. Nhưng bây giờ tôi sẽ rất vui khi hiển thị tập tin.

Tôi đang mở cho các giải pháp khác nhau như chuyển đổi trước tệp, vì nó sẽ chỉ là ứng dụng này trong ứng dụng.

Cảm ơn!

Cập nhật trạng thái Tải và hiển thị cơ bản hoạt động ngay bây giờ, như được hiển thị trong câu trả lời của riêng tôi.

+3

Vì bạn đang sử dụng Android , rất có thể câu hỏi của bạn nhắm mục tiêu OpenGL-ES 2 chứ không phải OpenGL 2. Nếu đúng như vậy, tôi khuyên bạn nên cập nhật câu hỏi và xử lý câu hỏi cho phù hợp. – BDL

Trả lời

4

tôi đã kết thúc viết một phân tích cú pháp mới, nó có thể được sử dụng như thế này để xây dựng FloatBuffers để sử dụng trong Renderer của bạn:

ObjLoader objLoader = new ObjLoader(context, "Mug.obj"); 

numFaces = objLoader.numFaces; 

// Initialize the buffers. 
positions = ByteBuffer.allocateDirect(objLoader.positions.length * mBytesPerFloat) 
     .order(ByteOrder.nativeOrder()).asFloatBuffer(); 
positions.put(objLoader.positions).position(0); 

normals = ByteBuffer.allocateDirect(objLoader.normals.length * mBytesPerFloat) 
     .order(ByteOrder.nativeOrder()).asFloatBuffer(); 
normals.put(objLoader.normals).position(0); 

textureCoordinates = ByteBuffer.allocateDirect(objLoader.textureCoordinates.length * mBytesPerFloat) 
     .order(ByteOrder.nativeOrder()).asFloatBuffer(); 
textureCoordinates.put(objLoader.textureCoordinates).position(0); 

và đây là phân tích cú pháp:

public final class ObjLoader { 

    public final int numFaces; 

    public final float[] normals; 
    public final float[] textureCoordinates; 
    public final float[] positions; 

    public ObjLoader(Context context, String file) { 

     Vector<Float> vertices = new Vector<>(); 
     Vector<Float> normals = new Vector<>(); 
     Vector<Float> textures = new Vector<>(); 
     Vector<String> faces = new Vector<>(); 

     BufferedReader reader = null; 
     try { 
      InputStreamReader in = new InputStreamReader(context.getAssets().open(file)); 
      reader = new BufferedReader(in); 

      // read file until EOF 
      String line; 
      while ((line = reader.readLine()) != null) { 
       String[] parts = line.split(" "); 
       switch (parts[0]) { 
        case "v": 
         // vertices 
         vertices.add(Float.valueOf(parts[1])); 
         vertices.add(Float.valueOf(parts[2])); 
         vertices.add(Float.valueOf(parts[3])); 
         break; 
        case "vt": 
         // textures 
         textures.add(Float.valueOf(parts[1])); 
         textures.add(Float.valueOf(parts[2])); 
         break; 
        case "vn": 
         // normals 
         normals.add(Float.valueOf(parts[1])); 
         normals.add(Float.valueOf(parts[2])); 
         normals.add(Float.valueOf(parts[3])); 
         break; 
        case "f": 
         // faces: vertex/texture/normal 
         faces.add(parts[1]); 
         faces.add(parts[2]); 
         faces.add(parts[3]); 
         break; 
       } 
      } 
     } catch (IOException e) { 
      // cannot load or read file 
     } finally { 
      if (reader != null) { 
       try { 
        reader.close(); 
       } catch (IOException e) { 
        //log the exception 
       } 
      } 
     } 

     numFaces = faces.size(); 
     this.normals = new float[numFaces * 3]; 
     textureCoordinates = new float[numFaces * 2]; 
     positions = new float[numFaces * 3]; 
     int positionIndex = 0; 
     int normalIndex = 0; 
     int textureIndex = 0; 
     for (String face : faces) { 
      String[] parts = face.split("/"); 

      int index = 3 * (Short.valueOf(parts[0]) - 1); 
      positions[positionIndex++] = vertices.get(index++); 
      positions[positionIndex++] = vertices.get(index++); 
      positions[positionIndex++] = vertices.get(index); 

      index = 2 * (Short.valueOf(parts[1]) - 1); 
      textureCoordinates[normalIndex++] = textures.get(index++); 
      // NOTE: Bitmap gets y-inverted 
      textureCoordinates[normalIndex++] = 1 - textures.get(index); 

      index = 3 * (Short.valueOf(parts[2]) - 1); 
      this.normals[textureIndex++] = normals.get(index++); 
      this.normals[textureIndex++] = normals.get(index++); 
      this.normals[textureIndex++] = normals.get(index); 
     } 
    } 
} 
+0

HI tôi có thể lấy toàn bộ tập tin ObjLoader ur không? Tôi đang gặp một số vấn đề với nó. Có thực sự đánh giá cao nó rất nhiều –

+0

Hi i am cực kỳ mới để opengles u có thể hướng dẫn tôi để làm cho bộ đệm, tôi đã có thể tạo ra các bộ đệm nhờ vào mã ur, nhưng không thể làm lại nó. –

0

Khi bạn có thể phân tích các tệp obj, hãy tham khảo post này có thể giúp bạn rất nhiều.

Có cách dễ dàng hơn, sử dụng ba.js objloader. Sử dụng XWalkView để thêm trang web trong ứng dụng android của bạn. XWalkView là một cái gì đó như webview, ở đây workview có thể không hoạt động để render cảnh phức tạp, Trong khi XWalkView có. Nếu bạn không làm cho trang web từ xa, bạn có thể làm cho nó địa phương.

+0

Cảm ơn câu trả lời của bạn nhưng tôi muốn có giải pháp OpenGL-ES. –

Các vấn đề liên quan