Model.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. #include "Model.h"
  2. #define STB_IMAGE_IMPLEMENTATION
  3. #include "stb_image.h"
  4. Model::Model(string fileName)
  5. {
  6. std::string dirName = fileName;
  7. if (dirName.rfind("/") != std::string::npos)
  8. dirName = dirName.substr(0, dirName.rfind("/"));
  9. if (dirName.rfind("\\") != std::string::npos)
  10. dirName = dirName.substr(0, dirName.rfind("\\"));
  11. if (fileName == dirName)
  12. dirName = "";
  13. std::ifstream pFile(fileName.c_str());
  14. if (!pFile.is_open())
  15. {
  16. std::cout << "Could not open file " << fileName << std::endl;
  17. return;
  18. }
  19. ObjGroup* currentGroup = new ObjGroup();
  20. currentGroup->materialIndex = -1;
  21. while (!pFile.eof())
  22. {
  23. std::string line;
  24. std::getline(pFile, line);
  25. line = replace(line, "\t", " ");
  26. while (line.find(" ") != std::string::npos)
  27. line = replace(line, " ", " ");
  28. if (line == "")
  29. continue;
  30. if (line[0] == ' ')
  31. line = line.substr(1);
  32. if (line == "")
  33. continue;
  34. if (line[line.length() - 1] == ' ')
  35. line = line.substr(0, line.length() - 1);
  36. if (line == "")
  37. continue;
  38. if (line[0] == '#')
  39. continue;
  40. std::vector<std::string> params = split(line, " ");
  41. params[0] = toLower(params[0]);
  42. if (params[0] == "v")
  43. vertices.push_back(Vec3f((float)atof(params[1].c_str()), (float)atof(params[2].c_str()), (float)atof(params[3].c_str())));
  44. else if (params[0] == "vn")
  45. normals.push_back(Vec3f((float)atof(params[1].c_str()), (float)atof(params[2].c_str()), (float)atof(params[3].c_str())));
  46. else if (params[0] == "vt")
  47. texcoords.push_back(Vec2f((float)atof(params[1].c_str()), (float)atof(params[2].c_str())));
  48. else if (params[0] == "f")
  49. {
  50. for (size_t ii = 4; ii <= params.size(); ii++)
  51. {
  52. Face face;
  53. for (size_t i = ii - 3; i < ii; i++) //magische forlus om van quads triangles te maken ;)
  54. {
  55. Vertex vertex;
  56. std::vector<std::string> indices = split(params[i == (ii - 3) ? 1 : i], "/");
  57. if (indices.size() >= 1) //er is een positie
  58. vertex.position = atoi(indices[0].c_str()) - 1;
  59. if (indices.size() == 2) //alleen texture
  60. vertex.texcoord = atoi(indices[1].c_str()) - 1;
  61. if (indices.size() == 3) //v/t/n of v//n
  62. {
  63. if (indices[1] != "")
  64. vertex.texcoord = atoi(indices[1].c_str()) - 1;
  65. vertex.normal = atoi(indices[2].c_str()) - 1;
  66. }
  67. face.vertices.push_back(vertex);
  68. }
  69. currentGroup->faces.push_back(face);
  70. }
  71. }
  72. else if (params[0] == "s")
  73. {//smoothing
  74. }
  75. else if (params[0] == "mtllib")
  76. {
  77. loadMaterialFile(dirName + "/" + params[1], dirName);
  78. }
  79. else if (params[0] == "usemtl")
  80. {
  81. if (currentGroup->faces.size() != 0)
  82. groups.push_back(currentGroup);
  83. currentGroup = new ObjGroup();
  84. currentGroup->materialIndex = -1;
  85. for (size_t i = 0; i < materials.size(); i++)
  86. {
  87. MaterialInfo* info = materials[i];
  88. if (info->name == params[1])
  89. {
  90. currentGroup->materialIndex = i;
  91. break;
  92. }
  93. }
  94. if (currentGroup->materialIndex == -1)
  95. std::cout << "Could not find material name " << params[1] << std::endl;
  96. }
  97. }
  98. groups.push_back(currentGroup);
  99. }
  100. Model::~Model(void)
  101. {
  102. }
  103. void Model::draw()
  104. {
  105. for (auto &g : groups)
  106. {
  107. if (materials[g->materialIndex]->hasTexture)
  108. {
  109. glEnable(GL_TEXTURE_2D);
  110. materials[g->materialIndex]->texture->bind();
  111. }
  112. else
  113. {
  114. glDisable(GL_TEXTURE_2D);
  115. float color[4] = { 1, 0, 0, 1 };
  116. if (materials[g->materialIndex]->hasDiffuse)
  117. {
  118. memcpy(color, materials[g->materialIndex]->diffuseColor.v, 3 * sizeof(float));
  119. glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);
  120. }
  121. else if (materials[g->materialIndex]->hasAmbient)
  122. {
  123. memcpy(color, materials[g->materialIndex]->ambientColor.v, 3 * sizeof(float));
  124. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);
  125. }
  126. else if (materials[g->materialIndex]->hasSpecular)
  127. {
  128. memcpy(color, materials[g->materialIndex]->specularColor.v, 3 * sizeof(float));
  129. glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
  130. }
  131. }
  132. glBegin(GL_TRIANGLES);
  133. for (auto &f : g->faces)
  134. {
  135. for (auto &v : f.vertices)
  136. {
  137. glNormal3f(normals[v.normal].x, normals[v.normal].y, normals[v.normal].z);
  138. glTexCoord2f(texcoords[v.texcoord].x, texcoords[v.texcoord].y);
  139. glVertex3f(vertices[v.position].x, vertices[v.position].y, vertices[v.position].z);
  140. }
  141. }
  142. glEnd();
  143. }
  144. }
  145. void Model::loadMaterialFile(std::string fileName, std::string dirName)
  146. {
  147. std::ifstream pFile(fileName.c_str());
  148. if (!pFile.is_open())
  149. {
  150. std::cout << "Could not open file " << fileName << std::endl;
  151. return;
  152. }
  153. MaterialInfo* currentMaterial = NULL;
  154. while (!pFile.eof())
  155. {
  156. std::string line;
  157. std::getline(pFile, line);
  158. line = replace(line, "\t", " ");
  159. while (line.find(" ") != std::string::npos)
  160. line = replace(line, " ", " ");
  161. if (line == "")
  162. continue;
  163. if (line[0] == ' ')
  164. line = line.substr(1);
  165. if (line == "")
  166. continue;
  167. if (line[line.length() - 1] == ' ')
  168. line = line.substr(0, line.length() - 1);
  169. if (line == "")
  170. continue;
  171. if (line[0] == '#')
  172. continue;
  173. std::vector<std::string> params = split(line, " ");
  174. params[0] = toLower(params[0]);
  175. if (params[0] == "newmtl")
  176. {
  177. if (currentMaterial != NULL)
  178. {
  179. materials.push_back(currentMaterial);
  180. }
  181. currentMaterial = new MaterialInfo();
  182. currentMaterial->name = params[1];
  183. }
  184. else if (params[0] == "map_kd")
  185. {
  186. currentMaterial->hasTexture = true;
  187. currentMaterial->texture = new Texture(dirName + "/" + params[1]);
  188. }
  189. else if (params[0] == "kd")
  190. {
  191. currentMaterial->hasDiffuse = true;
  192. currentMaterial->diffuseColor = Vec3f(atof(params[1].c_str()), atof(params[2].c_str()), atof(params[3].c_str()));
  193. }
  194. else if (params[0] == "ka")
  195. {
  196. currentMaterial->hasAmbient = true;
  197. currentMaterial->ambientColor = Vec3f(atof(params[1].c_str()), atof(params[2].c_str()), atof(params[3].c_str()));
  198. }
  199. else if (params[0] == "ks")
  200. {
  201. currentMaterial->hasSpecular = true;
  202. currentMaterial->specularColor = Vec3f(atof(params[1].c_str()), atof(params[2].c_str()), atof(params[3].c_str()));
  203. }
  204. else
  205. std::cout << "Didn't parse " << params[0] << " in material file" << std::endl;
  206. }
  207. if (currentMaterial != NULL)
  208. materials.push_back(currentMaterial);
  209. }
  210. Model::MaterialInfo::MaterialInfo()
  211. {
  212. Texture *texture;
  213. hasTexture = false;
  214. }
  215. Model::Texture::Texture(const std::string & fileName)
  216. {
  217. int width, height, bpp;
  218. stbi_set_flip_vertically_on_load(true);
  219. unsigned char* imgData = stbi_load(fileName.c_str(), &width, &height, &bpp, 4);
  220. glGenTextures(1, &index);
  221. glBindTexture(GL_TEXTURE_2D, index);
  222. glTexImage2D(GL_TEXTURE_2D,
  223. 0, //level
  224. GL_RGBA, //internal format
  225. width, //width
  226. height, //height
  227. 0, //border
  228. GL_RGBA, //data format
  229. GL_UNSIGNED_BYTE, //data type
  230. imgData); //data
  231. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  232. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  233. stbi_image_free(imgData);
  234. }
  235. void Model::Texture::bind()
  236. {
  237. glBindTexture(GL_TEXTURE_2D, index);
  238. }