Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.net  
   

Die mobilen Seiten von c++.net:
https://m.c-plusplus.net

  
C++ Forum :: Spiele-/Grafikprogrammierung ::  [OpenGL & C]Modelldarstellung mit Fehlern (OBJ-Loader)     Zeige alle Beiträge auf einer Seite Auf Beitrag antworten
Autor Nachricht
OpenGLNeuling
Unregistrierter




Beitrag OpenGLNeuling Unregistrierter 19:41:46 06.03.2018   Titel:   [OpenGL & C]Modelldarstellung mit Fehlern (OBJ-Loader)            Zitieren

Screenshot: https://i.imgur.com/CaDAA1J.png

Egal welches Modell ich lade, es kommt immer mit Fehldarstellungen (s. Screenshot). Ich vermute, dass es an glBufferData, glVertexAttribPointer oder glDrawElements liegt, weil evtl. die Bytegrößen nicht richtig gesetzt worden sind.

Ich verwende eine einfach verkette Listen beim Parsen des Objekts (ist sehr langsam). Zudem verwende ich benutzdefinierte Array-Objekte/Struktur (die noch zusätzlich zum Array die Größeninformation inne hat). Das wäre einmal FloatArray und UIntArray. FloatArray ist ähnlich wie UIntArray mittels typedef definiert. Der Unterschied ist, dass das UIntArray ein uint32_t Array beinhaltet. Hier ist die sind die typedefs dazu:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#ifndef ARRAYS_H_
#define ARRAYS_H_

#include <stddef.h>

#include <inttypes.h>
 
// uint array object
typedef struct {
  uint32_t* elements;
  size_t length;
} UIntArray;
 
// float array object
typedef struct {
  float* elements;
  size_t length;
} FloatArray;
 
// Dumps an primitive uint array on the heap with its size info
UIntArray* newUIntArray(uint32_t* dump, const size_t length);
// Dumps an primitive uint array on the heap with its size info
UIntArray* newUIntArrayNoDump(const size_t length);
// Creates a float array object with the specified size
FloatArray* newFloatArrayNoDump(const size_t length);
// Dumps an primitive float array on the heap with its size info
FloatArray* newFloatArray(float* dump, const size_t length);
// Free up used heap memory by the uint array object
void delUIntArray(UIntArray* p);
// Free up used heap memory by the float array object
void delFloatArray(FloatArray* p);

#endif // ARRAYS_H_




Details

Das ist die engine.c mit der Funktion run, die die Rendering-Loop enthält:

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include "engine.h"
#include "shader.h"
#include "mesh.h"
#include "linalg.h"
#include <math.h>
#include "arrays.h"
 
// TODO define a function instead of a macro
#define TO_RAD(d) ((float) (d * M_PI) / 180.0f)
 
