269 lines
10 KiB
C++
269 lines
10 KiB
C++
|
/// \file AMFImporter_Material.cpp
|
|||
|
/// \brief Parsing data from material nodes.
|
|||
|
/// \date 2016
|
|||
|
/// \author smal.root@gmail.com
|
|||
|
|
|||
|
#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
|
|||
|
|
|||
|
#include "AMFImporter.hpp"
|
|||
|
#include "AMFImporter_Macro.hpp"
|
|||
|
|
|||
|
namespace Assimp
|
|||
|
{
|
|||
|
|
|||
|
// <color
|
|||
|
// profile="" - The ICC color space used to interpret the three color channels <r>, <g> and <b>.
|
|||
|
// >
|
|||
|
// </color>
|
|||
|
// A color definition.
|
|||
|
// Multi elements - No.
|
|||
|
// Parent element - <material>, <object>, <volume>, <vertex>, <triangle>.
|
|||
|
//
|
|||
|
// "profile" can be one of "sRGB", "AdobeRGB", "Wide-Gamut-RGB", "CIERGB", "CIELAB", or "CIEXYZ".
|
|||
|
// Children elements:
|
|||
|
// <r>, <g>, <b>, <a>
|
|||
|
// Multi elements - No.
|
|||
|
// Red, Greed, Blue and Alpha (transparency) component of a color in sRGB space, values ranging from 0 to 1. The
|
|||
|
// values can be specified as constants, or as a formula depending on the coordinates.
|
|||
|
void AMFImporter::ParseNode_Color()
|
|||
|
{
|
|||
|
std::string profile;
|
|||
|
CAMFImporter_NodeElement* ne;
|
|||
|
|
|||
|
// Read attributes for node <color>.
|
|||
|
MACRO_ATTRREAD_LOOPBEG;
|
|||
|
MACRO_ATTRREAD_CHECK_RET("profile", profile, mReader->getAttributeValue);
|
|||
|
MACRO_ATTRREAD_LOOPEND;
|
|||
|
|
|||
|
// create new color object.
|
|||
|
ne = new CAMFImporter_NodeElement_Color(mNodeElement_Cur);
|
|||
|
|
|||
|
CAMFImporter_NodeElement_Color& als = *((CAMFImporter_NodeElement_Color*)ne);// alias for convenience
|
|||
|
|
|||
|
als.Profile = profile;
|
|||
|
// Check for child nodes
|
|||
|
if(!mReader->isEmptyElement())
|
|||
|
{
|
|||
|
bool read_flag[4] = { false, false, false, false };
|
|||
|
|
|||
|
ParseHelper_Node_Enter(ne);
|
|||
|
MACRO_NODECHECK_LOOPBEGIN("color");
|
|||
|
MACRO_NODECHECK_READCOMP_F("r", read_flag[0], als.Color.r);
|
|||
|
MACRO_NODECHECK_READCOMP_F("g", read_flag[1], als.Color.g);
|
|||
|
MACRO_NODECHECK_READCOMP_F("b", read_flag[2], als.Color.b);
|
|||
|
MACRO_NODECHECK_READCOMP_F("a", read_flag[3], als.Color.a);
|
|||
|
MACRO_NODECHECK_LOOPEND("color");
|
|||
|
ParseHelper_Node_Exit();
|
|||
|
// check that all components was defined
|
|||
|
if(!(read_flag[0] && read_flag[1] && read_flag[2])) throw DeadlyImportError("Not all color components are defined.");
|
|||
|
// check if <a> is absent. Then manualy add "a == 1".
|
|||
|
if(!read_flag[3]) als.Color.a = 1;
|
|||
|
|
|||
|
}// if(!mReader->isEmptyElement())
|
|||
|
else
|
|||
|
{
|
|||
|
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
|
|||
|
}// if(!mReader->isEmptyElement()) else
|
|||
|
|
|||
|
als.Composed = false;
|
|||
|
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
|
|||
|
}
|
|||
|
|
|||
|
// <material
|
|||
|
// id="" - A unique material id. material ID "0" is reserved to denote no material (void) or sacrificial material.
|
|||
|
// >
|
|||
|
// </material>
|
|||
|
// An available material.
|
|||
|
// Multi elements - Yes.
|
|||
|
// Parent element - <amf>.
|
|||
|
void AMFImporter::ParseNode_Material()
|
|||
|
{
|
|||
|
std::string id;
|
|||
|
CAMFImporter_NodeElement* ne;
|
|||
|
|
|||
|
// Read attributes for node <color>.
|
|||
|
MACRO_ATTRREAD_LOOPBEG;
|
|||
|
MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
|
|||
|
MACRO_ATTRREAD_LOOPEND;
|
|||
|
|
|||
|
// create new object.
|
|||
|
ne = new CAMFImporter_NodeElement_Material(mNodeElement_Cur);
|
|||
|
// and assign read data
|
|||
|
((CAMFImporter_NodeElement_Material*)ne)->ID = id;
|
|||
|
// Check for child nodes
|
|||
|
if(!mReader->isEmptyElement())
|
|||
|
{
|
|||
|
bool col_read = false;
|
|||
|
|
|||
|
ParseHelper_Node_Enter(ne);
|
|||
|
MACRO_NODECHECK_LOOPBEGIN("material");
|
|||
|
if(XML_CheckNode_NameEqual("color"))
|
|||
|
{
|
|||
|
// Check if data already defined.
|
|||
|
if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <material>.");
|
|||
|
// read data and set flag about it
|
|||
|
ParseNode_Color();
|
|||
|
col_read = true;
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
|
|||
|
MACRO_NODECHECK_LOOPEND("material");
|
|||
|
ParseHelper_Node_Exit();
|
|||
|
}// if(!mReader->isEmptyElement())
|
|||
|
else
|
|||
|
{
|
|||
|
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
|
|||
|
}// if(!mReader->isEmptyElement()) else
|
|||
|
|
|||
|
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
|
|||
|
}
|
|||
|
|
|||
|
// <texture
|
|||
|
// id="" - Assigns a unique texture id for the new texture.
|
|||
|
// width="" - Width (horizontal size, x) of the texture, in pixels.
|
|||
|
// height="" - Height (lateral size, y) of the texture, in pixels.
|
|||
|
// depth="" - Depth (vertical size, z) of the texture, in pixels.
|
|||
|
// type="" - Encoding of the data in the texture. Currently allowed values are "grayscale" only. In grayscale mode, each pixel is represented by one byte
|
|||
|
// 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
|
|||
|
// 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
|
|||
|
// transparency may require a fourth channel.
|
|||
|
// tiled="" - If true then texture repeated when UV-coordinates is greater than 1.
|
|||
|
// >
|
|||
|
// </triangle>
|
|||
|
// 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,
|
|||
|
// then layer by layer.
|
|||
|
// Multi elements - Yes.
|
|||
|
// Parent element - <amf>.
|
|||
|
void AMFImporter::ParseNode_Texture()
|
|||
|
{
|
|||
|
std::string id;
|
|||
|
uint32_t width = 0;
|
|||
|
uint32_t height = 0;
|
|||
|
uint32_t depth = 1;
|
|||
|
std::string type;
|
|||
|
bool tiled = false;
|
|||
|
std::string enc64_data;
|
|||
|
CAMFImporter_NodeElement* ne;
|
|||
|
|
|||
|
// Read attributes for node <color>.
|
|||
|
MACRO_ATTRREAD_LOOPBEG;
|
|||
|
MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
|
|||
|
MACRO_ATTRREAD_CHECK_RET("width", width, XML_ReadNode_GetAttrVal_AsU32);
|
|||
|
MACRO_ATTRREAD_CHECK_RET("height", height, XML_ReadNode_GetAttrVal_AsU32);
|
|||
|
MACRO_ATTRREAD_CHECK_RET("depth", depth, XML_ReadNode_GetAttrVal_AsU32);
|
|||
|
MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue);
|
|||
|
MACRO_ATTRREAD_CHECK_RET("tiled", tiled, XML_ReadNode_GetAttrVal_AsBool);
|
|||
|
MACRO_ATTRREAD_LOOPEND;
|
|||
|
|
|||
|
// create new texture object.
|
|||
|
ne = new CAMFImporter_NodeElement_Texture(mNodeElement_Cur);
|
|||
|
|
|||
|
CAMFImporter_NodeElement_Texture& als = *((CAMFImporter_NodeElement_Texture*)ne);// alias for convenience
|
|||
|
|
|||
|
// Check for child nodes
|
|||
|
if(!mReader->isEmptyElement()) XML_ReadNode_GetVal_AsString(enc64_data);
|
|||
|
|
|||
|
// check that all components was defined
|
|||
|
if(id.empty()) throw DeadlyImportError("ID for texture must be defined.");
|
|||
|
if(width < 1) Throw_IncorrectAttrValue("width");
|
|||
|
if(height < 1) Throw_IncorrectAttrValue("height");
|
|||
|
if(depth < 1) Throw_IncorrectAttrValue("depth");
|
|||
|
if(type != "grayscale") Throw_IncorrectAttrValue("type");
|
|||
|
if(enc64_data.empty()) throw DeadlyImportError("Texture data not defined.");
|
|||
|
// copy data
|
|||
|
als.ID = id;
|
|||
|
als.Width = width;
|
|||
|
als.Height = height;
|
|||
|
als.Depth = depth;
|
|||
|
als.Tiled = tiled;
|
|||
|
ParseHelper_Decode_Base64(enc64_data, als.Data);
|
|||
|
// check data size
|
|||
|
if((width * height * depth) != als.Data.size()) throw DeadlyImportError("Texture has incorrect data size.");
|
|||
|
|
|||
|
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
|
|||
|
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
|
|||
|
}
|
|||
|
|
|||
|
// <texmap
|
|||
|
// rtexid="" - Texture ID for red color component.
|
|||
|
// gtexid="" - Texture ID for green color component.
|
|||
|
// btexid="" - Texture ID for blue color component.
|
|||
|
// atexid="" - Texture ID for alpha color component. Optional.
|
|||
|
// >
|
|||
|
// </texmap>, old name: <map>
|
|||
|
// Specifies texture coordinates for triangle.
|
|||
|
// Multi elements - No.
|
|||
|
// Parent element - <triangle>.
|
|||
|
// Children elements:
|
|||
|
// <utex1>, <utex2>, <utex3>, <vtex1>, <vtex2>, <vtex3>. Old name: <u1>, <u2>, <u3>, <v1>, <v2>, <v3>.
|
|||
|
// Multi elements - No.
|
|||
|
// Texture coordinates for every vertex of triangle.
|
|||
|
void AMFImporter::ParseNode_TexMap(const bool pUseOldName)
|
|||
|
{
|
|||
|
std::string rtexid, gtexid, btexid, atexid;
|
|||
|
CAMFImporter_NodeElement* ne;
|
|||
|
|
|||
|
// Read attributes for node <color>.
|
|||
|
MACRO_ATTRREAD_LOOPBEG;
|
|||
|
MACRO_ATTRREAD_CHECK_RET("rtexid", rtexid, mReader->getAttributeValue);
|
|||
|
MACRO_ATTRREAD_CHECK_RET("gtexid", gtexid, mReader->getAttributeValue);
|
|||
|
MACRO_ATTRREAD_CHECK_RET("btexid", btexid, mReader->getAttributeValue);
|
|||
|
MACRO_ATTRREAD_CHECK_RET("atexid", atexid, mReader->getAttributeValue);
|
|||
|
MACRO_ATTRREAD_LOOPEND;
|
|||
|
|
|||
|
// create new texture coordinates object.
|
|||
|
ne = new CAMFImporter_NodeElement_TexMap(mNodeElement_Cur);
|
|||
|
|
|||
|
CAMFImporter_NodeElement_TexMap& als = *((CAMFImporter_NodeElement_TexMap*)ne);// alias for convenience
|
|||
|
// check data
|
|||
|
if(rtexid.empty() && gtexid.empty() && btexid.empty()) throw DeadlyImportError("ParseNode_TexMap. At least one texture ID must be defined.");
|
|||
|
// Check for children nodes
|
|||
|
XML_CheckNode_MustHaveChildren();
|
|||
|
// read children nodes
|
|||
|
bool read_flag[6] = { false, false, false, false, false, false };
|
|||
|
|
|||
|
ParseHelper_Node_Enter(ne);
|
|||
|
if(!pUseOldName)
|
|||
|
{
|
|||
|
MACRO_NODECHECK_LOOPBEGIN("texmap");
|
|||
|
MACRO_NODECHECK_READCOMP_F("utex1", read_flag[0], als.TextureCoordinate[0].x);
|
|||
|
MACRO_NODECHECK_READCOMP_F("utex2", read_flag[1], als.TextureCoordinate[1].x);
|
|||
|
MACRO_NODECHECK_READCOMP_F("utex3", read_flag[2], als.TextureCoordinate[2].x);
|
|||
|
MACRO_NODECHECK_READCOMP_F("vtex1", read_flag[3], als.TextureCoordinate[0].y);
|
|||
|
MACRO_NODECHECK_READCOMP_F("vtex2", read_flag[4], als.TextureCoordinate[1].y);
|
|||
|
MACRO_NODECHECK_READCOMP_F("vtex3", read_flag[5], als.TextureCoordinate[2].y);
|
|||
|
MACRO_NODECHECK_LOOPEND("texmap");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
MACRO_NODECHECK_LOOPBEGIN("map");
|
|||
|
MACRO_NODECHECK_READCOMP_F("u1", read_flag[0], als.TextureCoordinate[0].x);
|
|||
|
MACRO_NODECHECK_READCOMP_F("u2", read_flag[1], als.TextureCoordinate[1].x);
|
|||
|
MACRO_NODECHECK_READCOMP_F("u3", read_flag[2], als.TextureCoordinate[2].x);
|
|||
|
MACRO_NODECHECK_READCOMP_F("v1", read_flag[3], als.TextureCoordinate[0].y);
|
|||
|
MACRO_NODECHECK_READCOMP_F("v2", read_flag[4], als.TextureCoordinate[1].y);
|
|||
|
MACRO_NODECHECK_READCOMP_F("v3", read_flag[5], als.TextureCoordinate[2].y);
|
|||
|
MACRO_NODECHECK_LOOPEND("map");
|
|||
|
}// if(!pUseOldName) else
|
|||
|
|
|||
|
ParseHelper_Node_Exit();
|
|||
|
|
|||
|
// check that all components was defined
|
|||
|
if(!(read_flag[0] && read_flag[1] && read_flag[2] && read_flag[3] && read_flag[4] && read_flag[5]))
|
|||
|
throw DeadlyImportError("Not all texture coordinates are defined.");
|
|||
|
|
|||
|
// copy attributes data
|
|||
|
als.TextureID_R = rtexid;
|
|||
|
als.TextureID_G = gtexid;
|
|||
|
als.TextureID_B = btexid;
|
|||
|
als.TextureID_A = atexid;
|
|||
|
|
|||
|
mNodeElement_List.push_back(ne);// add to node element list because its a new object in graph.
|
|||
|
}
|
|||
|
|
|||
|
}// namespace Assimp
|
|||
|
|
|||
|
#endif // !ASSIMP_BUILD_NO_AMF_IMPORTER
|