ModelLoader.cpp 7.0 KB

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