ExporterMaterial.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. // Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include "Exporter.h"
  6. #include <iostream>
  7. //==============================================================================
  8. void Exporter::exportMaterial(const aiMaterial& mtl) const
  9. {
  10. std::string diffTex;
  11. std::string normTex;
  12. std::string specColTex;
  13. std::string shininessTex;
  14. std::string dispTex;
  15. std::string emissiveTex;
  16. std::string metallicTex;
  17. aiString path;
  18. std::string name = getMaterialName(mtl);
  19. LOGI("Exporting material %s", name.c_str());
  20. // Diffuse texture
  21. if(mtl.GetTextureCount(aiTextureType_DIFFUSE) > 0)
  22. {
  23. if(mtl.GetTexture(aiTextureType_DIFFUSE, 0, &path) == AI_SUCCESS)
  24. {
  25. diffTex = getFilename(path.C_Str());
  26. }
  27. else
  28. {
  29. ERROR("Failed to retrieve texture");
  30. }
  31. }
  32. // Normal texture
  33. if(mtl.GetTextureCount(aiTextureType_NORMALS) > 0)
  34. {
  35. if(mtl.GetTexture(aiTextureType_NORMALS, 0, &path) == AI_SUCCESS)
  36. {
  37. normTex = getFilename(path.C_Str());
  38. }
  39. else
  40. {
  41. ERROR("Failed to retrieve texture");
  42. }
  43. }
  44. // Specular color
  45. if(mtl.GetTextureCount(aiTextureType_SPECULAR) > 0)
  46. {
  47. if(mtl.GetTexture(aiTextureType_SPECULAR, 0, &path) == AI_SUCCESS)
  48. {
  49. specColTex = getFilename(path.C_Str());
  50. }
  51. else
  52. {
  53. ERROR("Failed to retrieve texture");
  54. }
  55. }
  56. // Shininess color
  57. if(mtl.GetTextureCount(aiTextureType_SHININESS) > 0)
  58. {
  59. if(mtl.GetTexture(aiTextureType_SHININESS, 0, &path) == AI_SUCCESS)
  60. {
  61. shininessTex = getFilename(path.C_Str());
  62. }
  63. else
  64. {
  65. ERROR("Failed to retrieve texture");
  66. }
  67. }
  68. // Height texture
  69. if(mtl.GetTextureCount(aiTextureType_DISPLACEMENT) > 0)
  70. {
  71. if(mtl.GetTexture(aiTextureType_DISPLACEMENT, 0, &path) == AI_SUCCESS)
  72. {
  73. dispTex = getFilename(path.C_Str());
  74. }
  75. else
  76. {
  77. ERROR("Failed to retrieve texture");
  78. }
  79. }
  80. // Emissive texture
  81. if(mtl.GetTextureCount(aiTextureType_EMISSIVE) > 0)
  82. {
  83. if(mtl.GetTexture(aiTextureType_EMISSIVE, 0, &path) == AI_SUCCESS)
  84. {
  85. emissiveTex = getFilename(path.C_Str());
  86. }
  87. else
  88. {
  89. ERROR("Failed to retrieve texture");
  90. }
  91. }
  92. // Metallic texture
  93. if(mtl.GetTextureCount(aiTextureType_REFLECTION) > 0)
  94. {
  95. if(mtl.GetTexture(aiTextureType_REFLECTION, 0, &path) == AI_SUCCESS)
  96. {
  97. metallicTex = getFilename(path.C_Str());
  98. }
  99. else
  100. {
  101. ERROR("Failed to retrieve texture");
  102. }
  103. }
  104. // Write file
  105. static const char* diffNormSpecFragTemplate =
  106. #include "templates/diffNormSpecFrag.h"
  107. ;
  108. static const char* simpleVertTemplate =
  109. #include "templates/simpleVert.h"
  110. ;
  111. static const char* tessVertTemplate =
  112. #include "templates/tessVert.h"
  113. ;
  114. static const char* readRgbFromTextureTemplate = R"(
  115. <operation>
  116. <id>%id%</id>
  117. <returnType>vec3</returnType>
  118. <function>readRgbFromTexture</function>
  119. <arguments>
  120. <argument>%map%</argument>
  121. <argument>out2</argument>
  122. </arguments>
  123. </operation>)";
  124. static const char* readRFromTextureTemplate = R"(
  125. <operation>
  126. <id>%id%</id>
  127. <returnType>float</returnType>
  128. <function>readRFromTexture</function>
  129. <arguments>
  130. <argument>%map%</argument>
  131. <argument>out2</argument>
  132. </arguments>
  133. </operation>)";
  134. // Compose full template
  135. // First geometry part
  136. std::string materialStr;
  137. materialStr = R"(<?xml version="1.0" encoding="UTF-8" ?>)";
  138. materialStr += "\n<material>\n\t<programs>\n";
  139. if(/*dispTex.empty()*/ 1)
  140. {
  141. materialStr += simpleVertTemplate;
  142. }
  143. else
  144. {
  145. materialStr += tessVertTemplate;
  146. }
  147. materialStr += "\n";
  148. // Then fragment part
  149. materialStr += diffNormSpecFragTemplate;
  150. materialStr += "\n\t</programs>\t</material>";
  151. // Replace strings
  152. if(!dispTex.empty())
  153. {
  154. materialStr =
  155. replaceAllString(materialStr, "%dispMap%", m_texrpath + dispTex);
  156. }
  157. // Diffuse
  158. if(!diffTex.empty())
  159. {
  160. materialStr = replaceAllString(materialStr,
  161. "%diffuseColorInput%",
  162. R"(<input><type>sampler2D</type><name>uDiffuseColor</name><value>)"
  163. + m_texrpath
  164. + diffTex
  165. + R"(</value></input>)");
  166. materialStr = replaceAllString(
  167. materialStr, "%diffuseColorFunc%", readRgbFromTextureTemplate);
  168. materialStr = replaceAllString(materialStr, "%id%", "10");
  169. materialStr = replaceAllString(materialStr, "%map%", "uDiffuseColor");
  170. materialStr =
  171. replaceAllString(materialStr, "%diffuseColorArg%", "out10");
  172. }
  173. else
  174. {
  175. aiColor3D diffCol = {0.0, 0.0, 0.0};
  176. mtl.Get(AI_MATKEY_COLOR_DIFFUSE, diffCol);
  177. materialStr = replaceAllString(materialStr,
  178. "%diffuseColorInput%",
  179. R"(<input><type>vec3</type><name>uDiffuseColor</name><value>)"
  180. + std::to_string(diffCol[0])
  181. + " "
  182. + std::to_string(diffCol[1])
  183. + " "
  184. + std::to_string(diffCol[2])
  185. + R"(</value></input>)");
  186. materialStr = replaceAllString(materialStr, "%diffuseColorFunc%", "");
  187. materialStr =
  188. replaceAllString(materialStr, "%diffuseColorArg%", "uDiffuseColor");
  189. }
  190. // Normal
  191. if(!normTex.empty())
  192. {
  193. materialStr = replaceAllString(materialStr,
  194. "%normalInput%",
  195. R"(<input><type>sampler2D</type><name>uNormal</name><value>)"
  196. + m_texrpath
  197. + normTex
  198. + R"(</value></input>)");
  199. materialStr = replaceAllString(materialStr,
  200. "%normalFunc%",
  201. R"(
  202. <operation>
  203. <id>20</id>
  204. <returnType>vec3</returnType>
  205. <function>readNormalFromTexture</function>
  206. <arguments>
  207. <argument>out0</argument>
  208. <argument>out1</argument>
  209. <argument>uNormal</argument>
  210. <argument>out2</argument>
  211. </arguments>
  212. </operation>)");
  213. materialStr = replaceAllString(materialStr, "%normalArg%", "out20");
  214. }
  215. else
  216. {
  217. materialStr = replaceAllString(materialStr, "%normalInput%", " ");
  218. materialStr = replaceAllString(materialStr, "%normalFunc%", " ");
  219. materialStr = replaceAllString(materialStr, "%normalArg%", "out0");
  220. }
  221. // Specular
  222. if(!specColTex.empty())
  223. {
  224. materialStr = replaceAllString(materialStr,
  225. "%specularColorInput%",
  226. R"(<input><type>sampler2D</type><name>uSpecularColor</name><value>)"
  227. + m_texrpath
  228. + specColTex
  229. + R"(</value></input>)");
  230. materialStr = replaceAllString(
  231. materialStr, "%specularColorFunc%", readRgbFromTextureTemplate);
  232. materialStr = replaceAllString(materialStr, "%id%", "50");
  233. materialStr = replaceAllString(materialStr, "%map%", "uSpecularColor");
  234. materialStr =
  235. replaceAllString(materialStr, "%specularColorArg%", "out50");
  236. }
  237. else
  238. {
  239. aiColor3D specCol = {0.0, 0.0, 0.0};
  240. mtl.Get(AI_MATKEY_COLOR_SPECULAR, specCol);
  241. materialStr = replaceAllString(materialStr,
  242. "%specularColorInput%",
  243. R"(<input><type>vec3</type><name>uSpecularColor</name><value>)"
  244. + std::to_string(specCol[0])
  245. + " "
  246. + std::to_string(specCol[1])
  247. + " "
  248. + std::to_string(specCol[2])
  249. + R"(</value></input>)");
  250. materialStr = replaceAllString(materialStr, "%specularColorFunc%", "");
  251. materialStr = replaceAllString(
  252. materialStr, "%specularColorArg%", "uSpecularColor");
  253. }
  254. if(!shininessTex.empty())
  255. {
  256. materialStr = replaceAllString(materialStr,
  257. "%specularPowerInput%",
  258. R"(<input><type>sampler2D</type><name>uSpecularPower</name><value>)"
  259. + m_texrpath
  260. + shininessTex
  261. + R"(</value></input>)");
  262. materialStr = replaceAllString(
  263. materialStr, "%specularPowerValue%", m_texrpath + shininessTex);
  264. materialStr = replaceAllString(
  265. materialStr, "%specularPowerFunc%", readRFromTextureTemplate);
  266. materialStr = replaceAllString(materialStr, "%id%", "60");
  267. materialStr = replaceAllString(materialStr, "%map%", "uSpecularPower");
  268. materialStr =
  269. replaceAllString(materialStr, "%specularPowerArg%", "out60");
  270. }
  271. else
  272. {
  273. float shininess = 0.0;
  274. mtl.Get(AI_MATKEY_SHININESS, shininess);
  275. const float MAX_SHININESS = 511.0;
  276. shininess = std::min(MAX_SHININESS, shininess);
  277. if(shininess > MAX_SHININESS)
  278. {
  279. LOGW("Shininness exceeds %f", MAX_SHININESS);
  280. }
  281. shininess = shininess / MAX_SHININESS;
  282. materialStr = replaceAllString(materialStr,
  283. "%specularPowerInput%",
  284. R"(<input><type>float</type><name>uSpecularPower</name><value>)"
  285. + std::to_string(shininess)
  286. + R"(</value></input>)");
  287. materialStr = replaceAllString(materialStr, "%specularPowerFunc%", "");
  288. materialStr = replaceAllString(
  289. materialStr, "%specularPowerArg%", "uSpecularPower");
  290. }
  291. materialStr = replaceAllString(materialStr, "%maxSpecularPower%", " ");
  292. // Emission
  293. aiColor3D emissionCol = {0.0, 0.0, 0.0};
  294. mtl.Get(AI_MATKEY_COLOR_EMISSIVE, emissionCol);
  295. float emission = (emissionCol[0] + emissionCol[1] + emissionCol[2]) / 3.0;
  296. if(!emissiveTex.empty())
  297. {
  298. materialStr = replaceAllString(materialStr,
  299. "%emissionInput%",
  300. "<input><type>sampler2D</type><name>emissionTex</name><value>"
  301. + m_texrpath
  302. + emissiveTex
  303. + "</value></input>)\n"
  304. + "\t\t\t\t<input><type>float</type><name>emission</"
  305. "name><value>"
  306. + std::to_string(10.0)
  307. + "</value><const>1</const></input>");
  308. std::string func = readRFromTextureTemplate;
  309. func = replaceAllString(func, "%id%", "71");
  310. func = replaceAllString(func, "%map%", "emissionTex");
  311. func += R"(
  312. <operation>
  313. <id>70</id>
  314. <returnType>float</returnType>
  315. <function>mul</function>
  316. <arguments>
  317. <argument>out71</argument>
  318. <argument>emission</argument>
  319. </arguments>
  320. </operation>)";
  321. materialStr = replaceAllString(materialStr, "%emissionFunc%", func);
  322. materialStr = replaceAllString(materialStr, "%map%", "emissionTex");
  323. materialStr = replaceAllString(materialStr, "%emissionArg%", "out70");
  324. }
  325. else
  326. {
  327. materialStr = replaceAllString(materialStr,
  328. "%emissionInput%",
  329. R"(<input><type>float</type><name>emission</name><value>)"
  330. + std::to_string(emission)
  331. + R"(</value><const>1</const></input>)");
  332. materialStr = replaceAllString(materialStr, "%emissionFunc%", "");
  333. materialStr =
  334. replaceAllString(materialStr, "%emissionArg%", "emission");
  335. }
  336. // Metallic
  337. if(!metallicTex.empty())
  338. {
  339. materialStr = replaceAllString(materialStr,
  340. "%metallicInput%",
  341. "<input><type>sampler2D</type><name>metallicTex</name><value>"
  342. + m_texrpath
  343. + metallicTex
  344. + "</value></input>");
  345. std::string func = readRFromTextureTemplate;
  346. func = replaceAllString(func, "%id%", "80");
  347. func = replaceAllString(func, "%map%", "metallicTex");
  348. materialStr = replaceAllString(materialStr, "%metallicFunc%", func);
  349. materialStr = replaceAllString(materialStr, "%map%", "metallicTex");
  350. materialStr = replaceAllString(materialStr, "%metallicArg%", "out80");
  351. }
  352. else
  353. {
  354. float metallic = 0.0;
  355. if(mtl.mAnKiProperties.find("metallic") != mtl.mAnKiProperties.end())
  356. {
  357. metallic = std::stof(mtl.mAnKiProperties.at("metallic"));
  358. }
  359. materialStr = replaceAllString(materialStr,
  360. "%metallicInput%",
  361. R"(<input><type>float</type><name>metallic</name><value>)"
  362. + std::to_string(metallic)
  363. + R"(</value><const>1</const></input>)");
  364. materialStr = replaceAllString(materialStr, "%metallicFunc%", "");
  365. materialStr =
  366. replaceAllString(materialStr, "%metallicArg%", "metallic");
  367. }
  368. // Height to parallax
  369. if(!dispTex.empty())
  370. {
  371. materialStr = replaceAllString(materialStr,
  372. "%heightVertInput%",
  373. "<input><type>mat4</type><name>anki_mv"
  374. "</name><inShadow>0</inShadow></input>");
  375. materialStr = replaceAllString(materialStr,
  376. "%heightVertFunc%",
  377. R"(<operation>
  378. <id>2</id>
  379. <returnType>void</returnType>
  380. <function>writeParallax</function>
  381. <arguments>
  382. <argument>anki_n</argument>
  383. <argument>anki_mv</argument>
  384. </arguments>
  385. </operation>)");
  386. materialStr = replaceAllString(materialStr,
  387. "%heightInput%",
  388. "<input><type>sampler2D</type><name>heightMap</name>"
  389. "<value>"
  390. + m_texrpath
  391. + dispTex
  392. + "</value></input>\n"
  393. "\t\t\t\t<input><type>float</type><name>heightMapScale</name>"
  394. "<value>0.05</value><const>1</const></input>");
  395. // At this point everyone will have to use out4 as tex coords
  396. materialStr = replaceAllString(materialStr,
  397. "<argument>out2</argument>",
  398. "<argument>out4</argument>");
  399. materialStr = replaceAllString(materialStr,
  400. "%heightFunc%",
  401. R"(<operation>
  402. <id>4</id>
  403. <returnType>vec2</returnType>
  404. <function>computeTextureCoordParallax</function>
  405. <arguments>
  406. <argument>heightMap</argument>
  407. <argument>out2</argument>
  408. <argument>heightMapScale</argument>
  409. </arguments>
  410. </operation>)");
  411. }
  412. else
  413. {
  414. materialStr = replaceAllString(materialStr, "%heightVertInput%", " ");
  415. materialStr = replaceAllString(materialStr, "%heightVertFunc%", " ");
  416. materialStr = replaceAllString(materialStr, "%heightInput%", " ");
  417. materialStr = replaceAllString(materialStr, "%heightFunc%", " ");
  418. }
  419. // Continue
  420. materialStr =
  421. replaceAllString(materialStr, "%diffuseMap%", m_texrpath + diffTex);
  422. // Subsurface
  423. materialStr = replaceAllString(materialStr,
  424. "%subsurfaceInput%",
  425. "<input><type>float</type><name>subsurface</name>"
  426. "<const>1</const><value>0.0</value></input>");
  427. materialStr =
  428. replaceAllString(materialStr, "%subsurfaceArg%", "subsurface");
  429. // Replace texture extensions with .anki
  430. materialStr = replaceAllString(materialStr, ".tga", ".ankitex");
  431. materialStr = replaceAllString(materialStr, ".png", ".ankitex");
  432. materialStr = replaceAllString(materialStr, ".jpg", ".ankitex");
  433. materialStr = replaceAllString(materialStr, ".jpeg", ".ankitex");
  434. // Open and write file
  435. std::fstream file;
  436. file.open(m_outputDirectory + name + ".ankimtl", std::ios::out);
  437. file << materialStr;
  438. }