Small OpenGL based c++ rendering library
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.

loadobj.cpp 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. #include "loadobj.h"
  2. namespace segl {
  3. LoadOBJ::LoadOBJ(std::string _filename) : Modelloader(_filename) {
  4. }
  5. bool LoadOBJ::load(Model *m) {
  6. // Filestreams
  7. std::ifstream file(filename.c_str());
  8. std::ifstream matfile;
  9. std::string inbuf; // TMP-Var
  10. std::vector<std::string> v;
  11. std::vector<std::string> v2;
  12. int anz;
  13. unsigned int vertanz=0, polyanz=0, matanz=0, texanz=0, normanz=0;
  14. std::string materials;
  15. // Punkt2D *texdata = 0;
  16. // texdataanz = 0;
  17. // Punkt3D *normdata = 0;
  18. // normdata = 0;
  19. Material *usemat;
  20. if(!file)
  21. return false;
  22. // start counting items, read file
  23. while(getline(file, inbuf)) {
  24. anz = explode(inbuf, " ", &v);
  25. if(!anz)
  26. continue;
  27. if(v[0]=="f")
  28. polyanz++; // polygon
  29. else if(v[0]=="v")
  30. vertanz++; // vertex
  31. else if(v[0]=="mtllib") {
  32. if(anz>1)
  33. materials = trim(v[1]);
  34. // std::cout << "V1: " << v[1] << std::endl;
  35. } else if(v[0]=="vt")
  36. texanz++; // texcoord
  37. else if(v[0]=="vn")
  38. normanz++; // normal
  39. }
  40. if(materials!="") {
  41. matfile.open((rbasename(filename)+materials).c_str());
  42. if(matfile) {
  43. while(getline(matfile, inbuf)) {
  44. anz = explode(inbuf, " ", &v);
  45. if(!anz)
  46. continue;
  47. if(v[0]=="newmtl")
  48. matanz++;
  49. }
  50. }
  51. }
  52. // std::cout << "Vert: " << vertanz << " Poly: " << polyanz << " Mat: " << matanz << " (Matfile: " << materials << ") Norm: " << normanz << std::endl;
  53. if(!vertanz || !polyanz)
  54. return false;
  55. if(m->isLoaded())
  56. m->unload();
  57. // Allocate memory for filecontent
  58. m->meshdataanz = vertanz;
  59. m->meshdata = new Punkt3D[vertanz];
  60. m->polydataanz = polyanz;
  61. m->polydata = new Meshpolygon[polyanz];
  62. if(matanz) {
  63. m->matdataanz = matanz;
  64. m->matdata = new Material[matanz];
  65. }
  66. m->texdataanz = texanz;
  67. m->texdata = new Punkt2D[matanz];
  68. m->normdataanz = normanz;
  69. m->normdata = new Punkt3D[normanz];
  70. // Readout Material
  71. matfile.clear();
  72. matfile.seekg(0);
  73. if(matanz&&matfile) { // Got milk.. eh.. material?
  74. matanz = 0;
  75. Material mat;
  76. while(getline(matfile, inbuf)) {
  77. anz = explode(inbuf, " ", &v);
  78. if(!anz)
  79. continue;
  80. if(v[0]=="newmtl") {
  81. if(matanz!=0)
  82. m->matdata[matanz-1] = mat; // Push material
  83. matanz++;
  84. mat = Material();
  85. mat.name = trim(v[1]);
  86. } else if(v[0]=="Ka") {
  87. if(anz<4)
  88. continue;
  89. mat.ambient.set(std::atof(v[1].c_str()), std::atof(v[2].c_str()), std::atof(v[3].c_str()));
  90. } else if(v[0]=="Kd") {
  91. if(anz<4)
  92. continue;
  93. mat.diffuse.set(std::atof(v[1].c_str()), std::atof(v[2].c_str()), std::atof(v[3].c_str()));
  94. } else if(v[0]=="Ks") {
  95. if(anz<4)
  96. continue;
  97. mat.specular.set(std::atof(v[1].c_str()), std::atof(v[2].c_str()), std::atof(v[3].c_str()));
  98. }
  99. }
  100. // Last material wasnt pushed
  101. if(matanz!=0)
  102. m->matdata[matanz-1] = mat;
  103. }
  104. // Readout File
  105. usemat = &(m->backupmat); // If material required but not avilable use backup
  106. file.clear();
  107. file.seekg(0);
  108. polyanz = vertanz = normanz = texanz = 0; // Reset counters
  109. while(getline(file, inbuf)) {
  110. anz = explode(inbuf, " ", &v);
  111. if(!anz)
  112. continue;
  113. if(v[0]=="v") {
  114. if(anz<4)
  115. continue;
  116. m->meshdata[vertanz].set(std::atof(v[1].c_str()), std::atof(v[2].c_str()), std::atof(v[3].c_str()));
  117. vertanz++;
  118. } else if(v[0]=="vn") {
  119. if(anz<4)
  120. continue;
  121. m->normdata[normanz].set(std::atof(v[1].c_str()), std::atof(v[2].c_str()), std::atof(v[3].c_str()));
  122. normanz++;
  123. } else if(v[0]=="vt") {
  124. if(anz<3)
  125. continue;
  126. m->texdata[texanz].set(std::atof(v[1].c_str()), std::atof(v[2].c_str()));
  127. texanz++;
  128. } else if(v[0]=="f") {
  129. if(anz<4)
  130. continue;
  131. unsigned int arr[3][3] = { {0,0,0}, {0,0,0}, {0,0,0} };
  132. for(unsigned int i=0; i<3; i++) {
  133. int zanz = explode(v[i+1], "/", &v2);
  134. // std::cout << "explode " << v[i+1] << " anz " << zanz << std::endl;
  135. if(zanz<3) {
  136. if(zanz==1)
  137. arr[i][0] = std::atoi(v2[0].c_str());
  138. continue;
  139. }
  140. arr[i][0] = std::atoi(v2[0].c_str());
  141. arr[i][1] = std::atoi(v2[1].c_str());
  142. arr[i][2] = std::atoi(v2[2].c_str());
  143. // std::cout << "Loaded: " << arr[i][0] << " " << arr[i][1] << " " << arr[i][2] << " " << std::endl;
  144. // std::cout << "From: " << v2[0] << " " << v2[1] << " " << v2[2] << " " << std::endl;
  145. }
  146. if(arr[0][0])
  147. m->polydata[polyanz].m1.point = &(m->meshdata[arr[0][0]-1]);
  148. if(arr[0][1])
  149. m->polydata[polyanz].m1.tex = &(m->texdata[arr[0][1]-1]);
  150. if(arr[0][2])
  151. m->polydata[polyanz].m1.normal = &(m->normdata[arr[0][2]-1]);
  152. if(arr[1][0])
  153. m->polydata[polyanz].m2.point = &(m->meshdata[arr[1][0]-1]);
  154. if(arr[1][1])
  155. m->polydata[polyanz].m2.tex = &(m->texdata[arr[1][1]-1]);
  156. if(arr[1][2])
  157. m->polydata[polyanz].m2.normal = &(m->normdata[arr[1][2]-1]);
  158. if(arr[2][0])
  159. m->polydata[polyanz].m3.point = &(m->meshdata[arr[2][0]-1]);
  160. if(arr[2][1])
  161. m->polydata[polyanz].m3.tex = &(m->texdata[arr[2][1]-1]);
  162. if(arr[2][2])
  163. m->polydata[polyanz].m3.normal = &(m->normdata[arr[2][2]-1]);
  164. // std::cout << "POLY " << polyanz << std::endl;
  165. polyanz++;
  166. } else if(v[0]=="usemtl") {
  167. if(anz<2)
  168. continue;
  169. std::string fterm = trim(v[1]);
  170. for(unsigned int i=0; i < m->matdataanz; i++) {
  171. if(m->matdata[i].name==fterm) {
  172. usemat = &(m->matdata[i]);
  173. break;
  174. }
  175. }
  176. }
  177. v.clear();
  178. }
  179. // Calculate bounding box
  180. float minx=m->meshdata[0].x, maxx=m->meshdata[0].x, miny=m->meshdata[0].y, maxy=m->meshdata[0].y, minz=m->meshdata[0].z, maxz=m->meshdata[0].z;
  181. for(unsigned int i=0; i<m->meshdataanz; i++) {
  182. minx = std::min(minx, m->meshdata[i].x);
  183. maxx = std::max(maxx, m->meshdata[i].x);
  184. miny = std::min(miny, m->meshdata[i].y);
  185. maxy = std::max(maxy, m->meshdata[i].y);
  186. minz = std::min(minz, m->meshdata[i].z);
  187. maxz = std::max(maxz, m->meshdata[i].z);
  188. }
  189. // std::cout << "(" << minx << ", " << maxx << ") " << "(" << miny << ", " << maxy << ") " << "(" << minz << ", " << maxz << ") " << std::endl;
  190. m->boundingbox.d.set(minx, miny, minz);
  191. m->boundingbox.a.set(minx, miny, maxz);
  192. m->boundingbox.b.set(maxx, miny, maxz);
  193. m->boundingbox.c.set(maxx, miny, minz);
  194. m->boundingbox.h.set(minx, maxy, minz);
  195. m->boundingbox.e.set(minx, maxy, maxz);
  196. m->boundingbox.f.set(maxx, maxy, maxz);
  197. m->boundingbox.g.set(maxx, maxy, minz);
  198. m->boundingrad = std::max( std::abs(minx)+std::abs(maxx),
  199. std::max( std::abs(miny)+std::abs(maxy),
  200. std::abs(minz)+std::abs(maxz)));
  201. m->loaded = true;
  202. // std::cout << "Loaded!" << std::endl;
  203. return true;
  204. }
  205. } // namespace segl