AMFImporter_Material.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /// \file AMFImporter_Material.cpp
  2. /// \brief Parsing data from material nodes.
  3. /// \date 2016
  4. /// \author [email protected]
  5. #ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
  6. #include "AMFImporter.hpp"
  7. #include "AMFImporter_Macro.hpp"
  8. namespace Assimp
  9. {
  10. // <color
  11. // profile="" - The ICC color space used to interpret the three color channels <r>, <g> and <b>.
  12. // >
  13. // </color>
  14. // A color definition.
  15. // Multi elements - No.
  16. // Parent element - <material>, <object>, <volume>, <vertex>, <triangle>.
  17. //
  18. // "profile" can be one of "sRGB", "AdobeRGB", "Wide-Gamut-RGB", "CIERGB", "CIELAB", or "CIEXYZ".
  19. // Children elements:
  20. // <r>, <g>, <b>, <a>
  21. // Multi elements - No.
  22. // Red, Greed, Blue and Alpha (transparency) component of a color in sRGB space, values ranging from 0 to 1. The
  23. // values can be specified as constants, or as a formula depending on the coordinates.
  24. void AMFImporter::ParseNode_Color()
  25. {
  26. std::string profile;
  27. CAMFImporter_NodeElement* ne;
  28. // Read attributes for node <color>.
  29. MACRO_ATTRREAD_LOOPBEG;
  30. MACRO_ATTRREAD_CHECK_RET("profile", profile, mReader->getAttributeValue);
  31. MACRO_ATTRREAD_LOOPEND;
  32. // create new color object.
  33. ne = new CAMFImporter_NodeElement_Color(mNodeElement_Cur);
  34. CAMFImporter_NodeElement_Color& als = *((CAMFImporter_NodeElement_Color*)ne);// alias for convenience
  35. als.Profile = profile;
  36. // Check for child nodes
  37. if(!mReader->isEmptyElement())
  38. {
  39. bool read_flag[4] = { false, false, false, false };
  40. ParseHelper_Node_Enter(ne);
  41. MACRO_NODECHECK_LOOPBEGIN("color");
  42. MACRO_NODECHECK_READCOMP_F("r", read_flag[0], als.Color.r);
  43. MACRO_NODECHECK_READCOMP_F("g", read_flag[1], als.Color.g);
  44. MACRO_NODECHECK_READCOMP_F("b", read_flag[2], als.Color.b);
  45. MACRO_NODECHECK_READCOMP_F("a", read_flag[3], als.Color.a);
  46. MACRO_NODECHECK_LOOPEND("color");
  47. ParseHelper_Node_Exit();
  48. // check that all components was defined
  49. if(!(read_flag[0] && read_flag[1] && read_flag[2])) throw DeadlyImportError("Not all color components are defined.");
  50. // check if <a> is absent. Then manualy add "a == 1".
  51. if(!read_flag[3]) als.Color.a = 1;
  52. }// if(!mReader->isEmptyElement())
  53. else
  54. {
  55. mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
  56. }// if(!mReader->isEmptyElement()) else
  57. als.Composed = false;
  58. mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
  59. }
  60. // <material
  61. // id="" - A unique material id. material ID "0" is reserved to denote no material (void) or sacrificial material.
  62. // >
  63. // </material>
  64. // An available material.
  65. // Multi elements - Yes.
  66. // Parent element - <amf>.
  67. void AMFImporter::ParseNode_Material()
  68. {
  69. std::string id;
  70. CAMFImporter_NodeElement* ne;
  71. // Read attributes for node <color>.
  72. MACRO_ATTRREAD_LOOPBEG;
  73. MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
  74. MACRO_ATTRREAD_LOOPEND;
  75. // create new object.
  76. ne = new CAMFImporter_NodeElement_Material(mNodeElement_Cur);
  77. // and assign read data
  78. ((CAMFImporter_NodeElement_Material*)ne)->ID = id;
  79. // Check for child nodes
  80. if(!mReader->isEmptyElement())
  81. {
  82. bool col_read = false;
  83. ParseHelper_Node_Enter(ne);
  84. MACRO_NODECHECK_LOOPBEGIN("material");
  85. if(XML_CheckNode_NameEqual("color"))
  86. {
  87. // Check if data already defined.
  88. if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <material>.");
  89. // read data and set flag about it
  90. ParseNode_Color();
  91. col_read = true;
  92. continue;
  93. }
  94. if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
  95. MACRO_NODECHECK_LOOPEND("material");
  96. ParseHelper_Node_Exit();
  97. }// if(!mReader->isEmptyElement())
  98. else
  99. {
  100. mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
  101. }// if(!mReader->isEmptyElement()) else
  102. mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
  103. }
  104. // <texture
  105. // id="" - Assigns a unique texture id for the new texture.
  106. // width="" - Width (horizontal size, x) of the texture, in pixels.
  107. // height="" - Height (lateral size, y) of the texture, in pixels.
  108. // depth="" - Depth (vertical size, z) of the texture, in pixels.
  109. // type="" - Encoding of the data in the texture. Currently allowed values are "grayscale" only. In grayscale mode, each pixel is represented by one byte
  110. // in the range of 0-255. When the texture is referenced using the tex function, these values are converted into a single floating point number in the
  111. // range of 0-1 (see Annex 2). A full color graphics will typically require three textures, one for each of the color channels. A graphic involving
  112. // transparency may require a fourth channel.
  113. // tiled="" - If true then texture repeated when UV-coordinates is greater than 1.
  114. // >
  115. // </triangle>
  116. // Specifies an texture data to be used as a map. Lists a sequence of Base64 values specifying values for pixels from left to right then top to bottom,
  117. // then layer by layer.
  118. // Multi elements - Yes.
  119. // Parent element - <amf>.
  120. void AMFImporter::ParseNode_Texture()
  121. {
  122. std::string id;
  123. uint32_t width = 0;
  124. uint32_t height = 0;
  125. uint32_t depth = 1;
  126. std::string type;
  127. bool tiled = false;
  128. std::string enc64_data;
  129. CAMFImporter_NodeElement* ne;
  130. // Read attributes for node <color>.
  131. MACRO_ATTRREAD_LOOPBEG;
  132. MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
  133. MACRO_ATTRREAD_CHECK_RET("width", width, XML_ReadNode_GetAttrVal_AsU32);
  134. MACRO_ATTRREAD_CHECK_RET("height", height, XML_ReadNode_GetAttrVal_AsU32);
  135. MACRO_ATTRREAD_CHECK_RET("depth", depth, XML_ReadNode_GetAttrVal_AsU32);
  136. MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue);
  137. MACRO_ATTRREAD_CHECK_RET("tiled", tiled, XML_ReadNode_GetAttrVal_AsBool);
  138. MACRO_ATTRREAD_LOOPEND;
  139. // create new texture object.
  140. ne = new CAMFImporter_NodeElement_Texture(mNodeElement_Cur);
  141. CAMFImporter_NodeElement_Texture& als = *((CAMFImporter_NodeElement_Texture*)ne);// alias for convenience
  142. // Check for child nodes
  143. if(!mReader->isEmptyElement()) XML_ReadNode_GetVal_AsString(enc64_data);
  144. // check that all components was defined
  145. if(id.empty()) throw DeadlyImportError("ID for texture must be defined.");
  146. if(width < 1) Throw_IncorrectAttrValue("width");
  147. if(height < 1) Throw_IncorrectAttrValue("height");
  148. if(depth < 1) Throw_IncorrectAttrValue("depth");
  149. if(type != "grayscale") Throw_IncorrectAttrValue("type");
  150. if(enc64_data.empty()) throw DeadlyImportError("Texture data not defined.");
  151. // copy data
  152. als.ID = id;
  153. als.Width = width;
  154. als.Height = height;
  155. als.Depth = depth;
  156. als.Tiled = tiled;
  157. ParseHelper_Decode_Base64(enc64_data, als.Data);
  158. // check data size
  159. if((width * height * depth) != als.Data.size()) throw DeadlyImportError("Texture has incorrect data size.");
  160. mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
  161. mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
  162. }
  163. // <texmap
  164. // rtexid="" - Texture ID for red color component.
  165. // gtexid="" - Texture ID for green color component.
  166. // btexid="" - Texture ID for blue color component.
  167. // atexid="" - Texture ID for alpha color component. Optional.
  168. // >
  169. // </texmap>, old name: <map>
  170. // Specifies texture coordinates for triangle.
  171. // Multi elements - No.
  172. // Parent element - <triangle>.
  173. // Children elements:
  174. // <utex1>, <utex2>, <utex3>, <vtex1>, <vtex2>, <vtex3>. Old name: <u1>, <u2>, <u3>, <v1>, <v2>, <v3>.
  175. // Multi elements - No.
  176. // Texture coordinates for every vertex of triangle.
  177. void AMFImporter::ParseNode_TexMap(const bool pUseOldName)
  178. {
  179. std::string rtexid, gtexid, btexid, atexid;
  180. CAMFImporter_NodeElement* ne;
  181. // Read attributes for node <color>.
  182. MACRO_ATTRREAD_LOOPBEG;
  183. MACRO_ATTRREAD_CHECK_RET("rtexid", rtexid, mReader->getAttributeValue);
  184. MACRO_ATTRREAD_CHECK_RET("gtexid", gtexid, mReader->getAttributeValue);
  185. MACRO_ATTRREAD_CHECK_RET("btexid", btexid, mReader->getAttributeValue);
  186. MACRO_ATTRREAD_CHECK_RET("atexid", atexid, mReader->getAttributeValue);
  187. MACRO_ATTRREAD_LOOPEND;
  188. // create new texture coordinates object.
  189. ne = new CAMFImporter_NodeElement_TexMap(mNodeElement_Cur);
  190. CAMFImporter_NodeElement_TexMap& als = *((CAMFImporter_NodeElement_TexMap*)ne);// alias for convenience
  191. // check data
  192. if(rtexid.empty() && gtexid.empty() && btexid.empty()) throw DeadlyImportError("ParseNode_TexMap. At least one texture ID must be defined.");
  193. // Check for children nodes
  194. XML_CheckNode_MustHaveChildren();
  195. // read children nodes
  196. bool read_flag[6] = { false, false, false, false, false, false };
  197. ParseHelper_Node_Enter(ne);
  198. if(!pUseOldName)
  199. {
  200. MACRO_NODECHECK_LOOPBEGIN("texmap");
  201. MACRO_NODECHECK_READCOMP_F("utex1", read_flag[0], als.TextureCoordinate[0].x);
  202. MACRO_NODECHECK_READCOMP_F("utex2", read_flag[1], als.TextureCoordinate[1].x);
  203. MACRO_NODECHECK_READCOMP_F("utex3", read_flag[2], als.TextureCoordinate[2].x);
  204. MACRO_NODECHECK_READCOMP_F("vtex1", read_flag[3], als.TextureCoordinate[0].y);
  205. MACRO_NODECHECK_READCOMP_F("vtex2", read_flag[4], als.TextureCoordinate[1].y);
  206. MACRO_NODECHECK_READCOMP_F("vtex3", read_flag[5], als.TextureCoordinate[2].y);
  207. MACRO_NODECHECK_LOOPEND("texmap");
  208. }
  209. else
  210. {
  211. MACRO_NODECHECK_LOOPBEGIN("map");
  212. MACRO_NODECHECK_READCOMP_F("u1", read_flag[0], als.TextureCoordinate[0].x);
  213. MACRO_NODECHECK_READCOMP_F("u2", read_flag[1], als.TextureCoordinate[1].x);
  214. MACRO_NODECHECK_READCOMP_F("u3", read_flag[2], als.TextureCoordinate[2].x);
  215. MACRO_NODECHECK_READCOMP_F("v1", read_flag[3], als.TextureCoordinate[0].y);
  216. MACRO_NODECHECK_READCOMP_F("v2", read_flag[4], als.TextureCoordinate[1].y);
  217. MACRO_NODECHECK_READCOMP_F("v3", read_flag[5], als.TextureCoordinate[2].y);
  218. MACRO_NODECHECK_LOOPEND("map");
  219. }// if(!pUseOldName) else
  220. ParseHelper_Node_Exit();
  221. // check that all components was defined
  222. if(!(read_flag[0] && read_flag[1] && read_flag[2] && read_flag[3] && read_flag[4] && read_flag[5]))
  223. throw DeadlyImportError("Not all texture coordinates are defined.");
  224. // copy attributes data
  225. als.TextureID_R = rtexid;
  226. als.TextureID_G = gtexid;
  227. als.TextureID_B = btexid;
  228. als.TextureID_A = atexid;
  229. mNodeElement_List.push_back(ne);// add to node element list because its a new object in graph.
  230. }
  231. }// namespace Assimp
  232. #endif // !ASSIMP_BUILD_NO_AMF_IMPORTER