You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 lines
4.5 KiB

4 years ago
  1. #include "ObjModel.h"
  2. #include "utils.h"
  3. #include <stdio.h>
  4. #include <sstream>
  5. #include <string>
  6. #include <vector>
  7. void ObjModel::Init(const char*modelFilePath)
  8. {
  9. struct VertexInfo
  10. {
  11. float v[3];
  12. VertexInfo()
  13. {
  14. memset(v, 0, sizeof(float) * 3);
  15. }
  16. };
  17. struct VertexDefine
  18. {
  19. int positionIndex;
  20. int texcoordIndex;
  21. int normalIndex;
  22. };
  23. std::vector<VertexInfo> positions;
  24. std::vector<VertexInfo> texcoords;
  25. std::vector<VertexInfo> normals;
  26. std::vector<VertexDefine> vertices;
  27. std::vector<unsigned int> faces;
  28. //load model from file
  29. char*fileContent = LoadFileContent(modelFilePath);
  30. //decode model
  31. std::stringstream ssFileContent(fileContent);
  32. char szOneLine[256];
  33. std::string temp;
  34. while (!ssFileContent.eof())
  35. {
  36. memset(szOneLine, 0, 256);
  37. ssFileContent.getline(szOneLine, 256);
  38. if (strlen(szOneLine)>0)
  39. {
  40. std::stringstream ssOneLine(szOneLine);
  41. if (szOneLine[0]=='v')
  42. {
  43. if (szOneLine[1]=='t')
  44. {
  45. VertexInfo vi;
  46. ssOneLine >> temp;//vt
  47. ssOneLine >> vi.v[0];
  48. ssOneLine >> vi.v[1];
  49. texcoords.push_back(vi);
  50. }
  51. else if (szOneLine[1]=='n')
  52. {
  53. VertexInfo vi;
  54. ssOneLine >> temp;//vn
  55. ssOneLine >> vi.v[0];
  56. ssOneLine >> vi.v[1];
  57. ssOneLine >> vi.v[2];
  58. normals.push_back(vi);
  59. }
  60. else
  61. {
  62. VertexInfo vi;
  63. ssOneLine >> temp;//v
  64. ssOneLine >> vi.v[0];
  65. ssOneLine >> vi.v[1];
  66. ssOneLine >> vi.v[2];
  67. positions.push_back(vi);
  68. }
  69. }
  70. else if(szOneLine[0]=='f')
  71. {
  72. //
  73. ssOneLine >> temp;//f
  74. std::string vertexStr;
  75. for (int i = 0; i < 3; ++i)
  76. {
  77. ssOneLine >> vertexStr;
  78. size_t pos = vertexStr.find_first_of('/');
  79. std::string positionIndexStr = vertexStr.substr(0, pos);
  80. size_t pos2 = vertexStr.find_first_of('/', pos + 1);
  81. std::string texcoordIndexStr = vertexStr.substr(pos + 1, pos2 - pos - 1);
  82. std::string normalIndexStr = vertexStr.substr(pos2 + 1, vertexStr.length() - pos2 - 1);
  83. VertexDefine vd;
  84. vd.positionIndex = atoi(positionIndexStr.c_str())-1;
  85. vd.texcoordIndex = atoi(texcoordIndexStr.c_str())-1;
  86. vd.normalIndex = atoi(normalIndexStr.c_str())-1;
  87. //trim the same vertice
  88. int nCurrentVertexIndex = -1;
  89. size_t nCurrentVerticeCount = vertices.size();
  90. for(int j=0;j<nCurrentVerticeCount;++j)
  91. {
  92. if (vertices[j].positionIndex==vd.positionIndex&&
  93. vertices[j].texcoordIndex == vd.texcoordIndex&&
  94. vertices[j].normalIndex == vd.normalIndex)
  95. {
  96. nCurrentVertexIndex = j;
  97. break;
  98. }
  99. }
  100. if (nCurrentVertexIndex==-1)
  101. {
  102. nCurrentVertexIndex = (int)vertices.size();
  103. vertices.push_back(vd);
  104. }
  105. faces.push_back(nCurrentVertexIndex);
  106. }
  107. }
  108. }
  109. }
  110. //convert to opengl vbo & ibo
  111. int vertexCount = (int)vertices.size();
  112. VertexData*vertexes = new VertexData[vertexCount];
  113. for (int i=0;i<vertexCount;++i)
  114. {
  115. memcpy(vertexes[i].position, positions[vertices[i].positionIndex].v, sizeof(float) * 3);
  116. memcpy(vertexes[i].texcoord, texcoords[vertices[i].texcoordIndex].v, sizeof(float) * 2);
  117. memcpy(vertexes[i].normal, normals[vertices[i].normalIndex].v, sizeof(float) * 3);
  118. }
  119. //create vbo
  120. glGenBuffers(1, &mVBO);
  121. glBindBuffer(GL_ARRAY_BUFFER, mVBO);
  122. glBufferData(GL_ARRAY_BUFFER,sizeof(VertexData)*vertexCount,vertexes,GL_STATIC_DRAW);
  123. glBindBuffer(GL_ARRAY_BUFFER, 0);
  124. delete vertexes;
  125. //ibo
  126. mIndexCount = (int)faces.size();
  127. unsigned int *indexes = new unsigned int[mIndexCount];
  128. for (int i=0;i<mIndexCount;++i)
  129. {
  130. indexes[i] = faces[i];
  131. }
  132. glGenBuffers(1, &mIBO);
  133. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIBO);
  134. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*mIndexCount, indexes, GL_STATIC_DRAW);
  135. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  136. delete indexes;
  137. delete fileContent;
  138. }
  139. void ObjModel::Bind(GLint posLoc, GLint texcoordLoc, GLint normalLoc)
  140. {
  141. glBindBuffer(GL_ARRAY_BUFFER, mVBO);
  142. glEnableVertexAttribArray(posLoc);
  143. glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), 0);
  144. glEnableVertexAttribArray(texcoordLoc);
  145. glVertexAttribPointer(texcoordLoc, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)(sizeof(float) * 3));
  146. glEnableVertexAttribArray(normalLoc);
  147. glVertexAttribPointer(normalLoc, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)(sizeof(float) * 5));
  148. glBindBuffer(GL_ARRAY_BUFFER, 0);
  149. }
  150. void ObjModel::Draw()
  151. {
  152. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIBO);
  153. glDrawElements(GL_TRIANGLES, mIndexCount, GL_UNSIGNED_INT, 0);
  154. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  155. }