Model.cpp 8.2 KB

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