💿🐜 Antkeeper source code https://antkeeper.com
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.

198 lines
5.1 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
6 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. /*
  2. * Copyright (C) 2017 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper Source Code.
  5. *
  6. * Antkeeper Source Code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper Source Code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "material-loader.hpp"
  20. #include <fstream>
  21. #include <sstream>
  22. #include <vector>
  23. MaterialLoader::MaterialLoader()
  24. {
  25. textureLoader.setGamma(1.0f);
  26. textureLoader.setCubemap(false);
  27. textureLoader.setMipmapChain(false);
  28. textureLoader.setMaxAnisotropy(16.0f);
  29. }
  30. MaterialLoader::~MaterialLoader()
  31. {
  32. unload();
  33. }
  34. void MaterialLoader::unload()
  35. {
  36. for (auto it = materialCache.begin(); it != materialCache.end(); ++it)
  37. {
  38. delete it->second;
  39. }
  40. materialCache.clear();
  41. for (auto it = textureCache.begin(); it != textureCache.end(); ++it)
  42. {
  43. delete it->second;
  44. }
  45. textureCache.clear();
  46. }
  47. PhysicalMaterial* MaterialLoader::load(const std::string& filename)
  48. {
  49. // Check if material exists in cache
  50. auto it = materialCache.find(filename);
  51. if (it != materialCache.end())
  52. {
  53. return it->second;
  54. }
  55. // Allocate new material
  56. PhysicalMaterial* material = new PhysicalMaterial();
  57. // Open file
  58. std::ifstream file(filename.c_str(), std::ifstream::in);
  59. if (!file.is_open())
  60. {
  61. std::cerr << "MaterialLoader::load(): Failed to open material file \"" << filename << "\"" << std::endl;
  62. delete material;
  63. return nullptr;
  64. }
  65. // Parse lines
  66. std::string line;
  67. while (file.good() && std::getline(file, line))
  68. {
  69. const std::string whitespace = " \t";
  70. // Skip empty lines
  71. if (line.empty())
  72. {
  73. continue;
  74. }
  75. // Find position of first character in command string
  76. std::size_t firstCommand = line.find_first_not_of(whitespace, 0);
  77. if (firstCommand == std::string::npos)
  78. {
  79. continue;
  80. }
  81. // Find position of first character in delimeter string
  82. std::size_t firstDelimeter = line.find_first_of(whitespace, firstCommand);
  83. if (firstDelimeter == std::string::npos)
  84. {
  85. continue;
  86. }
  87. // Find position of first character in arguments string
  88. std::size_t firstArgument = line.find_first_not_of(whitespace, firstDelimeter);
  89. if (firstArgument == std::string::npos)
  90. {
  91. firstArgument = firstDelimeter + 1;
  92. }
  93. // Form command string and argument list string
  94. std::string command = line.substr(firstCommand, firstDelimeter - firstCommand);
  95. std::string argumentList = line.substr(firstArgument);
  96. // Form vector of argument strings
  97. std::vector<std::string> arguments;
  98. std::istringstream argumentStream(argumentList);
  99. std::string argument;
  100. while (argumentStream >> argument)
  101. {
  102. arguments.push_back(argument);
  103. }
  104. if (command == "albedo" && arguments.size() == 3)
  105. {
  106. std::stringstream(arguments[0]) >> material->albedo.x;
  107. std::stringstream(arguments[1]) >> material->albedo.y;
  108. std::stringstream(arguments[2]) >> material->albedo.z;
  109. }
  110. else if (command == "opacity" && arguments.size() == 1)
  111. {
  112. std::stringstream(arguments[0]) >> material->opacity;
  113. }
  114. else if (command == "metalness" && arguments.size() == 1)
  115. {
  116. std::stringstream(arguments[0]) >> material->metalness;
  117. }
  118. else if (command == "roughness" && arguments.size() == 1)
  119. {
  120. std::stringstream(arguments[0]) >> material->roughness;
  121. }
  122. else if (command == "translucent" && arguments.size() == 1)
  123. {
  124. int translucent = 0;
  125. std::stringstream(arguments[0]) >> translucent;
  126. if (translucent)
  127. {
  128. material->flags |= static_cast<unsigned int>(PhysicalMaterial::Flags::TRANSLUCENT);
  129. }
  130. }
  131. else if (command == "albedo-opacity-map")
  132. {
  133. material->albedoOpacityMap = loadTexture(argumentList);
  134. }
  135. else if (command == "metalness-roughness-map")
  136. {
  137. material->metalnessRoughnessMap = loadTexture(argumentList);
  138. }
  139. else if (command == "normal-occlusion-map")
  140. {
  141. material->normalOcclusionMap = loadTexture(argumentList);
  142. }
  143. else if (command[0] != '#')
  144. {
  145. std::cerr << "MaterialLoader::load(): Invalid line \"" << line << "\" in file \"" << filename << "\"" << std::endl;
  146. }
  147. }
  148. // Close file
  149. file.close();
  150. // Add material to cache
  151. materialCache[filename] = material;
  152. return material;
  153. }
  154. Texture* MaterialLoader::loadTexture(const std::string& filename)
  155. {
  156. // Check if texture exists in cache
  157. auto it = textureCache.find(filename);
  158. if (it != textureCache.end())
  159. {
  160. return it->second;
  161. }
  162. std::string fullFilename = std::string("data/textures/") + filename;
  163. // Load texture
  164. Texture* texture = textureLoader.load(fullFilename);
  165. if (!texture)
  166. {
  167. std::cerr << "MaterialLoader::loadTexture(): Failed to load texture file \"" << fullFilename << "\"" << std::endl;
  168. return nullptr;
  169. }
  170. // Add texture to cache
  171. textureCache[filename] = texture;
  172. return texture;
  173. }