void run() {
  // Window creation
  WNDHND wh = createWindow(WIN_WIDTH, WIN_HEIGHT, WIN_TITLE);
  // Compile and link the shaders
  SHADERID progID = setupShaders("vs1.glsl", "fs1.glsl");
  // Dump vertex and index data into the array objects from an OBJ file
  FloatArray* vertexDump;
  UIntArray* indexDump;
  loadOBJ("cow.smf", &vertexDump, &indexDump);
  // Send the vertex and index data to the graphics driver
  OBJECTID vao1 = setupBuffers(vertexDump, indexDump);
  // Model matrix definition (col.-major)
  const float Tx = +0.0f;
  const float Ty = +0.0f;
  const float Tz = +1.0f;
  Matrix16f M = {
    +1.0f, +0.0f, +0.0f, +Tx,
    +0.0f, +1.0f, +0.0f, +Ty,
    +0.0f, +0.0f, +1.0f, +Tz,
    +0.0f, +0.0f, +0.0f, +1.0f,
  };
  // View matrix definition (col.-major)
  const float Rx = 1.0f;
  const float Ry = 0.0f;
  const float Rz = 0.0f;
  const float Ux = 0.0f;
  const float Uy = 1.0f;
  const float Uz = 0.0f;
  const float Px = 0.0f;
  const float Py = 0.0f;
  const float Pz = 0.0f;
  const float Fx = 0.0f;
  const float Fy = 0.0f;
  const float Fz = 1.0f;
  Matrix16f V = {
    +Rx, +Ry, +Rz, -Px,
    +Ux, +Uy, -Uz, -Py,
    -Fx, -Fy, -Fz, -Pz,
    +0.0f, +0.0f, +0.0f, +1.0f,
  };
 // Projection matrix (col.-major)
 const float near = 0.1f;
 const float far = 100.0f;
 const float aspect = (float) WIN_WIDTH / WIN_HEIGHT;
 const float fov = 75.0f;
 const float range = tan(TO_RAD(fov) / 2.0f) * near;
 const float Sx = (float) (2.0f * near) / (float) (range * aspect + range * aspect);
 const float Sy = (float) near / (float) range;
 const float Sz = (float) -(far + near) / (float) (far - near);
 const float PPz = (float) -(2 * far * near) / (float) (far - near);
 Matrix16f P = {
   +Sx, +0.0f, +0.0f, +0.0f,
   +0.0f, +Sy, +0.0f, +0.0f,
   +0.0f, +0.0f, +Sz, +PPz,
   +0.0f, +0.0f, -1.0f, +0.0f,
  };
  // Construct MVP matrix
  Matrix16f MVP = {0};
  multiplyMatrices(&MVP, M, V);
  multiplyMatrices(&MVP, MVP, P);
  // Send the constructed MVP matrix to the vertex shader
  sendMVPMatrix(progID, MVP.entries);
  // Set the clear color
  const float r = 0.3f;
  const float g = 0.3f;
  const float b = 0.3f;
  const float a = 1.0f;
  glClearColor(r, g, b, a);
  // Enable depth
  glEnable(GL_DEPTH_TEST);
  glDepthFunc(GL_LESS);
  // Culling options
  glDisable(GL_CULL_FACE);
  glFrontFace(GL_CCW);
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  // Render loop
  while(!windowShouldClose(wh)) {
    // Clear color buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    // Resize frame buffer if the window dimensions are changing
    maintainAspectRatio(wh);
    // Use shader program
    glUseProgram(progID);
    // Activate the VAO
    glBindVertexArray(vao1);
    // Enable the position attribute in the vertex shader at location 0
    glEnableVertexAttribArray(0);
    // Draw
    const uint32_t faceCount = indexDump->length / 3;
    glDrawElements(GL_TRIANGLES, faceCount, GL_UNSIGNED_INT, 0);
    // Swap buffers
    swapBuffers(wh);
    // Listen for any events
    pollEvents();
  }
  destroyWindow(wh);
}


Das ist mesh.c mit den Funktionen setupBuffers und loadOBJ:

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include "mesh.h"
#include "shader.h"
#include <string.h>
 
BUFFERID setupBuffers(FloatArray* verts, UIntArray* inds) {
  // Generate VAO
  uint32_t vao;
  glGenVertexArrays(1, &vao);
  // Bind the VAO
  glBindVertexArray(vao);
  // Generate VBO
  uint32_t vbo;
  glGenBuffers(1, &vbo);
  // Bind VBO
  glBindBuffer(GL_ARRAY_BUFFER, vbo);
  // Feed VBO with data
  const uint32_t arrayBufferSize = sizeof(float) * verts->length;
  glBufferData(GL_ARRAY_BUFFER, arrayBufferSize, verts->elements, GL_STATIC_DRAW);
  // TODO remove debug output
  // DEBUG vertices
  fprintf(stdout, "DEBUG verts->length in function setupBuffers: %d\n",
  verts->length);
  for (int i = 0; i < verts->length; ++i) {
    fprintf(stdout, "DEBUG verts->elements[%d] in function setupBuffers: %f\n",
    i,  verts->elements[i]);
  }
  // Link the position attribute in the vertex shader with the data at
  // attribute location 0.
  const uint32_t componentCountPos = 3;
  const uint32_t stride = sizeof(float) * componentCountPos;
  const uint32_t offsetPos = 0;
  glVertexAttribPointer(0, componentCountPos, GL_FLOAT, GL_FALSE, stride,
    (void*) offsetPos);
  glEnableVertexAttribArray(0);
  // Generate element buffer object
  uint32_t ebo;
  glGenBuffers(1, &ebo);
  // Bind the EBO
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
  // Feed with index data
  const uint32_t elementArrayBufferSize = sizeof(uint32_t) * inds->length;
  glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementArrayBufferSize, inds->elements, GL_STATIC_DRAW);
  // TODO remove debug output
  // DEBUG indices
  fprintf(stdout, "DEBUG inds->length in function setupBuffers: %d\n",
  inds->length);
  for (int i = 0; i < inds->length; ++i) {
    fprintf(stdout, "DEBUG inds->elements[%d] in function setupBuffers: %d\n",
    i,  inds->elements[i]);
  }
  // Return back the ID to the VAO
  return vao;
}
 
// TODO complete implementation: read UVs, normals too
void loadOBJ(const uint8_t* path, FloatArray** verts, UIntArray** inds) {
  // Open OBJ file
  FILE* fis = fopen(path, "rb");
  if (!fis) {
    perror("Error: failed to open OBJ file.\n");
    exit(1);
  }
  // Parse vertex data
  FloatNode* fn = NULL;
  UIntNode* uin = NULL;
  uint8_t lineHeader[128];
  float vX = 0.0f;
  float vY = 0.0f;
  float vZ = 0.0f;
  uint32_t i1 = 0;
  uint32_t i2 = 0;
  uint32_t i3 = 0;
  while (fscanf(fis, "%s", lineHeader) != EOF) {
    if (strcmp(lineHeader, "v") == 0) {
      if (fscanf(fis, "%f %f %f\n", &vX, &vY, &vZ)) {
        fn = addFloatNodeLast(fn, vX);
        fn = addFloatNodeLast(fn, vY);
        fn = addFloatNodeLast(fn, vZ);
    }
    } else if (strcmp(lineHeader, "f") == 0) {
        uint32_t junk;
        if (fscanf(fis, "%d %d %d %d/%d/%d %d/%d/%d\n",
        &i1, &i2, &i3, &junk,
        &junk, &junk, &junk, &junk, &junk)) {
          uin = addUIntNodeLast(uin, i1);
          uin = addUIntNodeLast(uin, i2);
          uin = addUIntNodeLast(uin, i3);
      }
    }
  }
  // Copy float list to float array object
  const uint64_t flLength = getFloatListLength(fn);
  FloatNode* fnIt = fn;
  (*verts) = newFloatArrayNoDump(flLength);
  for (uint64_t i = 0; i < flLength; ++i) {
    (*verts)->elements[i] = fnIt->data;
    if (fnIt) {
      fnIt = fnIt->next;
    }
  }
  // Copy uint32_t list to uint32_t array object
  const uint64_t uilLength = getUIntListLength(uin);
  UIntNode* uinIt = uin;
  (*inds) = newUIntArrayNoDump(uilLength);
  for (uint64_t i = 0; i < (*inds)->length; ++i) {
    (*inds)->elements[i] = uinIt->data;
    if (uinIt) {
      uinIt = uinIt->next;
    }
  }
  // Close file stream
  fclose(fis);
} // end of loadOBJ


Das ist cow.smf (das Modell, das geladen wird): https://pastebin.com/Fg3hMrQH
OpenGLNeuling
Unregistrierter




Beitrag OpenGLNeuling Unregistrierter 19:50:57 06.03.2018   Titel:              Zitieren

Edit: Ansonsten werden die Vertex- und Indexdaten schon korrekt geparst.
C++ Forum :: Spiele-/Grafikprogrammierung ::  [OpenGL & C]Modelldarstellung mit Fehlern (OBJ-Loader)   Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können Beiträge in dieses Forum schreiben.
Sie können auf Beiträge in diesem Forum antworten.
Sie können Ihre Beiträge in diesem Forum nicht bearbeiten.
Sie können Ihre Beiträge in diesem Forum nicht löschen.
Sie können an Umfragen in diesem Forum nicht mitmachen.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.net ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info und www.c-plusplus.net enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.