Merge branch 'master' into doc/expand_description_about_embedded_textures
commit
53e4e653a8
|
@ -32,8 +32,8 @@ Please check our Wiki as well: https://github.com/assimp/assimp/wiki
|
||||||
|
|
||||||
#### Supported file formats ####
|
#### Supported file formats ####
|
||||||
|
|
||||||
A full list [is here](http://assimp.org/main_features_formats.html).
|
|
||||||
__Importers__:
|
__Importers__:
|
||||||
|
|
||||||
- 3D
|
- 3D
|
||||||
- 3DS
|
- 3DS
|
||||||
- 3MF
|
- 3MF
|
||||||
|
@ -109,6 +109,8 @@ __Exporters__:
|
||||||
- STEP
|
- STEP
|
||||||
- glTF 1.0 (partial)
|
- glTF 1.0 (partial)
|
||||||
- glTF 2.0 (partial)
|
- glTF 2.0 (partial)
|
||||||
|
- 3MF ( experimental )
|
||||||
|
- FBX ( experimental )
|
||||||
|
|
||||||
### Building ###
|
### Building ###
|
||||||
Take a look into the `INSTALL` file. Our build system is CMake, if you used CMake before there is a good chance you know what to do.
|
Take a look into the `INSTALL` file. Our build system is CMake, if you used CMake before there is a good chance you know what to do.
|
||||||
|
|
|
@ -72,7 +72,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial()
|
||||||
unsigned int idx( NotSet );
|
unsigned int idx( NotSet );
|
||||||
for (unsigned int i = 0; i < mScene->mMaterials.size();++i)
|
for (unsigned int i = 0; i < mScene->mMaterials.size();++i)
|
||||||
{
|
{
|
||||||
std::string s = mScene->mMaterials[i].mName;
|
std::string &s = mScene->mMaterials[i].mName;
|
||||||
for ( std::string::iterator it = s.begin(); it != s.end(); ++it ) {
|
for ( std::string::iterator it = s.begin(); it != s.end(); ++it ) {
|
||||||
*it = static_cast< char >( ::tolower( *it ) );
|
*it = static_cast< char >( ::tolower( *it ) );
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,10 +156,11 @@ size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string&
|
||||||
TextureConverted_Index = 0;
|
TextureConverted_Index = 0;
|
||||||
for(const SPP_Texture& tex_convd: mTexture_Converted)
|
for(const SPP_Texture& tex_convd: mTexture_Converted)
|
||||||
{
|
{
|
||||||
if(tex_convd.ID == TextureConverted_ID)
|
if ( tex_convd.ID == TextureConverted_ID ) {
|
||||||
return TextureConverted_Index;
|
return TextureConverted_Index;
|
||||||
else
|
} else {
|
||||||
TextureConverted_Index++;
|
++TextureConverted_Index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -267,7 +267,9 @@ void Parser::Parse()
|
||||||
// at the file extension (ASE, ASK, ASC)
|
// at the file extension (ASE, ASK, ASC)
|
||||||
// *************************************************************
|
// *************************************************************
|
||||||
|
|
||||||
if (fmt)iFileFormat = fmt;
|
if ( fmt ) {
|
||||||
|
iFileFormat = fmt;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// main scene information
|
// main scene information
|
||||||
|
@ -427,28 +429,25 @@ void Parser::ParseLV1SoftSkinBlock()
|
||||||
// Reserve enough storage
|
// Reserve enough storage
|
||||||
vert.mBoneWeights.reserve(numWeights);
|
vert.mBoneWeights.reserve(numWeights);
|
||||||
|
|
||||||
for (unsigned int w = 0; w < numWeights;++w)
|
std::string bone;
|
||||||
{
|
for (unsigned int w = 0; w < numWeights;++w) {
|
||||||
std::string bone;
|
bone.clear();
|
||||||
ParseString(bone,"*MESH_SOFTSKINVERTS.Bone");
|
ParseString(bone,"*MESH_SOFTSKINVERTS.Bone");
|
||||||
|
|
||||||
// Find the bone in the mesh's list
|
// Find the bone in the mesh's list
|
||||||
std::pair<int,ai_real> me;
|
std::pair<int,ai_real> me;
|
||||||
me.first = -1;
|
me.first = -1;
|
||||||
|
|
||||||
for (unsigned int n = 0; n < curMesh->mBones.size();++n)
|
for (unsigned int n = 0; n < curMesh->mBones.size();++n) {
|
||||||
{
|
if (curMesh->mBones[n].mName == bone) {
|
||||||
if (curMesh->mBones[n].mName == bone)
|
|
||||||
{
|
|
||||||
me.first = n;
|
me.first = n;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (-1 == me.first)
|
if (-1 == me.first) {
|
||||||
{
|
|
||||||
// We don't have this bone yet, so add it to the list
|
// We don't have this bone yet, so add it to the list
|
||||||
me.first = (int)curMesh->mBones.size();
|
me.first = static_cast<int>( curMesh->mBones.size() );
|
||||||
curMesh->mBones.push_back(ASE::Bone(bone));
|
curMesh->mBones.push_back( ASE::Bone( bone ) );
|
||||||
}
|
}
|
||||||
ParseLV4MeshFloat( me.second );
|
ParseLV4MeshFloat( me.second );
|
||||||
|
|
||||||
|
@ -745,6 +744,7 @@ void Parser::ParseLV3MapBlock(Texture& map)
|
||||||
// empty the texture won't be used later.
|
// empty the texture won't be used later.
|
||||||
// ***********************************************************
|
// ***********************************************************
|
||||||
bool parsePath = true;
|
bool parsePath = true;
|
||||||
|
std::string temp;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if ('*' == *filePtr)
|
if ('*' == *filePtr)
|
||||||
|
@ -753,7 +753,7 @@ void Parser::ParseLV3MapBlock(Texture& map)
|
||||||
// type of map
|
// type of map
|
||||||
if (TokenMatch(filePtr,"MAP_CLASS" ,9))
|
if (TokenMatch(filePtr,"MAP_CLASS" ,9))
|
||||||
{
|
{
|
||||||
std::string temp;
|
temp.clear();
|
||||||
if(!ParseString(temp,"*MAP_CLASS"))
|
if(!ParseString(temp,"*MAP_CLASS"))
|
||||||
SkipToNextToken();
|
SkipToNextToken();
|
||||||
if (temp != "Bitmap" && temp != "Normal Bump")
|
if (temp != "Bitmap" && temp != "Normal Bump")
|
||||||
|
|
|
@ -199,6 +199,7 @@ aiNode* BVHLoader::ReadNode()
|
||||||
Node& internNode = mNodes.back();
|
Node& internNode = mNodes.back();
|
||||||
|
|
||||||
// now read the node's contents
|
// now read the node's contents
|
||||||
|
std::string siteToken;
|
||||||
while( 1)
|
while( 1)
|
||||||
{
|
{
|
||||||
std::string token = GetNextToken();
|
std::string token = GetNextToken();
|
||||||
|
@ -218,7 +219,8 @@ aiNode* BVHLoader::ReadNode()
|
||||||
else if( token == "End")
|
else if( token == "End")
|
||||||
{
|
{
|
||||||
// The real symbol is "End Site". Second part comes in a separate token
|
// The real symbol is "End Site". Second part comes in a separate token
|
||||||
std::string siteToken = GetNextToken();
|
siteToken.clear();
|
||||||
|
siteToken = GetNextToken();
|
||||||
if( siteToken != "Site")
|
if( siteToken != "Site")
|
||||||
ThrowException( format() << "Expected \"End Site\" keyword, but found \"" << token << " " << siteToken << "\"." );
|
ThrowException( format() << "Expected \"End Site\" keyword, but found \"" << token << " " << siteToken << "\"." );
|
||||||
|
|
||||||
|
@ -262,21 +264,18 @@ aiNode* BVHLoader::ReadEndSite( const std::string& pParentName)
|
||||||
aiNode* node = new aiNode( "EndSite_" + pParentName);
|
aiNode* node = new aiNode( "EndSite_" + pParentName);
|
||||||
|
|
||||||
// now read the node's contents. Only possible entry is "OFFSET"
|
// now read the node's contents. Only possible entry is "OFFSET"
|
||||||
while( 1)
|
std::string token;
|
||||||
{
|
while( 1) {
|
||||||
std::string token = GetNextToken();
|
token.clear();
|
||||||
|
token = GetNextToken();
|
||||||
|
|
||||||
// end node's offset
|
// end node's offset
|
||||||
if( token == "OFFSET")
|
if( token == "OFFSET") {
|
||||||
{
|
|
||||||
ReadNodeOffset( node);
|
ReadNodeOffset( node);
|
||||||
}
|
} else if( token == "}") {
|
||||||
else if( token == "}")
|
|
||||||
{
|
|
||||||
// we're done with the end node
|
// we're done with the end node
|
||||||
break;
|
break;
|
||||||
} else
|
} else {
|
||||||
{
|
|
||||||
// everything else is a parse error
|
// everything else is a parse error
|
||||||
ThrowException( format() << "Unknown keyword \"" << token << "\"." );
|
ThrowException( format() << "Unknown keyword \"" << token << "\"." );
|
||||||
}
|
}
|
||||||
|
@ -296,8 +295,10 @@ void BVHLoader::ReadNodeOffset( aiNode* pNode)
|
||||||
offset.z = GetNextTokenAsFloat();
|
offset.z = GetNextTokenAsFloat();
|
||||||
|
|
||||||
// build a transformation matrix from it
|
// build a transformation matrix from it
|
||||||
pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x, 0.0f, 1.0f, 0.0f, offset.y,
|
pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x,
|
||||||
0.0f, 0.0f, 1.0f, offset.z, 0.0f, 0.0f, 0.0f, 1.0f);
|
0.0f, 1.0f, 0.0f, offset.y,
|
||||||
|
0.0f, 0.0f, 1.0f, offset.z,
|
||||||
|
0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -251,7 +251,8 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
|
||||||
/* static */ bool BaseImporter::CheckMagicToken(IOSystem* pIOHandler, const std::string& pFile,
|
/* static */ bool BaseImporter::CheckMagicToken(IOSystem* pIOHandler, const std::string& pFile,
|
||||||
const void* _magic, unsigned int num, unsigned int offset, unsigned int size)
|
const void* _magic, unsigned int num, unsigned int offset, unsigned int size)
|
||||||
{
|
{
|
||||||
ai_assert(size <= 16 && _magic);
|
ai_assert( size <= 16 );
|
||||||
|
ai_assert( _magic );
|
||||||
|
|
||||||
if (!pIOHandler) {
|
if (!pIOHandler) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1269,7 +1269,8 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
|
||||||
|
|
||||||
mOutput << startstr << "<animation id=\"" + idstrEscaped + "\" name=\"" + animation_name_escaped + "\">" << endstr;
|
mOutput << startstr << "<animation id=\"" + idstrEscaped + "\" name=\"" + animation_name_escaped + "\">" << endstr;
|
||||||
PushTag();
|
PushTag();
|
||||||
|
|
||||||
|
std::string node_idstr;
|
||||||
for (size_t a = 0; a < anim->mNumChannels; ++a) {
|
for (size_t a = 0; a < anim->mNumChannels; ++a) {
|
||||||
const aiNodeAnim * nodeAnim = anim->mChannels[a];
|
const aiNodeAnim * nodeAnim = anim->mChannels[a];
|
||||||
|
|
||||||
|
@ -1277,7 +1278,9 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
|
||||||
if ( nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys ) continue;
|
if ( nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys ) continue;
|
||||||
|
|
||||||
{
|
{
|
||||||
const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-input");
|
node_idstr.clear();
|
||||||
|
node_idstr += nodeAnim->mNodeName.data;
|
||||||
|
node_idstr += std::string( "_matrix-input" );
|
||||||
|
|
||||||
std::vector<ai_real> frames;
|
std::vector<ai_real> frames;
|
||||||
for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
|
for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
|
||||||
|
@ -1289,12 +1292,14 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-output");
|
node_idstr.clear();
|
||||||
|
|
||||||
|
node_idstr += nodeAnim->mNodeName.data;
|
||||||
|
node_idstr += std::string("_matrix-output");
|
||||||
|
|
||||||
std::vector<ai_real> keyframes;
|
std::vector<ai_real> keyframes;
|
||||||
keyframes.reserve(nodeAnim->mNumPositionKeys * 16);
|
keyframes.reserve(nodeAnim->mNumPositionKeys * 16);
|
||||||
for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
|
for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
|
||||||
|
|
||||||
aiVector3D Scaling = nodeAnim->mScalingKeys[i].mValue;
|
aiVector3D Scaling = nodeAnim->mScalingKeys[i].mValue;
|
||||||
aiMatrix4x4 ScalingM; // identity
|
aiMatrix4x4 ScalingM; // identity
|
||||||
ScalingM[0][0] = Scaling.x; ScalingM[1][1] = Scaling.y; ScalingM[2][2] = Scaling.z;
|
ScalingM[0][0] = Scaling.x; ScalingM[1][1] = Scaling.y; ScalingM[2][2] = Scaling.z;
|
||||||
|
@ -1361,7 +1366,6 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
|
||||||
PopTag();
|
PopTag();
|
||||||
mOutput << startstr << "</source>" << endstr;
|
mOutput << startstr << "</source>" << endstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t a = 0; a < anim->mNumChannels; ++a) {
|
for (size_t a = 0; a < anim->mNumChannels; ++a) {
|
||||||
|
|
|
@ -1121,6 +1121,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// now check all channels if they affect the current node
|
// now check all channels if they affect the current node
|
||||||
|
std::string targetID, subElement;
|
||||||
for( std::vector<Collada::AnimationChannel>::const_iterator cit = pSrcAnim->mChannels.begin();
|
for( std::vector<Collada::AnimationChannel>::const_iterator cit = pSrcAnim->mChannels.begin();
|
||||||
cit != pSrcAnim->mChannels.end(); ++cit)
|
cit != pSrcAnim->mChannels.end(); ++cit)
|
||||||
{
|
{
|
||||||
|
@ -1147,7 +1148,9 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
||||||
}
|
}
|
||||||
if( srcChannel.mTarget.find( '/', slashPos+1) != std::string::npos)
|
if( srcChannel.mTarget.find( '/', slashPos+1) != std::string::npos)
|
||||||
continue;
|
continue;
|
||||||
std::string targetID = srcChannel.mTarget.substr( 0, slashPos);
|
|
||||||
|
targetID.clear();
|
||||||
|
targetID = srcChannel.mTarget.substr( 0, slashPos);
|
||||||
if( targetID != srcNode->mID)
|
if( targetID != srcNode->mID)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -1160,7 +1163,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
||||||
|
|
||||||
entry.mTransformId = srcChannel.mTarget.substr( slashPos+1, dotPos - slashPos - 1);
|
entry.mTransformId = srcChannel.mTarget.substr( slashPos+1, dotPos - slashPos - 1);
|
||||||
|
|
||||||
std::string subElement = srcChannel.mTarget.substr( dotPos+1);
|
subElement.clear();
|
||||||
|
subElement = srcChannel.mTarget.substr( dotPos+1);
|
||||||
if( subElement == "ANGLE")
|
if( subElement == "ANGLE")
|
||||||
entry.mSubElement = 3; // last number in an Axis-Angle-Transform is the angle
|
entry.mSubElement = 3; // last number in an Axis-Angle-Transform is the angle
|
||||||
else if( subElement == "X")
|
else if( subElement == "X")
|
||||||
|
@ -1181,7 +1185,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
||||||
if (bracketPos != std::string::npos)
|
if (bracketPos != std::string::npos)
|
||||||
{
|
{
|
||||||
entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1, bracketPos - slashPos - 1);
|
entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1, bracketPos - slashPos - 1);
|
||||||
std::string subElement = srcChannel.mTarget.substr(bracketPos);
|
subElement.clear();
|
||||||
|
subElement = srcChannel.mTarget.substr(bracketPos);
|
||||||
|
|
||||||
if (subElement == "(0)(0)")
|
if (subElement == "(0)(0)")
|
||||||
entry.mSubElement = 0;
|
entry.mSubElement = 0;
|
||||||
|
@ -1215,7 +1220,6 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
||||||
entry.mSubElement = 14;
|
entry.mSubElement = 14;
|
||||||
else if (subElement == "(3)(3)")
|
else if (subElement == "(3)(3)")
|
||||||
entry.mSubElement = 15;
|
entry.mSubElement = 15;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine which transform step is affected by this channel
|
// determine which transform step is affected by this channel
|
||||||
|
|
|
@ -117,6 +117,7 @@ bool D3MFExporter::exportArchive( const char *file ) {
|
||||||
if ( nullptr == m_zipArchive ) {
|
if ( nullptr == m_zipArchive ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ok |= exportContentTypes();
|
ok |= exportContentTypes();
|
||||||
ok |= export3DModel();
|
ok |= export3DModel();
|
||||||
ok |= exportRelations();
|
ok |= exportRelations();
|
||||||
|
@ -181,6 +182,8 @@ bool D3MFExporter::export3DModel() {
|
||||||
mModelOutput << "<" << XmlTag::resources << ">";
|
mModelOutput << "<" << XmlTag::resources << ">";
|
||||||
mModelOutput << std::endl;
|
mModelOutput << std::endl;
|
||||||
|
|
||||||
|
writeMetaData();
|
||||||
|
|
||||||
writeBaseMaterials();
|
writeBaseMaterials();
|
||||||
|
|
||||||
writeObjects();
|
writeObjects();
|
||||||
|
@ -209,22 +212,45 @@ void D3MFExporter::writeHeader() {
|
||||||
mModelOutput << std::endl;
|
mModelOutput << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void D3MFExporter::writeMetaData() {
|
||||||
|
if ( nullptr == mScene->mMetaData ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned int numMetaEntries( mScene->mMetaData->mNumProperties );
|
||||||
|
if ( 0 == numMetaEntries ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const aiString *key;
|
||||||
|
const aiMetadataEntry *entry(nullptr);
|
||||||
|
for ( size_t i = 0; i < numMetaEntries; ++i ) {
|
||||||
|
mScene->mMetaData->Get( i, key, entry );
|
||||||
|
std::string k( key->C_Str() );
|
||||||
|
aiString value;
|
||||||
|
mScene->mMetaData->Get( k, value );
|
||||||
|
mModelOutput << "<" << XmlTag::meta << " " << XmlTag::meta_name << "=\"" << key->C_Str() << "\">";
|
||||||
|
mModelOutput << value.C_Str();
|
||||||
|
mModelOutput << "</" << XmlTag::meta << ">" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void D3MFExporter::writeBaseMaterials() {
|
void D3MFExporter::writeBaseMaterials() {
|
||||||
mModelOutput << "<basematerials id=\"1\">\n";
|
mModelOutput << "<basematerials id=\"1\">\n";
|
||||||
|
std::string strName, hexDiffuseColor , tmp;
|
||||||
for ( size_t i = 0; i < mScene->mNumMaterials; ++i ) {
|
for ( size_t i = 0; i < mScene->mNumMaterials; ++i ) {
|
||||||
aiMaterial *mat = mScene->mMaterials[ i ];
|
aiMaterial *mat = mScene->mMaterials[ i ];
|
||||||
std::string strName;
|
|
||||||
aiString name;
|
aiString name;
|
||||||
if ( mat->Get( AI_MATKEY_NAME, name ) != aiReturn_SUCCESS ) {
|
if ( mat->Get( AI_MATKEY_NAME, name ) != aiReturn_SUCCESS ) {
|
||||||
strName = "basemat_" + to_string( i );
|
strName = "basemat_" + to_string( i );
|
||||||
} else {
|
} else {
|
||||||
strName = name.C_Str();
|
strName = name.C_Str();
|
||||||
}
|
}
|
||||||
std::string hexDiffuseColor;
|
|
||||||
aiColor4D color;
|
aiColor4D color;
|
||||||
if ( mat->Get( AI_MATKEY_COLOR_DIFFUSE, color ) == aiReturn_SUCCESS ) {
|
if ( mat->Get( AI_MATKEY_COLOR_DIFFUSE, color ) == aiReturn_SUCCESS ) {
|
||||||
|
hexDiffuseColor.clear();
|
||||||
|
tmp.clear();
|
||||||
hexDiffuseColor = "#";
|
hexDiffuseColor = "#";
|
||||||
std::string tmp;
|
|
||||||
|
|
||||||
tmp = DecimalToHexa( color.r );
|
tmp = DecimalToHexa( color.r );
|
||||||
hexDiffuseColor += tmp;
|
hexDiffuseColor += tmp;
|
||||||
|
|
|
@ -76,6 +76,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void writeHeader();
|
void writeHeader();
|
||||||
|
void writeMetaData();
|
||||||
void writeBaseMaterials();
|
void writeBaseMaterials();
|
||||||
void writeObjects();
|
void writeObjects();
|
||||||
void writeMesh( aiMesh *mesh );
|
void writeMesh( aiMesh *mesh );
|
||||||
|
|
|
@ -94,14 +94,17 @@ public:
|
||||||
scene->mRootNode = new aiNode();
|
scene->mRootNode = new aiNode();
|
||||||
std::vector<aiNode*> children;
|
std::vector<aiNode*> children;
|
||||||
|
|
||||||
|
std::string nodeName;
|
||||||
while(ReadToEndElement(D3MF::XmlTag::model)) {
|
while(ReadToEndElement(D3MF::XmlTag::model)) {
|
||||||
const std::string nodeName( xmlReader->getNodeName() );
|
nodeName = xmlReader->getNodeName();
|
||||||
if( nodeName == D3MF::XmlTag::object) {
|
if( nodeName == D3MF::XmlTag::object) {
|
||||||
children.push_back(ReadObject(scene));
|
children.push_back(ReadObject(scene));
|
||||||
} else if( nodeName == D3MF::XmlTag::build) {
|
} else if( nodeName == D3MF::XmlTag::build) {
|
||||||
//
|
//
|
||||||
} else if ( nodeName == D3MF::XmlTag::basematerials ) {
|
} else if ( nodeName == D3MF::XmlTag::basematerials ) {
|
||||||
ReadBaseMaterials();
|
ReadBaseMaterials();
|
||||||
|
} else if ( nodeName == D3MF::XmlTag::meta ) {
|
||||||
|
ReadMetadata();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,19 +112,31 @@ public:
|
||||||
scene->mRootNode->mName.Set( "3MF" );
|
scene->mRootNode->mName.Set( "3MF" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// import the metadata
|
||||||
|
if ( !mMetaData.empty() ) {
|
||||||
|
const size_t numMeta( mMetaData.size() );
|
||||||
|
scene->mMetaData = aiMetadata::Alloc( numMeta );
|
||||||
|
for ( size_t i = 0; i < numMeta; ++i ) {
|
||||||
|
aiString val( mMetaData[ i ].value );
|
||||||
|
scene->mMetaData->Set( i, mMetaData[ i ].name, val );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// import the meshes
|
||||||
scene->mNumMeshes = static_cast<unsigned int>( mMeshes.size());
|
scene->mNumMeshes = static_cast<unsigned int>( mMeshes.size());
|
||||||
scene->mMeshes = new aiMesh*[scene->mNumMeshes]();
|
scene->mMeshes = new aiMesh*[scene->mNumMeshes]();
|
||||||
|
|
||||||
std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes);
|
std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes);
|
||||||
|
|
||||||
|
// import the materials
|
||||||
scene->mNumMaterials = static_cast<unsigned int>( mMatArray.size() );
|
scene->mNumMaterials = static_cast<unsigned int>( mMatArray.size() );
|
||||||
if ( 0 != scene->mNumMaterials ) {
|
if ( 0 != scene->mNumMaterials ) {
|
||||||
scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ];
|
scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ];
|
||||||
std::copy( mMatArray.begin(), mMatArray.end(), scene->mMaterials );
|
std::copy( mMatArray.begin(), mMatArray.end(), scene->mMaterials );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create the scenegraph
|
||||||
scene->mRootNode->mNumChildren = static_cast<unsigned int>(children.size());
|
scene->mRootNode->mNumChildren = static_cast<unsigned int>(children.size());
|
||||||
scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren]();
|
scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren]();
|
||||||
|
|
||||||
std::copy(children.begin(), children.end(), scene->mRootNode->mChildren);
|
std::copy(children.begin(), children.end(), scene->mRootNode->mChildren);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,6 +195,21 @@ private:
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ReadMetadata() {
|
||||||
|
const std::string name = xmlReader->getAttributeValue( D3MF::XmlTag::meta_name.c_str() );
|
||||||
|
xmlReader->read();
|
||||||
|
const std::string value = xmlReader->getNodeData();
|
||||||
|
|
||||||
|
if ( name.empty() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaEntry entry;
|
||||||
|
entry.name = name;
|
||||||
|
entry.value = value;
|
||||||
|
mMetaData.push_back( entry );
|
||||||
|
}
|
||||||
|
|
||||||
void ImportVertices(aiMesh* mesh) {
|
void ImportVertices(aiMesh* mesh) {
|
||||||
std::vector<aiVector3D> vertices;
|
std::vector<aiVector3D> vertices;
|
||||||
while(ReadToEndElement(D3MF::XmlTag::vertices)) {
|
while(ReadToEndElement(D3MF::XmlTag::vertices)) {
|
||||||
|
@ -253,7 +283,7 @@ private:
|
||||||
MatIdArray = it->second;
|
MatIdArray = it->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MatIdArray.push_back( newMatIdx );
|
MatIdArray.push_back( static_cast<unsigned int>( newMatIdx ) );
|
||||||
mMatId2MatArray[ mActiveMatGroup ] = MatIdArray;
|
mMatId2MatArray[ mActiveMatGroup ] = MatIdArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,8 +401,12 @@ private:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct MetaEntry {
|
||||||
|
std::string name;
|
||||||
|
std::string value;
|
||||||
|
};
|
||||||
|
std::vector<MetaEntry> mMetaData;
|
||||||
std::vector<aiMesh*> mMeshes;
|
std::vector<aiMesh*> mMeshes;
|
||||||
MatArray mMatArray;
|
MatArray mMatArray;
|
||||||
unsigned int mActiveMatGroup;
|
unsigned int mActiveMatGroup;
|
||||||
|
|
|
@ -288,8 +288,8 @@ bool D3MFZipArchive::Exists(const char* pFile) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string rFile(pFile);
|
std::string filename(pFile);
|
||||||
std::map<std::string, ZipFile*>::const_iterator it = m_ArchiveMap.find(rFile);
|
std::map<std::string, ZipFile*>::const_iterator it = m_ArchiveMap.find(filename);
|
||||||
bool exist( false );
|
bool exist( false );
|
||||||
if(it != m_ArchiveMap.end()) {
|
if(it != m_ArchiveMap.end()) {
|
||||||
exist = true;
|
exist = true;
|
||||||
|
|
|
@ -169,7 +169,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
LineSplitter splitter;
|
LineSplitter splitter;
|
||||||
int groupcode;
|
int groupcode;
|
||||||
std::string value;
|
std::string value;
|
||||||
|
|
|
@ -76,7 +76,7 @@ bool DefaultIOSystem::Exists( const char* pFile) const
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
wchar_t fileName16[PATHLIMIT];
|
wchar_t fileName16[PATHLIMIT];
|
||||||
|
|
||||||
bool isUnicode = IsTextUnicode(pFile, strlen(pFile), NULL);
|
bool isUnicode = IsTextUnicode(pFile, static_cast<int>(strlen(pFile)), NULL);
|
||||||
if (isUnicode) {
|
if (isUnicode) {
|
||||||
|
|
||||||
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT);
|
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT);
|
||||||
|
@ -110,7 +110,7 @@ IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode)
|
||||||
FILE* file;
|
FILE* file;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
wchar_t fileName16[PATHLIMIT];
|
wchar_t fileName16[PATHLIMIT];
|
||||||
bool isUnicode = IsTextUnicode(strFile, strlen(strFile), NULL );
|
bool isUnicode = IsTextUnicode(strFile, static_cast<int>(strlen(strFile)), NULL );
|
||||||
if (isUnicode) {
|
if (isUnicode) {
|
||||||
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT);
|
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT);
|
||||||
std::string mode8(strMode);
|
std::string mode8(strMode);
|
||||||
|
@ -158,7 +158,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
|
||||||
{
|
{
|
||||||
ai_assert(in && _out);
|
ai_assert(in && _out);
|
||||||
#if defined( _MSC_VER ) || defined( __MINGW32__ )
|
#if defined( _MSC_VER ) || defined( __MINGW32__ )
|
||||||
bool isUnicode = IsTextUnicode(in, strlen(in), NULL);
|
bool isUnicode = IsTextUnicode(in, static_cast<int>(strlen(in)), NULL);
|
||||||
if (isUnicode) {
|
if (isUnicode) {
|
||||||
wchar_t out16[PATHLIMIT];
|
wchar_t out16[PATHLIMIT];
|
||||||
wchar_t in16[PATHLIMIT];
|
wchar_t in16[PATHLIMIT];
|
||||||
|
|
|
@ -45,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
* @brief Implementation of DefaultLogger (and Logger)
|
* @brief Implementation of DefaultLogger (and Logger)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// Default log streams
|
// Default log streams
|
||||||
#include "Win32DebugLogStream.h"
|
#include "Win32DebugLogStream.h"
|
||||||
#include "StdOStreamLogStream.h"
|
#include "StdOStreamLogStream.h"
|
||||||
|
@ -62,8 +61,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
||||||
# include <thread>
|
# include <thread>
|
||||||
# include <mutex>
|
# include <mutex>
|
||||||
|
std::mutex loggerMutex;
|
||||||
std::mutex loggerMutex;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
@ -76,22 +74,19 @@ static const unsigned int SeverityAll = Logger::Info | Logger::Err | Logger::War
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
// Represents a log-stream + its error severity
|
// Represents a log-stream + its error severity
|
||||||
struct LogStreamInfo
|
struct LogStreamInfo {
|
||||||
{
|
unsigned int m_uiErrorSeverity;
|
||||||
unsigned int m_uiErrorSeverity;
|
LogStream *m_pStream;
|
||||||
LogStream *m_pStream;
|
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) :
|
LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) :
|
||||||
m_uiErrorSeverity( uiErrorSev ),
|
m_uiErrorSeverity( uiErrorSev ),
|
||||||
m_pStream( pStream )
|
m_pStream( pStream ) {
|
||||||
{
|
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
~LogStreamInfo()
|
~LogStreamInfo() {
|
||||||
{
|
|
||||||
delete m_pStream;
|
delete m_pStream;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -109,7 +104,7 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams,
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
return new Win32DebugLogStream();
|
return new Win32DebugLogStream();
|
||||||
#else
|
#else
|
||||||
return NULL;
|
return nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Platform-independent default streams
|
// Platform-independent default streams
|
||||||
|
@ -118,7 +113,7 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams,
|
||||||
case aiDefaultLogStream_STDOUT:
|
case aiDefaultLogStream_STDOUT:
|
||||||
return new StdOStreamLogStream(std::cout);
|
return new StdOStreamLogStream(std::cout);
|
||||||
case aiDefaultLogStream_FILE:
|
case aiDefaultLogStream_FILE:
|
||||||
return (name && *name ? new FileLogStream(name,io) : NULL);
|
return (name && *name ? new FileLogStream(name,io) : nullptr );
|
||||||
default:
|
default:
|
||||||
// We don't know this default log stream, so raise an assertion
|
// We don't know this default log stream, so raise an assertion
|
||||||
ai_assert(false);
|
ai_assert(false);
|
||||||
|
@ -134,34 +129,38 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams,
|
||||||
Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/,
|
Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/,
|
||||||
LogSeverity severity /*= NORMAL*/,
|
LogSeverity severity /*= NORMAL*/,
|
||||||
unsigned int defStreams /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/,
|
unsigned int defStreams /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/,
|
||||||
IOSystem* io /*= NULL*/)
|
IOSystem* io /*= NULL*/) {
|
||||||
{
|
|
||||||
// enter the mutex here to avoid concurrency problems
|
// enter the mutex here to avoid concurrency problems
|
||||||
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
||||||
std::lock_guard<std::mutex> lock(loggerMutex);
|
std::lock_guard<std::mutex> lock(loggerMutex);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (m_pLogger && !isNullLogger() )
|
if ( m_pLogger && !isNullLogger() ) {
|
||||||
delete m_pLogger;
|
delete m_pLogger;
|
||||||
|
}
|
||||||
|
|
||||||
m_pLogger = new DefaultLogger( severity );
|
m_pLogger = new DefaultLogger( severity );
|
||||||
|
|
||||||
// Attach default log streams
|
// Attach default log streams
|
||||||
// Stream the log to the MSVC debugger?
|
// Stream the log to the MSVC debugger?
|
||||||
if (defStreams & aiDefaultLogStream_DEBUGGER)
|
if ( defStreams & aiDefaultLogStream_DEBUGGER ) {
|
||||||
m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_DEBUGGER));
|
m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_DEBUGGER ) );
|
||||||
|
}
|
||||||
|
|
||||||
// Stream the log to COUT?
|
// Stream the log to COUT?
|
||||||
if (defStreams & aiDefaultLogStream_STDOUT)
|
if ( defStreams & aiDefaultLogStream_STDOUT ) {
|
||||||
m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDOUT));
|
m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDOUT ) );
|
||||||
|
}
|
||||||
|
|
||||||
// Stream the log to CERR?
|
// Stream the log to CERR?
|
||||||
if (defStreams & aiDefaultLogStream_STDERR)
|
if ( defStreams & aiDefaultLogStream_STDERR ) {
|
||||||
m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDERR));
|
m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDERR ) );
|
||||||
|
}
|
||||||
|
|
||||||
// Stream the log to a file
|
// Stream the log to a file
|
||||||
if (defStreams & aiDefaultLogStream_FILE && name && *name)
|
if ( defStreams & aiDefaultLogStream_FILE && name && *name ) {
|
||||||
m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_FILE,name,io));
|
m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_FILE, name, io ) );
|
||||||
|
}
|
||||||
|
|
||||||
return m_pLogger;
|
return m_pLogger;
|
||||||
}
|
}
|
||||||
|
@ -200,7 +199,6 @@ void Logger::warn(const char* message) {
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
void Logger::error(const char* message) {
|
void Logger::error(const char* message) {
|
||||||
|
|
||||||
// SECURITY FIX: see above
|
// SECURITY FIX: see above
|
||||||
if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
|
if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
|
||||||
return;
|
return;
|
||||||
|
@ -209,23 +207,24 @@ void Logger::error(const char* message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
void DefaultLogger::set( Logger *logger )
|
void DefaultLogger::set( Logger *logger ) {
|
||||||
{
|
|
||||||
// enter the mutex here to avoid concurrency problems
|
// enter the mutex here to avoid concurrency problems
|
||||||
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
||||||
std::lock_guard<std::mutex> lock(loggerMutex);
|
std::lock_guard<std::mutex> lock(loggerMutex);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!logger)logger = &s_pNullLogger;
|
if ( nullptr == logger ) {
|
||||||
if (m_pLogger && !isNullLogger() )
|
logger = &s_pNullLogger;
|
||||||
|
}
|
||||||
|
if ( nullptr != m_pLogger && !isNullLogger() ) {
|
||||||
delete m_pLogger;
|
delete m_pLogger;
|
||||||
|
}
|
||||||
|
|
||||||
DefaultLogger::m_pLogger = logger;
|
DefaultLogger::m_pLogger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
bool DefaultLogger::isNullLogger()
|
bool DefaultLogger::isNullLogger() {
|
||||||
{
|
|
||||||
return m_pLogger == &s_pNullLogger;
|
return m_pLogger == &s_pNullLogger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,8 +235,7 @@ Logger *DefaultLogger::get() {
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
// Kills the only instance
|
// Kills the only instance
|
||||||
void DefaultLogger::kill()
|
void DefaultLogger::kill() {
|
||||||
{
|
|
||||||
// enter the mutex here to avoid concurrency problems
|
// enter the mutex here to avoid concurrency problems
|
||||||
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
||||||
std::lock_guard<std::mutex> lock(loggerMutex);
|
std::lock_guard<std::mutex> lock(loggerMutex);
|
||||||
|
@ -252,10 +250,10 @@ void DefaultLogger::kill()
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
// Debug message
|
// Debug message
|
||||||
void DefaultLogger::OnDebug( const char* message )
|
void DefaultLogger::OnDebug( const char* message ) {
|
||||||
{
|
if ( m_Severity == Logger::NORMAL ) {
|
||||||
if ( m_Severity == Logger::NORMAL )
|
return;
|
||||||
return;
|
}
|
||||||
|
|
||||||
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
||||||
char msg[Size];
|
char msg[Size];
|
||||||
|
@ -266,8 +264,7 @@ void DefaultLogger::OnDebug( const char* message )
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
// Logs an info
|
// Logs an info
|
||||||
void DefaultLogger::OnInfo( const char* message )
|
void DefaultLogger::OnInfo( const char* message ){
|
||||||
{
|
|
||||||
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
||||||
char msg[Size];
|
char msg[Size];
|
||||||
ai_snprintf(msg, Size, "Info, T%u: %s", GetThreadID(), message );
|
ai_snprintf(msg, Size, "Info, T%u: %s", GetThreadID(), message );
|
||||||
|
@ -277,8 +274,7 @@ void DefaultLogger::OnInfo( const char* message )
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
// Logs a warning
|
// Logs a warning
|
||||||
void DefaultLogger::OnWarn( const char* message )
|
void DefaultLogger::OnWarn( const char* message ) {
|
||||||
{
|
|
||||||
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
||||||
char msg[Size];
|
char msg[Size];
|
||||||
ai_snprintf(msg, Size, "Warn, T%u: %s", GetThreadID(), message );
|
ai_snprintf(msg, Size, "Warn, T%u: %s", GetThreadID(), message );
|
||||||
|
@ -288,8 +284,7 @@ void DefaultLogger::OnWarn( const char* message )
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
// Logs an error
|
// Logs an error
|
||||||
void DefaultLogger::OnError( const char* message )
|
void DefaultLogger::OnError( const char* message ) {
|
||||||
{
|
|
||||||
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
||||||
char msg[ Size ];
|
char msg[ Size ];
|
||||||
ai_snprintf(msg, Size, "Error, T%u: %s", GetThreadID(), message );
|
ai_snprintf(msg, Size, "Error, T%u: %s", GetThreadID(), message );
|
||||||
|
@ -299,10 +294,10 @@ void DefaultLogger::OnError( const char* message )
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
// Will attach a new stream
|
// Will attach a new stream
|
||||||
bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity )
|
bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) {
|
||||||
{
|
if ( nullptr == pStream ) {
|
||||||
if (!pStream)
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (0 == severity) {
|
if (0 == severity) {
|
||||||
severity = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging;
|
severity = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging;
|
||||||
|
@ -312,8 +307,7 @@ bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity )
|
||||||
it != m_StreamArray.end();
|
it != m_StreamArray.end();
|
||||||
++it )
|
++it )
|
||||||
{
|
{
|
||||||
if ( (*it)->m_pStream == pStream )
|
if ( (*it)->m_pStream == pStream ) {
|
||||||
{
|
|
||||||
(*it)->m_uiErrorSeverity |= severity;
|
(*it)->m_uiErrorSeverity |= severity;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -326,34 +320,31 @@ bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity )
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
// Detach a stream
|
// Detach a stream
|
||||||
bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity )
|
bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) {
|
||||||
{
|
if ( nullptr == pStream ) {
|
||||||
if (!pStream)
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (0 == severity) {
|
if (0 == severity) {
|
||||||
severity = SeverityAll;
|
severity = SeverityAll;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( StreamIt it = m_StreamArray.begin();
|
bool res( false );
|
||||||
it != m_StreamArray.end();
|
for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
|
||||||
++it )
|
if ( (*it)->m_pStream == pStream ) {
|
||||||
{
|
|
||||||
if ( (*it)->m_pStream == pStream )
|
|
||||||
{
|
|
||||||
(*it)->m_uiErrorSeverity &= ~severity;
|
(*it)->m_uiErrorSeverity &= ~severity;
|
||||||
if ( (*it)->m_uiErrorSeverity == 0 )
|
if ( (*it)->m_uiErrorSeverity == 0 ) {
|
||||||
{
|
|
||||||
// don't delete the underlying stream 'cause the caller gains ownership again
|
// don't delete the underlying stream 'cause the caller gains ownership again
|
||||||
(**it).m_pStream = NULL;
|
(**it).m_pStream = nullptr;
|
||||||
delete *it;
|
delete *it;
|
||||||
m_StreamArray.erase( it );
|
m_StreamArray.erase( it );
|
||||||
|
res = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
|
@ -361,15 +352,13 @@ bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity )
|
||||||
DefaultLogger::DefaultLogger(LogSeverity severity)
|
DefaultLogger::DefaultLogger(LogSeverity severity)
|
||||||
: Logger ( severity )
|
: Logger ( severity )
|
||||||
, noRepeatMsg (false)
|
, noRepeatMsg (false)
|
||||||
, lastLen( 0 )
|
, lastLen( 0 ) {
|
||||||
{
|
|
||||||
lastMsg[0] = '\0';
|
lastMsg[0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
// Destructor
|
// Destructor
|
||||||
DefaultLogger::~DefaultLogger()
|
DefaultLogger::~DefaultLogger() {
|
||||||
{
|
|
||||||
for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
|
for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
|
||||||
// also frees the underlying stream, we are its owner.
|
// also frees the underlying stream, we are its owner.
|
||||||
delete *it;
|
delete *it;
|
||||||
|
@ -378,9 +367,8 @@ DefaultLogger::~DefaultLogger()
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
// Writes message to stream
|
// Writes message to stream
|
||||||
void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev )
|
void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev ) {
|
||||||
{
|
ai_assert(nullptr != message);
|
||||||
ai_assert(NULL != message);
|
|
||||||
|
|
||||||
// Check whether this is a repeated message
|
// Check whether this is a repeated message
|
||||||
if (! ::strncmp( message,lastMsg, lastLen-1))
|
if (! ::strncmp( message,lastMsg, lastLen-1))
|
||||||
|
|
|
@ -99,22 +99,22 @@ void EmbedTexturesProcess::Execute(aiScene* pScene) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const {
|
bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const {
|
||||||
uint32_t imageSize = 0;
|
std::streampos imageSize = 0;
|
||||||
std::string imagePath = path;
|
std::string imagePath = path;
|
||||||
|
|
||||||
// Test path directly
|
// Test path directly
|
||||||
std::ifstream file(imagePath, std::ios::binary | std::ios::ate);
|
std::ifstream file(imagePath, std::ios::binary | std::ios::ate);
|
||||||
if ((imageSize = file.tellg()) == -1u) {
|
if ((imageSize = file.tellg()) == std::streampos(-1)) {
|
||||||
DefaultLogger::get()->warn("EmbedTexturesProcess: Cannot find image: " + imagePath + ". Will try to find it in root folder.");
|
DefaultLogger::get()->warn("EmbedTexturesProcess: Cannot find image: " + imagePath + ". Will try to find it in root folder.");
|
||||||
|
|
||||||
// Test path in root path
|
// Test path in root path
|
||||||
imagePath = mRootPath + path;
|
imagePath = mRootPath + path;
|
||||||
file.open(imagePath, std::ios::binary | std::ios::ate);
|
file.open(imagePath, std::ios::binary | std::ios::ate);
|
||||||
if ((imageSize = file.tellg()) == -1u) {
|
if ((imageSize = file.tellg()) == std::streampos(-1)) {
|
||||||
// Test path basename in root path
|
// Test path basename in root path
|
||||||
imagePath = mRootPath + path.substr(path.find_last_of("\\/") + 1u);
|
imagePath = mRootPath + path.substr(path.find_last_of("\\/") + 1u);
|
||||||
file.open(imagePath, std::ios::binary | std::ios::ate);
|
file.open(imagePath, std::ios::binary | std::ios::ate);
|
||||||
if ((imageSize = file.tellg()) == -1u) {
|
if ((imageSize = file.tellg()) == std::streampos(-1)) {
|
||||||
DefaultLogger::get()->error("EmbedTexturesProcess: Unable to embed texture: " + path + ".");
|
DefaultLogger::get()->error("EmbedTexturesProcess: Unable to embed texture: " + path + ".");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const {
|
||||||
// Add the new texture
|
// Add the new texture
|
||||||
auto pTexture = new aiTexture();
|
auto pTexture = new aiTexture();
|
||||||
pTexture->mHeight = 0; // Means that this is still compressed
|
pTexture->mHeight = 0; // Means that this is still compressed
|
||||||
pTexture->mWidth = imageSize;
|
pTexture->mWidth = static_cast<uint32_t>(imageSize);
|
||||||
pTexture->pcData = imageContent;
|
pTexture->pcData = imageContent;
|
||||||
|
|
||||||
auto extension = path.substr(path.find_last_of('.') + 1u);
|
auto extension = path.substr(path.find_last_of('.') + 1u);
|
||||||
|
|
|
@ -308,7 +308,8 @@ bool IsVerboseFormat(const aiScene* pScene) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing, const ExportProperties* pProperties) {
|
aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath,
|
||||||
|
unsigned int pPreprocessing, const ExportProperties* pProperties) {
|
||||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||||
|
|
||||||
// when they create scenes from scratch, users will likely create them not in verbose
|
// when they create scenes from scratch, users will likely create them not in verbose
|
||||||
|
|
|
@ -704,7 +704,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector
|
||||||
aiMatrix4x4::Scaling( GeometricScaling, chain[ TransformationComp_GeometricScaling ] );
|
aiMatrix4x4::Scaling( GeometricScaling, chain[ TransformationComp_GeometricScaling ] );
|
||||||
aiVector3D GeometricScalingInverse = GeometricScaling;
|
aiVector3D GeometricScalingInverse = GeometricScaling;
|
||||||
bool canscale = true;
|
bool canscale = true;
|
||||||
for (size_t i = 0; i < 3; ++i) {
|
for (unsigned int i = 0; i < 3; ++i) {
|
||||||
if ( std::fabs( GeometricScalingInverse[i] ) > zero_epsilon ) {
|
if ( std::fabs( GeometricScalingInverse[i] ) > zero_epsilon ) {
|
||||||
GeometricScalingInverse[i] = 1.0f / GeometricScaling[i];
|
GeometricScalingInverse[i] = 1.0f / GeometricScaling[i];
|
||||||
} else {
|
} else {
|
||||||
|
@ -1642,9 +1642,8 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap&
|
||||||
}
|
}
|
||||||
|
|
||||||
void Converter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextureMap& layeredTextures,
|
void Converter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextureMap& layeredTextures,
|
||||||
const std::string& propName,
|
const std::string& propName,
|
||||||
aiTextureType target, const MeshGeometry* const mesh )
|
aiTextureType target, const MeshGeometry* const mesh ) {
|
||||||
{
|
|
||||||
LayeredTextureMap::const_iterator it = layeredTextures.find( propName );
|
LayeredTextureMap::const_iterator it = layeredTextures.find( propName );
|
||||||
if ( it == layeredTextures.end() ) {
|
if ( it == layeredTextures.end() ) {
|
||||||
return;
|
return;
|
||||||
|
@ -1888,11 +1887,11 @@ void Converter::SetShadingPropertiesCommon( aiMaterial* out_mat, const PropertyT
|
||||||
|
|
||||||
// TransparentColor / TransparencyFactor... gee thanks FBX :rolleyes:
|
// TransparentColor / TransparencyFactor... gee thanks FBX :rolleyes:
|
||||||
const aiColor3D& Transparent = GetColorPropertyFactored( props, "TransparentColor", "TransparencyFactor", ok );
|
const aiColor3D& Transparent = GetColorPropertyFactored( props, "TransparentColor", "TransparencyFactor", ok );
|
||||||
float CalculatedOpacity = 1.0;
|
float CalculatedOpacity = 1.0f;
|
||||||
if ( ok ) {
|
if ( ok ) {
|
||||||
out_mat->AddProperty( &Transparent, 1, AI_MATKEY_COLOR_TRANSPARENT );
|
out_mat->AddProperty( &Transparent, 1, AI_MATKEY_COLOR_TRANSPARENT );
|
||||||
// as calculated by FBX SDK 2017:
|
// as calculated by FBX SDK 2017:
|
||||||
CalculatedOpacity = 1.0 - ((Transparent.r + Transparent.g + Transparent.b) / 3.0);
|
CalculatedOpacity = 1.0f - ((Transparent.r + Transparent.g + Transparent.b) / 3.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// use of TransparencyFactor is inconsistent.
|
// use of TransparencyFactor is inconsistent.
|
||||||
|
|
|
@ -182,7 +182,7 @@ void FBX::Node::Begin(Assimp::StreamWriterLE &s)
|
||||||
s.PutU4(0); // total property section length
|
s.PutU4(0); // total property section length
|
||||||
|
|
||||||
// node name
|
// node name
|
||||||
s.PutU1(name.size()); // length of node name
|
s.PutU1(uint8_t(name.size())); // length of node name
|
||||||
s.PutString(name); // node name as raw bytes
|
s.PutString(name); // node name as raw bytes
|
||||||
|
|
||||||
// property data comes after here
|
// property data comes after here
|
||||||
|
@ -217,8 +217,8 @@ void FBX::Node::EndProperties(
|
||||||
ai_assert(pos > property_start);
|
ai_assert(pos > property_start);
|
||||||
size_t property_section_size = pos - property_start;
|
size_t property_section_size = pos - property_start;
|
||||||
s.Seek(start_pos + 4);
|
s.Seek(start_pos + 4);
|
||||||
s.PutU4(num_properties);
|
s.PutU4(uint32_t(num_properties));
|
||||||
s.PutU4(property_section_size);
|
s.PutU4(uint32_t(property_section_size));
|
||||||
s.Seek(pos);
|
s.Seek(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +232,7 @@ void FBX::Node::End(
|
||||||
// now go back and write initial pos
|
// now go back and write initial pos
|
||||||
this->end_pos = s.Tell();
|
this->end_pos = s.Tell();
|
||||||
s.Seek(start_pos);
|
s.Seek(start_pos);
|
||||||
s.PutU4(end_pos);
|
s.PutU4(uint32_t(end_pos));
|
||||||
s.Seek(end_pos);
|
s.Seek(end_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,9 +251,9 @@ void FBX::Node::WritePropertyNode(
|
||||||
Node node(name);
|
Node node(name);
|
||||||
node.Begin(s);
|
node.Begin(s);
|
||||||
s.PutU1('d');
|
s.PutU1('d');
|
||||||
s.PutU4(v.size()); // number of elements
|
s.PutU4(uint32_t(v.size())); // number of elements
|
||||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||||
s.PutU4(v.size() * 8); // data size
|
s.PutU4(uint32_t(v.size()) * 8); // data size
|
||||||
for (auto it = v.begin(); it != v.end(); ++it) { s.PutF8(*it); }
|
for (auto it = v.begin(); it != v.end(); ++it) { s.PutF8(*it); }
|
||||||
node.EndProperties(s, 1);
|
node.EndProperties(s, 1);
|
||||||
node.End(s, false);
|
node.End(s, false);
|
||||||
|
@ -271,9 +271,9 @@ void FBX::Node::WritePropertyNode(
|
||||||
Node node(name);
|
Node node(name);
|
||||||
node.Begin(s);
|
node.Begin(s);
|
||||||
s.PutU1('i');
|
s.PutU1('i');
|
||||||
s.PutU4(v.size()); // number of elements
|
s.PutU4(uint32_t(v.size())); // number of elements
|
||||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||||
s.PutU4(v.size() * 4); // data size
|
s.PutU4(uint32_t(v.size()) * 4); // data size
|
||||||
for (auto it = v.begin(); it != v.end(); ++it) { s.PutI4(*it); }
|
for (auto it = v.begin(); it != v.end(); ++it) { s.PutI4(*it); }
|
||||||
node.EndProperties(s, 1);
|
node.EndProperties(s, 1);
|
||||||
node.End(s, false);
|
node.End(s, false);
|
||||||
|
|
|
@ -127,8 +127,8 @@ FBX::Property::Property(const aiMatrix4x4& vm)
|
||||||
: type('d'), data(8*16)
|
: type('d'), data(8*16)
|
||||||
{
|
{
|
||||||
double* d = reinterpret_cast<double*>(data.data());
|
double* d = reinterpret_cast<double*>(data.data());
|
||||||
for (size_t c = 0; c < 4; ++c) {
|
for (unsigned int c = 0; c < 4; ++c) {
|
||||||
for (size_t r = 0; r < 4; ++r) {
|
for (unsigned int r = 0; r < 4; ++r) {
|
||||||
d[4*c+r] = vm[r][c];
|
d[4*c+r] = vm[r][c];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,15 +164,15 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s)
|
||||||
case 'L': s.PutI8(*(reinterpret_cast<int64_t*>(data.data()))); return;
|
case 'L': s.PutI8(*(reinterpret_cast<int64_t*>(data.data()))); return;
|
||||||
case 'S':
|
case 'S':
|
||||||
case 'R':
|
case 'R':
|
||||||
s.PutU4(data.size());
|
s.PutU4(uint32_t(data.size()));
|
||||||
for (size_t i = 0; i < data.size(); ++i) { s.PutU1(data[i]); }
|
for (size_t i = 0; i < data.size(); ++i) { s.PutU1(data[i]); }
|
||||||
return;
|
return;
|
||||||
case 'i':
|
case 'i':
|
||||||
N = data.size() / 4;
|
N = data.size() / 4;
|
||||||
s.PutU4(N); // number of elements
|
s.PutU4(uint32_t(N)); // number of elements
|
||||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||||
// TODO: compress if large?
|
// TODO: compress if large?
|
||||||
s.PutU4(data.size()); // data size
|
s.PutU4(uint32_t(data.size())); // data size
|
||||||
d = data.data();
|
d = data.data();
|
||||||
for (size_t i = 0; i < N; ++i) {
|
for (size_t i = 0; i < N; ++i) {
|
||||||
s.PutI4((reinterpret_cast<int32_t*>(d))[i]);
|
s.PutI4((reinterpret_cast<int32_t*>(d))[i]);
|
||||||
|
@ -180,10 +180,10 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s)
|
||||||
return;
|
return;
|
||||||
case 'd':
|
case 'd':
|
||||||
N = data.size() / 8;
|
N = data.size() / 8;
|
||||||
s.PutU4(N); // number of elements
|
s.PutU4(uint32_t(N)); // number of elements
|
||||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||||
// TODO: compress if large?
|
// TODO: compress if large?
|
||||||
s.PutU4(data.size()); // data size
|
s.PutU4(uint32_t(data.size())); // data size
|
||||||
d = data.data();
|
d = data.data();
|
||||||
for (size_t i = 0; i < N; ++i) {
|
for (size_t i = 0; i < N; ++i) {
|
||||||
s.PutF8((reinterpret_cast<double*>(d))[i]);
|
s.PutF8((reinterpret_cast<double*>(d))[i]);
|
||||||
|
|
|
@ -460,7 +460,7 @@ size_t count_images(const aiScene* scene) {
|
||||||
){
|
){
|
||||||
const aiTextureType textype = static_cast<aiTextureType>(tt);
|
const aiTextureType textype = static_cast<aiTextureType>(tt);
|
||||||
const size_t texcount = mat->GetTextureCount(textype);
|
const size_t texcount = mat->GetTextureCount(textype);
|
||||||
for (size_t j = 0; j < texcount; ++j) {
|
for (unsigned int j = 0; j < texcount; ++j) {
|
||||||
mat->GetTexture(textype, j, &texpath);
|
mat->GetTexture(textype, j, &texpath);
|
||||||
images.insert(std::string(texpath.C_Str()));
|
images.insert(std::string(texpath.C_Str()));
|
||||||
}
|
}
|
||||||
|
@ -593,7 +593,7 @@ void FBXExporter::WriteDefinitions ()
|
||||||
|
|
||||||
// Model / FbxNode
|
// Model / FbxNode
|
||||||
// <~~ node heirarchy
|
// <~~ node heirarchy
|
||||||
count = count_nodes(mScene->mRootNode) - 1; // (not counting root node)
|
count = int32_t(count_nodes(mScene->mRootNode)) - 1; // (not counting root node)
|
||||||
if (count) {
|
if (count) {
|
||||||
n = FBX::Node("ObjectType", Property("Model"));
|
n = FBX::Node("ObjectType", Property("Model"));
|
||||||
n.AddChild("Count", count);
|
n.AddChild("Count", count);
|
||||||
|
@ -763,7 +763,7 @@ void FBXExporter::WriteDefinitions ()
|
||||||
|
|
||||||
// Video / FbxVideo
|
// Video / FbxVideo
|
||||||
// one for each image file.
|
// one for each image file.
|
||||||
count = count_images(mScene);
|
count = int32_t(count_images(mScene));
|
||||||
if (count) {
|
if (count) {
|
||||||
n = FBX::Node("ObjectType", Property("Video"));
|
n = FBX::Node("ObjectType", Property("Video"));
|
||||||
n.AddChild("Count", count);
|
n.AddChild("Count", count);
|
||||||
|
@ -792,7 +792,7 @@ void FBXExporter::WriteDefinitions ()
|
||||||
|
|
||||||
// Texture / FbxFileTexture
|
// Texture / FbxFileTexture
|
||||||
// <~~ aiTexture
|
// <~~ aiTexture
|
||||||
count = count_textures(mScene);
|
count = int32_t(count_textures(mScene));
|
||||||
if (count) {
|
if (count) {
|
||||||
n = FBX::Node("ObjectType", Property("Texture"));
|
n = FBX::Node("ObjectType", Property("Texture"));
|
||||||
n.AddChild("Count", count);
|
n.AddChild("Count", count);
|
||||||
|
@ -848,7 +848,7 @@ void FBXExporter::WriteDefinitions ()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deformer
|
// Deformer
|
||||||
count = count_deformers(mScene);
|
count = int32_t(count_deformers(mScene));
|
||||||
if (count) {
|
if (count) {
|
||||||
n = FBX::Node("ObjectType", Property("Deformer"));
|
n = FBX::Node("ObjectType", Property("Deformer"));
|
||||||
n.AddChild("Count", count);
|
n.AddChild("Count", count);
|
||||||
|
@ -943,7 +943,7 @@ void FBXExporter::WriteObjects ()
|
||||||
std::vector<int32_t> vertex_indices;
|
std::vector<int32_t> vertex_indices;
|
||||||
// map of vertex value to its index in the data vector
|
// map of vertex value to its index in the data vector
|
||||||
std::map<aiVector3D,size_t> index_by_vertex_value;
|
std::map<aiVector3D,size_t> index_by_vertex_value;
|
||||||
size_t index = 0;
|
int32_t index = 0;
|
||||||
for (size_t vi = 0; vi < m->mNumVertices; ++vi) {
|
for (size_t vi = 0; vi < m->mNumVertices; ++vi) {
|
||||||
aiVector3D vtx = m->mVertices[vi];
|
aiVector3D vtx = m->mVertices[vi];
|
||||||
auto elem = index_by_vertex_value.find(vtx);
|
auto elem = index_by_vertex_value.find(vtx);
|
||||||
|
@ -955,7 +955,7 @@ void FBXExporter::WriteObjects ()
|
||||||
flattened_vertices.push_back(vtx[2]);
|
flattened_vertices.push_back(vtx[2]);
|
||||||
++index;
|
++index;
|
||||||
} else {
|
} else {
|
||||||
vertex_indices.push_back(elem->second);
|
vertex_indices.push_back(int32_t(elem->second));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FBX::Node::WritePropertyNode(
|
FBX::Node::WritePropertyNode(
|
||||||
|
@ -1052,7 +1052,7 @@ void FBXExporter::WriteObjects ()
|
||||||
std::vector<double> uv_data;
|
std::vector<double> uv_data;
|
||||||
std::vector<int32_t> uv_indices;
|
std::vector<int32_t> uv_indices;
|
||||||
std::map<aiVector3D,int32_t> index_by_uv;
|
std::map<aiVector3D,int32_t> index_by_uv;
|
||||||
size_t index = 0;
|
int32_t index = 0;
|
||||||
for (size_t fi = 0; fi < m->mNumFaces; ++fi) {
|
for (size_t fi = 0; fi < m->mNumFaces; ++fi) {
|
||||||
const aiFace &f = m->mFaces[fi];
|
const aiFace &f = m->mFaces[fi];
|
||||||
for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) {
|
for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) {
|
||||||
|
@ -1062,7 +1062,7 @@ void FBXExporter::WriteObjects ()
|
||||||
if (elem == index_by_uv.end()) {
|
if (elem == index_by_uv.end()) {
|
||||||
index_by_uv[uv] = index;
|
index_by_uv[uv] = index;
|
||||||
uv_indices.push_back(index);
|
uv_indices.push_back(index);
|
||||||
for (size_t x = 0; x < m->mNumUVComponents[uvi]; ++x) {
|
for (unsigned int x = 0; x < m->mNumUVComponents[uvi]; ++x) {
|
||||||
uv_data.push_back(uv[x]);
|
uv_data.push_back(uv[x]);
|
||||||
}
|
}
|
||||||
++index;
|
++index;
|
||||||
|
@ -1208,13 +1208,13 @@ void FBXExporter::WriteObjects ()
|
||||||
// and usualy are completely ignored when loading.
|
// and usualy are completely ignored when loading.
|
||||||
// One notable exception is the "Opacity" property,
|
// One notable exception is the "Opacity" property,
|
||||||
// which Blender uses as (1.0 - alpha).
|
// which Blender uses as (1.0 - alpha).
|
||||||
c.r = 0; c.g = 0; c.b = 0;
|
c.r = 0.0f; c.g = 0.0f; c.b = 0.0f;
|
||||||
m->Get(AI_MATKEY_COLOR_EMISSIVE, c);
|
m->Get(AI_MATKEY_COLOR_EMISSIVE, c);
|
||||||
p.AddP70vector("Emissive", c.r, c.g, c.b);
|
p.AddP70vector("Emissive", c.r, c.g, c.b);
|
||||||
c.r = 0.2; c.g = 0.2; c.b = 0.2;
|
c.r = 0.2f; c.g = 0.2f; c.b = 0.2f;
|
||||||
m->Get(AI_MATKEY_COLOR_AMBIENT, c);
|
m->Get(AI_MATKEY_COLOR_AMBIENT, c);
|
||||||
p.AddP70vector("Ambient", c.r, c.g, c.b);
|
p.AddP70vector("Ambient", c.r, c.g, c.b);
|
||||||
c.r = 0.8; c.g = 0.8; c.b = 0.8;
|
c.r = 0.8f; c.g = 0.8f; c.b = 0.8f;
|
||||||
m->Get(AI_MATKEY_COLOR_DIFFUSE, c);
|
m->Get(AI_MATKEY_COLOR_DIFFUSE, c);
|
||||||
p.AddP70vector("Diffuse", c.r, c.g, c.b);
|
p.AddP70vector("Diffuse", c.r, c.g, c.b);
|
||||||
// The FBX SDK determines "Opacity" from transparency colour (RGB)
|
// The FBX SDK determines "Opacity" from transparency colour (RGB)
|
||||||
|
@ -1223,29 +1223,29 @@ void FBXExporter::WriteObjects ()
|
||||||
// so we should take it from AI_MATKEY_OPACITY if possible.
|
// so we should take it from AI_MATKEY_OPACITY if possible.
|
||||||
// It might make more sense to use TransparencyFactor,
|
// It might make more sense to use TransparencyFactor,
|
||||||
// but Blender actually loads "Opacity" correctly, so let's use it.
|
// but Blender actually loads "Opacity" correctly, so let's use it.
|
||||||
f = 1.0;
|
f = 1.0f;
|
||||||
if (m->Get(AI_MATKEY_COLOR_TRANSPARENT, c) == aiReturn_SUCCESS) {
|
if (m->Get(AI_MATKEY_COLOR_TRANSPARENT, c) == aiReturn_SUCCESS) {
|
||||||
f = 1.0 - ((c.r + c.g + c.b) / 3);
|
f = 1.0f - ((c.r + c.g + c.b) / 3.0f);
|
||||||
}
|
}
|
||||||
m->Get(AI_MATKEY_OPACITY, f);
|
m->Get(AI_MATKEY_OPACITY, f);
|
||||||
p.AddP70double("Opacity", f);
|
p.AddP70double("Opacity", f);
|
||||||
if (phong) {
|
if (phong) {
|
||||||
// specular color is multiplied by shininess_strength
|
// specular color is multiplied by shininess_strength
|
||||||
c.r = 0.2; c.g = 0.2; c.b = 0.2;
|
c.r = 0.2f; c.g = 0.2f; c.b = 0.2f;
|
||||||
m->Get(AI_MATKEY_COLOR_SPECULAR, c);
|
m->Get(AI_MATKEY_COLOR_SPECULAR, c);
|
||||||
f = 1.0;
|
f = 1.0f;
|
||||||
m->Get(AI_MATKEY_SHININESS_STRENGTH, f);
|
m->Get(AI_MATKEY_SHININESS_STRENGTH, f);
|
||||||
p.AddP70vector("Specular", f*c.r, f*c.g, f*c.b);
|
p.AddP70vector("Specular", f*c.r, f*c.g, f*c.b);
|
||||||
f = 20.0;
|
f = 20.0f;
|
||||||
m->Get(AI_MATKEY_SHININESS, f);
|
m->Get(AI_MATKEY_SHININESS, f);
|
||||||
p.AddP70double("Shininess", f);
|
p.AddP70double("Shininess", f);
|
||||||
// Legacy "Reflectivity" is F*F*((R+G+B)/3),
|
// Legacy "Reflectivity" is F*F*((R+G+B)/3),
|
||||||
// where F is the proportion of light reflected (AKA reflectivity),
|
// where F is the proportion of light reflected (AKA reflectivity),
|
||||||
// and RGB is the reflective colour of the material.
|
// and RGB is the reflective colour of the material.
|
||||||
// No idea why, but we might as well set it the same way.
|
// No idea why, but we might as well set it the same way.
|
||||||
f = 0.0;
|
f = 0.0f;
|
||||||
m->Get(AI_MATKEY_REFLECTIVITY, f);
|
m->Get(AI_MATKEY_REFLECTIVITY, f);
|
||||||
c.r = 1.0, c.g = 1.0, c.b = 1.0;
|
c.r = 1.0f, c.g = 1.0f, c.b = 1.0f;
|
||||||
m->Get(AI_MATKEY_COLOR_REFLECTIVE, c);
|
m->Get(AI_MATKEY_COLOR_REFLECTIVE, c);
|
||||||
p.AddP70double("Reflectivity", f*f*((c.r+c.g+c.b)/3.0));
|
p.AddP70double("Reflectivity", f*f*((c.r+c.g+c.b)/3.0));
|
||||||
}
|
}
|
||||||
|
@ -1269,7 +1269,7 @@ void FBXExporter::WriteObjects ()
|
||||||
const aiTextureType textype = static_cast<aiTextureType>(tt);
|
const aiTextureType textype = static_cast<aiTextureType>(tt);
|
||||||
const size_t texcount = mat->GetTextureCount(textype);
|
const size_t texcount = mat->GetTextureCount(textype);
|
||||||
for (size_t j = 0; j < texcount; ++j) {
|
for (size_t j = 0; j < texcount; ++j) {
|
||||||
mat->GetTexture(textype, j, &texpath);
|
mat->GetTexture(textype, (unsigned int)j, &texpath);
|
||||||
const std::string texstring = texpath.C_Str();
|
const std::string texstring = texpath.C_Str();
|
||||||
auto elem = uid_by_image.find(texstring);
|
auto elem = uid_by_image.find(texstring);
|
||||||
if (elem == uid_by_image.end()) {
|
if (elem == uid_by_image.end()) {
|
||||||
|
@ -1591,7 +1591,7 @@ void FBXExporter::WriteObjects ()
|
||||||
std::vector<int32_t> vertex_indices;
|
std::vector<int32_t> vertex_indices;
|
||||||
// map of vertex value to its index in the data vector
|
// map of vertex value to its index in the data vector
|
||||||
std::map<aiVector3D,size_t> index_by_vertex_value;
|
std::map<aiVector3D,size_t> index_by_vertex_value;
|
||||||
size_t index = 0;
|
int32_t index = 0;
|
||||||
for (size_t vi = 0; vi < m->mNumVertices; ++vi) {
|
for (size_t vi = 0; vi < m->mNumVertices; ++vi) {
|
||||||
aiVector3D vtx = m->mVertices[vi];
|
aiVector3D vtx = m->mVertices[vi];
|
||||||
auto elem = index_by_vertex_value.find(vtx);
|
auto elem = index_by_vertex_value.find(vtx);
|
||||||
|
@ -1600,7 +1600,7 @@ void FBXExporter::WriteObjects ()
|
||||||
index_by_vertex_value[vtx] = index;
|
index_by_vertex_value[vtx] = index;
|
||||||
++index;
|
++index;
|
||||||
} else {
|
} else {
|
||||||
vertex_indices.push_back(elem->second);
|
vertex_indices.push_back(int32_t(elem->second));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1616,7 +1616,7 @@ void FBXExporter::WriteObjects ()
|
||||||
// as it can be instanced to many nodes.
|
// as it can be instanced to many nodes.
|
||||||
// All we can do is assume no instancing,
|
// All we can do is assume no instancing,
|
||||||
// and take the first node we find that contains the mesh.
|
// and take the first node we find that contains the mesh.
|
||||||
aiNode* mesh_node = get_node_for_mesh(mi, mScene->mRootNode);
|
aiNode* mesh_node = get_node_for_mesh((unsigned int)mi, mScene->mRootNode);
|
||||||
aiMatrix4x4 mesh_xform = get_world_transform(mesh_node, mScene);
|
aiMatrix4x4 mesh_xform = get_world_transform(mesh_node, mScene);
|
||||||
|
|
||||||
// now make a subdeformer for each bone in the skeleton
|
// now make a subdeformer for each bone in the skeleton
|
||||||
|
@ -1682,7 +1682,7 @@ void FBXExporter::WriteObjects ()
|
||||||
|
|
||||||
// this should be the same as the bone's mOffsetMatrix.
|
// this should be the same as the bone's mOffsetMatrix.
|
||||||
// if it's not the same, the skeleton isn't in the bind pose.
|
// if it's not the same, the skeleton isn't in the bind pose.
|
||||||
const float epsilon = 1e-5; // some error is to be expected
|
const float epsilon = 1e-5f; // some error is to be expected
|
||||||
bool bone_xform_okay = true;
|
bool bone_xform_okay = true;
|
||||||
if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) {
|
if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) {
|
||||||
not_in_bind_pose.insert(b);
|
not_in_bind_pose.insert(b);
|
||||||
|
@ -2002,7 +2002,7 @@ void FBXExporter::WriteModelNodes(
|
||||||
transform_chain.emplace_back(elem->first, t);
|
transform_chain.emplace_back(elem->first, t);
|
||||||
break;
|
break;
|
||||||
case 'r': // rotation
|
case 'r': // rotation
|
||||||
r *= DEG;
|
r *= float(DEG);
|
||||||
transform_chain.emplace_back(elem->first, r);
|
transform_chain.emplace_back(elem->first, r);
|
||||||
break;
|
break;
|
||||||
case 's': // scale
|
case 's': // scale
|
||||||
|
|
|
@ -622,7 +622,6 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
|
||||||
if (s != std::string::npos) {
|
if (s != std::string::npos) {
|
||||||
DefaultLogger::get()->info("File extension not known, trying signature-based detection");
|
DefaultLogger::get()->info("File extension not known, trying signature-based detection");
|
||||||
for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
|
for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
|
||||||
|
|
||||||
if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) {
|
if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) {
|
||||||
imp = pimpl->mImporter[a];
|
imp = pimpl->mImporter[a];
|
||||||
break;
|
break;
|
||||||
|
@ -947,6 +946,7 @@ BaseImporter* Importer::GetImporter (const char* szExtension) const
|
||||||
size_t Importer::GetImporterIndex (const char* szExtension) const
|
size_t Importer::GetImporterIndex (const char* szExtension) const
|
||||||
{
|
{
|
||||||
ai_assert(szExtension);
|
ai_assert(szExtension);
|
||||||
|
|
||||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||||
|
|
||||||
// skip over wildcard and dot characters at string head --
|
// skip over wildcard and dot characters at string head --
|
||||||
|
|
|
@ -583,9 +583,8 @@ typedef std::map<std::string, std::string> Metadata;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ProcessMetadata(const Schema_2x3::ListOf< Schema_2x3::Lazy< Schema_2x3::IfcProperty >, 1, 0 >& set, ConversionData& conv, Metadata& properties,
|
void ProcessMetadata(const Schema_2x3::ListOf< Schema_2x3::Lazy< Schema_2x3::IfcProperty >, 1, 0 >& set, ConversionData& conv, Metadata& properties,
|
||||||
const std::string& prefix = "",
|
const std::string& prefix = "",
|
||||||
unsigned int nest = 0)
|
unsigned int nest = 0) {
|
||||||
{
|
|
||||||
for(const Schema_2x3::IfcProperty& property : set) {
|
for(const Schema_2x3::IfcProperty& property : set) {
|
||||||
const std::string& key = prefix.length() > 0 ? (prefix + "." + property.Name) : property.Name;
|
const std::string& key = prefix.length() > 0 ? (prefix + "." + property.Name) : property.Name;
|
||||||
if (const Schema_2x3::IfcPropertySingleValue* const singleValue = property.ToPtr<Schema_2x3::IfcPropertySingleValue>()) {
|
if (const Schema_2x3::IfcPropertySingleValue* const singleValue = property.ToPtr<Schema_2x3::IfcPropertySingleValue>()) {
|
||||||
|
|
|
@ -132,18 +132,18 @@ ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMt
|
||||||
mOutputMat.precision(16);
|
mOutputMat.precision(16);
|
||||||
|
|
||||||
WriteGeometryFile(noMtl);
|
WriteGeometryFile(noMtl);
|
||||||
if (!noMtl)
|
if ( !noMtl ) {
|
||||||
WriteMaterialFile();
|
WriteMaterialFile();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
ObjExporter::~ObjExporter() {
|
ObjExporter::~ObjExporter() {
|
||||||
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
std::string ObjExporter :: GetMaterialLibName()
|
std::string ObjExporter::GetMaterialLibName() {
|
||||||
{
|
|
||||||
// within the Obj file, we use just the relative file name with the path stripped
|
// within the Obj file, we use just the relative file name with the path stripped
|
||||||
const std::string& s = GetMaterialLibFileName();
|
const std::string& s = GetMaterialLibFileName();
|
||||||
std::string::size_type il = s.find_last_of("/\\");
|
std::string::size_type il = s.find_last_of("/\\");
|
||||||
|
@ -158,8 +158,9 @@ std::string ObjExporter :: GetMaterialLibName()
|
||||||
std::string ObjExporter::GetMaterialLibFileName() {
|
std::string ObjExporter::GetMaterialLibFileName() {
|
||||||
// Remove existing .obj file extension so that the final material file name will be fileName.mtl and not fileName.obj.mtl
|
// Remove existing .obj file extension so that the final material file name will be fileName.mtl and not fileName.obj.mtl
|
||||||
size_t lastdot = filename.find_last_of('.');
|
size_t lastdot = filename.find_last_of('.');
|
||||||
if (lastdot != std::string::npos)
|
if ( lastdot != std::string::npos ) {
|
||||||
return filename.substr(0, lastdot) + MaterialExt;
|
return filename.substr( 0, lastdot ) + MaterialExt;
|
||||||
|
}
|
||||||
|
|
||||||
return filename + MaterialExt;
|
return filename + MaterialExt;
|
||||||
}
|
}
|
||||||
|
@ -172,8 +173,7 @@ void ObjExporter::WriteHeader(std::ostringstream& out) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
std::string ObjExporter::GetMaterialName(unsigned int index)
|
std::string ObjExporter::GetMaterialName(unsigned int index) {
|
||||||
{
|
|
||||||
const aiMaterial* const mat = pScene->mMaterials[index];
|
const aiMaterial* const mat = pScene->mMaterials[index];
|
||||||
if ( nullptr == mat ) {
|
if ( nullptr == mat ) {
|
||||||
static const std::string EmptyStr;
|
static const std::string EmptyStr;
|
||||||
|
@ -191,8 +191,7 @@ std::string ObjExporter::GetMaterialName(unsigned int index)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ObjExporter::WriteMaterialFile()
|
void ObjExporter::WriteMaterialFile() {
|
||||||
{
|
|
||||||
WriteHeader(mOutputMat);
|
WriteHeader(mOutputMat);
|
||||||
|
|
||||||
for(unsigned int i = 0; i < pScene->mNumMaterials; ++i) {
|
for(unsigned int i = 0; i < pScene->mNumMaterials; ++i) {
|
||||||
|
@ -310,8 +309,9 @@ void ObjExporter::WriteGeometryFile(bool noMtl) {
|
||||||
if (!m.name.empty()) {
|
if (!m.name.empty()) {
|
||||||
mOutput << "g " << m.name << endl;
|
mOutput << "g " << m.name << endl;
|
||||||
}
|
}
|
||||||
if (!noMtl)
|
if ( !noMtl ) {
|
||||||
mOutput << "usemtl " << m.matname << endl;
|
mOutput << "usemtl " << m.matname << endl;
|
||||||
|
}
|
||||||
|
|
||||||
for(const Face& f : m.faces) {
|
for(const Face& f : m.faces) {
|
||||||
mOutput << f.kind << ' ';
|
mOutput << f.kind << ' ';
|
||||||
|
@ -382,7 +382,7 @@ void ObjExporter::colIndexMap::getColors( std::vector<aiColor4D> &colors ) {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) {
|
void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) {
|
||||||
mMeshes.push_back(MeshInstance());
|
mMeshes.push_back(MeshInstance() );
|
||||||
MeshInstance& mesh = mMeshes.back();
|
MeshInstance& mesh = mMeshes.back();
|
||||||
|
|
||||||
mesh.name = std::string( name.data, name.length );
|
mesh.name = std::string( name.data, name.length );
|
||||||
|
@ -436,8 +436,7 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent)
|
void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent) {
|
||||||
{
|
|
||||||
const aiMatrix4x4& mAbs = mParent * nd->mTransformation;
|
const aiMatrix4x4& mAbs = mParent * nd->mTransformation;
|
||||||
|
|
||||||
for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
|
for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
|
||||||
|
|
|
@ -207,30 +207,24 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene
|
||||||
|
|
||||||
// Create the root node of the scene
|
// Create the root node of the scene
|
||||||
pScene->mRootNode = new aiNode;
|
pScene->mRootNode = new aiNode;
|
||||||
if ( !pModel->m_ModelName.empty() )
|
if ( !pModel->m_ModelName.empty() ) {
|
||||||
{
|
|
||||||
// Set the name of the scene
|
// Set the name of the scene
|
||||||
pScene->mRootNode->mName.Set(pModel->m_ModelName);
|
pScene->mRootNode->mName.Set(pModel->m_ModelName);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// This is a fatal error, so break down the application
|
// This is a fatal error, so break down the application
|
||||||
ai_assert(false);
|
ai_assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create nodes for the whole scene
|
// Create nodes for the whole scene
|
||||||
std::vector<aiMesh*> MeshArray;
|
std::vector<aiMesh*> MeshArray;
|
||||||
for (size_t index = 0; index < pModel->m_Objects.size(); index++)
|
for (size_t index = 0; index < pModel->m_Objects.size(); ++index ) {
|
||||||
{
|
|
||||||
createNodes(pModel, pModel->m_Objects[ index ], pScene->mRootNode, pScene, MeshArray);
|
createNodes(pModel, pModel->m_Objects[ index ], pScene->mRootNode, pScene, MeshArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create mesh pointer buffer for this scene
|
// Create mesh pointer buffer for this scene
|
||||||
if (pScene->mNumMeshes > 0)
|
if (pScene->mNumMeshes > 0) {
|
||||||
{
|
|
||||||
pScene->mMeshes = new aiMesh*[ MeshArray.size() ];
|
pScene->mMeshes = new aiMesh*[ MeshArray.size() ];
|
||||||
for (size_t index =0; index < MeshArray.size(); index++)
|
for (size_t index =0; index < MeshArray.size(); ++index ) {
|
||||||
{
|
|
||||||
pScene->mMeshes[ index ] = MeshArray[ index ];
|
pScene->mMeshes[ index ] = MeshArray[ index ];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,8 +255,7 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
|
||||||
appendChildToParentNode( pParent, pNode );
|
appendChildToParentNode( pParent, pNode );
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( size_t i=0; i< pObject->m_Meshes.size(); i++ )
|
for ( size_t i=0; i< pObject->m_Meshes.size(); ++i ) {
|
||||||
{
|
|
||||||
unsigned int meshId = pObject->m_Meshes[ i ];
|
unsigned int meshId = pObject->m_Meshes[ i ];
|
||||||
aiMesh *pMesh = createTopology( pModel, pObject, meshId );
|
aiMesh *pMesh = createTopology( pModel, pObject, meshId );
|
||||||
if( pMesh ) {
|
if( pMesh ) {
|
||||||
|
@ -275,8 +268,7 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create all nodes from the sub-objects stored in the current object
|
// Create all nodes from the sub-objects stored in the current object
|
||||||
if ( !pObject->m_SubObjects.empty() )
|
if ( !pObject->m_SubObjects.empty() ) {
|
||||||
{
|
|
||||||
size_t numChilds = pObject->m_SubObjects.size();
|
size_t numChilds = pObject->m_SubObjects.size();
|
||||||
pNode->mNumChildren = static_cast<unsigned int>( numChilds );
|
pNode->mNumChildren = static_cast<unsigned int>( numChilds );
|
||||||
pNode->mChildren = new aiNode*[ numChilds ];
|
pNode->mChildren = new aiNode*[ numChilds ];
|
||||||
|
@ -286,16 +278,14 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
|
||||||
|
|
||||||
// Set mesh instances into scene- and node-instances
|
// Set mesh instances into scene- and node-instances
|
||||||
const size_t meshSizeDiff = MeshArray.size()- oldMeshSize;
|
const size_t meshSizeDiff = MeshArray.size()- oldMeshSize;
|
||||||
if ( meshSizeDiff > 0 )
|
if ( meshSizeDiff > 0 ) {
|
||||||
{
|
|
||||||
pNode->mMeshes = new unsigned int[ meshSizeDiff ];
|
pNode->mMeshes = new unsigned int[ meshSizeDiff ];
|
||||||
pNode->mNumMeshes = static_cast<unsigned int>( meshSizeDiff );
|
pNode->mNumMeshes = static_cast<unsigned int>( meshSizeDiff );
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
for (size_t i = oldMeshSize; i < MeshArray.size(); i++)
|
for (size_t i = oldMeshSize; i < MeshArray.size(); ++i ) {
|
||||||
{
|
|
||||||
pNode->mMeshes[ index ] = pScene->mNumMeshes;
|
pNode->mMeshes[ index ] = pScene->mNumMeshes;
|
||||||
pScene->mNumMeshes++;
|
pScene->mNumMeshes++;
|
||||||
index++;
|
++index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -612,13 +612,14 @@ void ObjFileParser::getMaterialLib() {
|
||||||
if ( '/' != *path.rbegin() ) {
|
if ( '/' != *path.rbegin() ) {
|
||||||
path += '/';
|
path += '/';
|
||||||
}
|
}
|
||||||
absName = path + strMatName;
|
absName += path;
|
||||||
|
absName += strMatName;
|
||||||
} else {
|
} else {
|
||||||
absName = strMatName;
|
absName = strMatName;
|
||||||
}
|
}
|
||||||
IOStream *pFile = m_pIO->Open( absName );
|
|
||||||
|
|
||||||
if (!pFile ) {
|
IOStream *pFile = m_pIO->Open( absName );
|
||||||
|
if ( nullptr == pFile ) {
|
||||||
DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName);
|
DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName);
|
||||||
std::string strMatFallbackName = m_originalObjFileName.substr(0, m_originalObjFileName.length() - 3) + "mtl";
|
std::string strMatFallbackName = m_originalObjFileName.substr(0, m_originalObjFileName.length() - 3) + "mtl";
|
||||||
DefaultLogger::get()->info("OBJ: Opening fallback material file " + strMatFallbackName);
|
DefaultLogger::get()->info("OBJ: Opening fallback material file " + strMatFallbackName);
|
||||||
|
|
|
@ -52,27 +52,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
|
||||||
namespace Assimp
|
namespace Assimp {
|
||||||
{
|
namespace Ogre {
|
||||||
namespace Ogre
|
|
||||||
{
|
|
||||||
|
|
||||||
/// Returns a lower cased copy of @s.
|
/// Returns a lower cased copy of @s.
|
||||||
static inline std::string ToLower(std::string s)
|
static AI_FORCE_INLINE
|
||||||
|
std::string ToLower(std::string s)
|
||||||
{
|
{
|
||||||
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
|
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns if @c s ends with @c suffix. If @c caseSensitive is false, both strings will be lower cased before matching.
|
/// Returns if @c s ends with @c suffix. If @c caseSensitive is false, both strings will be lower cased before matching.
|
||||||
static inline bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitive = true)
|
static AI_FORCE_INLINE
|
||||||
{
|
bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitive = true) {
|
||||||
if (s.empty() || suffix.empty())
|
if (s.empty() || suffix.empty()) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
} else if (s.length() < suffix.length()) {
|
||||||
else if (s.length() < suffix.length())
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,48 +78,43 @@ static inline bool EndsWith(const std::string &s, const std::string &suffix, boo
|
||||||
|
|
||||||
size_t len = suffix.length();
|
size_t len = suffix.length();
|
||||||
std::string sSuffix = s.substr(s.length()-len, len);
|
std::string sSuffix = s.substr(s.length()-len, len);
|
||||||
|
|
||||||
return (ASSIMP_stricmp(sSuffix, suffix) == 0);
|
return (ASSIMP_stricmp(sSuffix, suffix) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Below trim functions adapted from http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring
|
// Below trim functions adapted from http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring
|
||||||
|
|
||||||
/// Trim from start
|
/// Trim from start
|
||||||
static inline std::string &TrimLeft(std::string &s, bool newlines = true)
|
static AI_FORCE_INLINE
|
||||||
{
|
std::string &TrimLeft(std::string &s, bool newlines = true) {
|
||||||
if (!newlines)
|
if (!newlines) {
|
||||||
{
|
|
||||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpace<char>(c); }));
|
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpace<char>(c); }));
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine<char>(c); }));
|
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine<char>(c); }));
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trim from end
|
/// Trim from end
|
||||||
static inline std::string &TrimRight(std::string &s, bool newlines = true)
|
static AI_FORCE_INLINE
|
||||||
{
|
std::string &TrimRight(std::string &s, bool newlines = true) {
|
||||||
if (!newlines)
|
if (!newlines) {
|
||||||
{
|
|
||||||
s.erase(std::find_if(s.rbegin(), s.rend(), [](char c) { return !Assimp::IsSpace<char>(c); }).base(),s.end());
|
s.erase(std::find_if(s.rbegin(), s.rend(), [](char c) { return !Assimp::IsSpace<char>(c); }).base(),s.end());
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine<char>(c); }));
|
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine<char>(c); }));
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trim from both ends
|
/// Trim from both ends
|
||||||
static inline std::string &Trim(std::string &s, bool newlines = true)
|
static AI_FORCE_INLINE
|
||||||
{
|
std::string &Trim(std::string &s, bool newlines = true) {
|
||||||
return TrimLeft(TrimRight(s, newlines), newlines);
|
return TrimLeft(TrimRight(s, newlines), newlines);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Skips a line from current @ss position until a newline. Returns the skipped part.
|
/// Skips a line from current @ss position until a newline. Returns the skipped part.
|
||||||
static inline std::string SkipLine(std::stringstream &ss)
|
static AI_FORCE_INLINE
|
||||||
{
|
std::string SkipLine(std::stringstream &ss) {
|
||||||
std::string skipped;
|
std::string skipped;
|
||||||
getline(ss, skipped);
|
getline(ss, skipped);
|
||||||
return skipped;
|
return skipped;
|
||||||
|
@ -131,8 +122,8 @@ static inline std::string SkipLine(std::stringstream &ss)
|
||||||
|
|
||||||
/// Skips a line and reads next element from @c ss to @c nextElement.
|
/// Skips a line and reads next element from @c ss to @c nextElement.
|
||||||
/** @return Skipped line content until newline. */
|
/** @return Skipped line content until newline. */
|
||||||
static inline std::string NextAfterNewLine(std::stringstream &ss, std::string &nextElement)
|
static AI_FORCE_INLINE
|
||||||
{
|
std::string NextAfterNewLine(std::stringstream &ss, std::string &nextElement) {
|
||||||
std::string skipped = SkipLine(ss);
|
std::string skipped = SkipLine(ss);
|
||||||
ss >> nextElement;
|
ss >> nextElement;
|
||||||
return skipped;
|
return skipped;
|
||||||
|
|
|
@ -213,18 +213,18 @@ std::string &OgreXmlSerializer::SkipCurrentNode()
|
||||||
DefaultLogger::get()->debug("Skipping node <" + m_currentNodeName + ">");
|
DefaultLogger::get()->debug("Skipping node <" + m_currentNodeName + ">");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for(;;)
|
for(;;) {
|
||||||
{
|
if (!m_reader->read()) {
|
||||||
if (!m_reader->read())
|
|
||||||
{
|
|
||||||
m_currentNodeName = "";
|
m_currentNodeName = "";
|
||||||
return m_currentNodeName;
|
return m_currentNodeName;
|
||||||
}
|
}
|
||||||
if (m_reader->getNodeType() != irr::io::EXN_ELEMENT_END)
|
if ( m_reader->getNodeType() != irr::io::EXN_ELEMENT_END ) {
|
||||||
continue;
|
continue;
|
||||||
else if (std::string(m_reader->getNodeName()) == m_currentNodeName)
|
} else if ( std::string( m_reader->getNodeName() ) == m_currentNodeName ) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NextNode();
|
return NextNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,17 +303,16 @@ static const char *anZ = "z";
|
||||||
|
|
||||||
// Mesh
|
// Mesh
|
||||||
|
|
||||||
MeshXml *OgreXmlSerializer::ImportMesh(XmlReader *reader)
|
MeshXml *OgreXmlSerializer::ImportMesh(XmlReader *reader) {
|
||||||
{
|
|
||||||
OgreXmlSerializer serializer(reader);
|
OgreXmlSerializer serializer(reader);
|
||||||
|
|
||||||
MeshXml *mesh = new MeshXml();
|
MeshXml *mesh = new MeshXml();
|
||||||
serializer.ReadMesh(mesh);
|
serializer.ReadMesh(mesh);
|
||||||
|
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreXmlSerializer::ReadMesh(MeshXml *mesh)
|
void OgreXmlSerializer::ReadMesh(MeshXml *mesh) {
|
||||||
{
|
|
||||||
if (NextNode() != nnMesh) {
|
if (NextNode() != nnMesh) {
|
||||||
throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting <mesh>");
|
throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting <mesh>");
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <assimp/SceneCombiner.h>
|
#include <assimp/SceneCombiner.h>
|
||||||
#include <assimp/StringUtils.h>
|
#include <assimp/StringUtils.h>
|
||||||
#include <assimp/fast_atof.h>
|
#include <assimp/fast_atof.h>
|
||||||
|
#include <assimp/metadata.h>
|
||||||
#include <assimp/Hash.h>
|
#include <assimp/Hash.h>
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
#include <assimp/DefaultLogger.hpp>
|
#include <assimp/DefaultLogger.hpp>
|
||||||
|
@ -806,8 +807,9 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/,
|
||||||
for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
|
for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
|
||||||
if ((*it)->mNormals) {
|
if ((*it)->mNormals) {
|
||||||
::memcpy(pv2,(*it)->mNormals,(*it)->mNumVertices*sizeof(aiVector3D));
|
::memcpy(pv2,(*it)->mNormals,(*it)->mNumVertices*sizeof(aiVector3D));
|
||||||
|
} else {
|
||||||
|
DefaultLogger::get()->warn( "JoinMeshes: Normals expected but input mesh contains no normals" );
|
||||||
}
|
}
|
||||||
else DefaultLogger::get()->warn("JoinMeshes: Normals expected but input mesh contains no normals");
|
|
||||||
pv2 += (*it)->mNumVertices;
|
pv2 += (*it)->mNumVertices;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -817,28 +819,29 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/,
|
||||||
pv2 = out->mTangents = new aiVector3D[out->mNumVertices];
|
pv2 = out->mTangents = new aiVector3D[out->mNumVertices];
|
||||||
aiVector3D* pv2b = out->mBitangents = new aiVector3D[out->mNumVertices];
|
aiVector3D* pv2b = out->mBitangents = new aiVector3D[out->mNumVertices];
|
||||||
|
|
||||||
for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
|
for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
|
||||||
if ((*it)->mTangents) {
|
if ((*it)->mTangents) {
|
||||||
::memcpy(pv2, (*it)->mTangents, (*it)->mNumVertices*sizeof(aiVector3D));
|
::memcpy(pv2, (*it)->mTangents, (*it)->mNumVertices*sizeof(aiVector3D));
|
||||||
::memcpy(pv2b,(*it)->mBitangents,(*it)->mNumVertices*sizeof(aiVector3D));
|
::memcpy(pv2b,(*it)->mBitangents,(*it)->mNumVertices*sizeof(aiVector3D));
|
||||||
|
} else {
|
||||||
|
DefaultLogger::get()->warn( "JoinMeshes: Tangents expected but input mesh contains no tangents" );
|
||||||
}
|
}
|
||||||
else DefaultLogger::get()->warn("JoinMeshes: Tangents expected but input mesh contains no tangents");
|
|
||||||
pv2 += (*it)->mNumVertices;
|
pv2 += (*it)->mNumVertices;
|
||||||
pv2b += (*it)->mNumVertices;
|
pv2b += (*it)->mNumVertices;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// copy texture coordinates
|
// copy texture coordinates
|
||||||
unsigned int n = 0;
|
unsigned int n = 0;
|
||||||
while ((**begin).HasTextureCoords(n)) {
|
while ((**begin).HasTextureCoords(n)) {
|
||||||
out->mNumUVComponents[n] = (*begin)->mNumUVComponents[n];
|
out->mNumUVComponents[n] = (*begin)->mNumUVComponents[n];
|
||||||
|
|
||||||
pv2 = out->mTextureCoords[n] = new aiVector3D[out->mNumVertices];
|
pv2 = out->mTextureCoords[n] = new aiVector3D[out->mNumVertices];
|
||||||
for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
|
for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
|
||||||
|
|
||||||
if ((*it)->mTextureCoords[n]) {
|
if ((*it)->mTextureCoords[n]) {
|
||||||
::memcpy(pv2,(*it)->mTextureCoords[n],(*it)->mNumVertices*sizeof(aiVector3D));
|
::memcpy(pv2,(*it)->mTextureCoords[n],(*it)->mNumVertices*sizeof(aiVector3D));
|
||||||
|
} else {
|
||||||
|
DefaultLogger::get()->warn( "JoinMeshes: UVs expected but input mesh contains no UVs" );
|
||||||
}
|
}
|
||||||
else DefaultLogger::get()->warn("JoinMeshes: UVs expected but input mesh contains no UVs");
|
|
||||||
pv2 += (*it)->mNumVertices;
|
pv2 += (*it)->mNumVertices;
|
||||||
}
|
}
|
||||||
++n;
|
++n;
|
||||||
|
@ -848,11 +851,11 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/,
|
||||||
while ((**begin).HasVertexColors(n)) {
|
while ((**begin).HasVertexColors(n)) {
|
||||||
aiColor4D* pv2 = out->mColors[n] = new aiColor4D[out->mNumVertices];
|
aiColor4D* pv2 = out->mColors[n] = new aiColor4D[out->mNumVertices];
|
||||||
for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
|
for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
|
||||||
|
|
||||||
if ((*it)->mColors[n]) {
|
if ((*it)->mColors[n]) {
|
||||||
::memcpy(pv2,(*it)->mColors[n],(*it)->mNumVertices*sizeof(aiColor4D));
|
::memcpy(pv2,(*it)->mColors[n],(*it)->mNumVertices*sizeof(aiColor4D));
|
||||||
|
} else {
|
||||||
|
DefaultLogger::get()->warn( "JoinMeshes: VCs expected but input mesh contains no VCs" );
|
||||||
}
|
}
|
||||||
else DefaultLogger::get()->warn("JoinMeshes: VCs expected but input mesh contains no VCs");
|
|
||||||
pv2 += (*it)->mNumVertices;
|
pv2 += (*it)->mNumVertices;
|
||||||
}
|
}
|
||||||
++n;
|
++n;
|
||||||
|
@ -1001,7 +1004,12 @@ void SceneCombiner::CopyScene(aiScene** _dest,const aiScene* src,bool allocate)
|
||||||
*_dest = new aiScene();
|
*_dest = new aiScene();
|
||||||
}
|
}
|
||||||
aiScene* dest = *_dest;
|
aiScene* dest = *_dest;
|
||||||
ai_assert(dest);
|
ai_assert(nullptr != dest);
|
||||||
|
|
||||||
|
// copy metadata
|
||||||
|
if ( nullptr != src->mMetaData ) {
|
||||||
|
dest->mMetaData = new aiMetadata( *src->mMetaData );
|
||||||
|
}
|
||||||
|
|
||||||
// copy animations
|
// copy animations
|
||||||
dest->mNumAnimations = src->mNumAnimations;
|
dest->mNumAnimations = src->mNumAnimations;
|
||||||
|
|
|
@ -1076,8 +1076,8 @@ std::string XFileParser::GetNextToken() {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
len = ReadBinDWord();
|
len = ReadBinDWord();
|
||||||
const int bounds( mEnd - mP );
|
const int bounds = int( mEnd - mP );
|
||||||
const int iLen( len );
|
const int iLen = int( len );
|
||||||
if ( iLen < 0 ) {
|
if ( iLen < 0 ) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,9 +131,7 @@ public:
|
||||||
bool detatchStream(LogStream *pStream,
|
bool detatchStream(LogStream *pStream,
|
||||||
unsigned int severity);
|
unsigned int severity);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
/** @briefPrivate construction for internal use by create().
|
/** @briefPrivate construction for internal use by create().
|
||||||
* @param severity Logging granularity */
|
* @param severity Logging granularity */
|
||||||
|
@ -143,8 +141,6 @@ private:
|
||||||
/** @briefDestructor */
|
/** @briefDestructor */
|
||||||
~DefaultLogger();
|
~DefaultLogger();
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
/** @brief Logs debug infos, only been written when severity level VERBOSE is set */
|
/** @brief Logs debug infos, only been written when severity level VERBOSE is set */
|
||||||
void OnDebug(const char* message);
|
void OnDebug(const char* message);
|
||||||
|
|
||||||
|
|
|
@ -115,8 +115,8 @@ bool IsSpaceOrNewLine( char_t in) {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE bool SkipSpaces( const char_t* in, const char_t** out)
|
AI_FORCE_INLINE
|
||||||
{
|
bool SkipSpaces( const char_t* in, const char_t** out) {
|
||||||
while( *in == ( char_t )' ' || *in == ( char_t )'\t' ) {
|
while( *in == ( char_t )' ' || *in == ( char_t )'\t' ) {
|
||||||
++in;
|
++in;
|
||||||
}
|
}
|
||||||
|
@ -126,15 +126,15 @@ AI_FORCE_INLINE bool SkipSpaces( const char_t* in, const char_t** out)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE bool SkipSpaces( const char_t** inout)
|
AI_FORCE_INLINE
|
||||||
{
|
bool SkipSpaces( const char_t** inout) {
|
||||||
return SkipSpaces<char_t>(*inout,inout);
|
return SkipSpaces<char_t>(*inout,inout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE bool SkipLine( const char_t* in, const char_t** out)
|
AI_FORCE_INLINE
|
||||||
{
|
bool SkipLine( const char_t* in, const char_t** out) {
|
||||||
while( *in != ( char_t )'\r' && *in != ( char_t )'\n' && *in != ( char_t )'\0' ) {
|
while( *in != ( char_t )'\r' && *in != ( char_t )'\n' && *in != ( char_t )'\0' ) {
|
||||||
++in;
|
++in;
|
||||||
}
|
}
|
||||||
|
@ -149,15 +149,15 @@ AI_FORCE_INLINE bool SkipLine( const char_t* in, const char_t** out)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE bool SkipLine( const char_t** inout)
|
AI_FORCE_INLINE
|
||||||
{
|
bool SkipLine( const char_t** inout) {
|
||||||
return SkipLine<char_t>(*inout,inout);
|
return SkipLine<char_t>(*inout,inout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out)
|
AI_FORCE_INLINE
|
||||||
{
|
bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out) {
|
||||||
while( *in == ( char_t )' ' || *in == ( char_t )'\t' || *in == ( char_t )'\r' || *in == ( char_t )'\n' ) {
|
while( *in == ( char_t )' ' || *in == ( char_t )'\t' || *in == ( char_t )'\r' || *in == ( char_t )'\n' ) {
|
||||||
++in;
|
++in;
|
||||||
}
|
}
|
||||||
|
@ -167,15 +167,15 @@ AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t** inout)
|
AI_FORCE_INLINE
|
||||||
{
|
bool SkipSpacesAndLineEnd( const char_t** inout) {
|
||||||
return SkipSpacesAndLineEnd<char_t>(*inout,inout);
|
return SkipSpacesAndLineEnd<char_t>(*inout,inout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE bool GetNextLine( const char_t*& buffer, char_t out[ BufferSize ] )
|
AI_FORCE_INLINE
|
||||||
{
|
bool GetNextLine( const char_t*& buffer, char_t out[ BufferSize ] ) {
|
||||||
if( ( char_t )'\0' == *buffer ) {
|
if( ( char_t )'\0' == *buffer ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -203,7 +203,8 @@ AI_FORCE_INLINE bool IsNumeric( char_t in)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len)
|
AI_FORCE_INLINE
|
||||||
|
bool TokenMatch(char_t*& in, const char* token, unsigned int len)
|
||||||
{
|
{
|
||||||
if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
|
if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
|
||||||
if (in[len] != '\0') {
|
if (in[len] != '\0') {
|
||||||
|
@ -223,26 +224,32 @@ AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len
|
||||||
* @param token Token to check for
|
* @param token Token to check for
|
||||||
* @param len Number of characters to check
|
* @param len Number of characters to check
|
||||||
*/
|
*/
|
||||||
AI_FORCE_INLINE bool TokenMatchI(const char*& in, const char* token, unsigned int len)
|
AI_FORCE_INLINE
|
||||||
{
|
bool TokenMatchI(const char*& in, const char* token, unsigned int len) {
|
||||||
if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
|
if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
|
||||||
in += len+1;
|
in += len+1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
AI_FORCE_INLINE void SkipToken(const char*& in)
|
AI_FORCE_INLINE
|
||||||
{
|
void SkipToken(const char*& in) {
|
||||||
SkipSpaces(&in);
|
SkipSpaces(&in);
|
||||||
while (!IsSpaceOrNewLine(*in))++in;
|
while ( !IsSpaceOrNewLine( *in ) ) {
|
||||||
|
++in;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
AI_FORCE_INLINE std::string GetNextToken(const char*& in)
|
AI_FORCE_INLINE
|
||||||
{
|
std::string GetNextToken(const char*& in) {
|
||||||
SkipSpacesAndLineEnd(&in);
|
SkipSpacesAndLineEnd(&in);
|
||||||
const char* cur = in;
|
const char* cur = in;
|
||||||
while (!IsSpaceOrNewLine(*in))++in;
|
while ( !IsSpaceOrNewLine( *in ) ) {
|
||||||
|
++in;
|
||||||
|
}
|
||||||
return std::string(cur,(size_t)(in-cur));
|
return std::string(cur,(size_t)(in-cur));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ public:
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
~StreamWriter() {
|
~StreamWriter() {
|
||||||
stream->Write(&buffer[0], 1, buffer.size());
|
stream->Write(buffer.data(), 1, buffer.size());
|
||||||
stream->Flush();
|
stream->Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ public:
|
||||||
/** Flush the contents of the internal buffer, and the output IOStream */
|
/** Flush the contents of the internal buffer, and the output IOStream */
|
||||||
void Flush()
|
void Flush()
|
||||||
{
|
{
|
||||||
stream->Write(&buffer[0], 1, buffer.size());
|
stream->Write(buffer.data(), 1, buffer.size());
|
||||||
stream->Flush();
|
stream->Flush();
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
cursor = 0;
|
cursor = 0;
|
||||||
|
|
|
@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#define INCLUDED_AI_STRING_WORKERS_H
|
#define INCLUDED_AI_STRING_WORKERS_H
|
||||||
|
|
||||||
#include <assimp/ai_assert.h>
|
#include <assimp/ai_assert.h>
|
||||||
|
#include <assimp/defs.h>
|
||||||
#include "StringComparison.h"
|
#include "StringComparison.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -72,8 +73,8 @@ namespace Assimp {
|
||||||
* @param number Number to be written
|
* @param number Number to be written
|
||||||
* @return Length of the output string, excluding the '\0'
|
* @return Length of the output string, excluding the '\0'
|
||||||
*/
|
*/
|
||||||
inline unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number)
|
AI_FORCE_INLINE
|
||||||
{
|
unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number) {
|
||||||
ai_assert(NULL != out);
|
ai_assert(NULL != out);
|
||||||
|
|
||||||
// write the unary minus to indicate we have a negative number
|
// write the unary minus to indicate we have a negative number
|
||||||
|
@ -91,7 +92,7 @@ inline unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number)
|
||||||
|
|
||||||
const unsigned int digit = number / cur;
|
const unsigned int digit = number / cur;
|
||||||
if (mustPrint || digit > 0 || 1 == cur) {
|
if (mustPrint || digit > 0 || 1 == cur) {
|
||||||
// print all future zeroes from now
|
// print all future zeroe's from now
|
||||||
mustPrint = true;
|
mustPrint = true;
|
||||||
|
|
||||||
*out++ = '0'+static_cast<char>(digit);
|
*out++ = '0'+static_cast<char>(digit);
|
||||||
|
@ -116,8 +117,8 @@ inline unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number)
|
||||||
* size of the array automatically.
|
* size of the array automatically.
|
||||||
*/
|
*/
|
||||||
template <size_t length>
|
template <size_t length>
|
||||||
inline unsigned int ASSIMP_itoa10( char(& out)[length], int32_t number)
|
AI_FORCE_INLINE
|
||||||
{
|
unsigned int ASSIMP_itoa10( char(& out)[length], int32_t number) {
|
||||||
return ASSIMP_itoa10(out,length,number);
|
return ASSIMP_itoa10(out,length,number);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,9 +133,10 @@ inline unsigned int ASSIMP_itoa10( char(& out)[length], int32_t number)
|
||||||
* @param s2 Second input string
|
* @param s2 Second input string
|
||||||
* @return 0 if the given strings are identical
|
* @return 0 if the given strings are identical
|
||||||
*/
|
*/
|
||||||
inline int ASSIMP_stricmp(const char *s1, const char *s2)
|
AI_FORCE_INLINE
|
||||||
{
|
int ASSIMP_stricmp(const char *s1, const char *s2) {
|
||||||
ai_assert(NULL != s1 && NULL != s2);
|
ai_assert( NULL != s1 );
|
||||||
|
ai_assert( NULL != s2 );
|
||||||
|
|
||||||
#if (defined _MSC_VER)
|
#if (defined _MSC_VER)
|
||||||
|
|
||||||
|
@ -161,8 +163,8 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2)
|
||||||
* @param b Second string
|
* @param b Second string
|
||||||
* @return 0 if a == b
|
* @return 0 if a == b
|
||||||
*/
|
*/
|
||||||
inline int ASSIMP_stricmp(const std::string& a, const std::string& b)
|
AI_FORCE_INLINE
|
||||||
{
|
int ASSIMP_stricmp(const std::string& a, const std::string& b) {
|
||||||
int i = (int)b.length()-(int)a.length();
|
int i = (int)b.length()-(int)a.length();
|
||||||
return (i ? i : ASSIMP_stricmp(a.c_str(),b.c_str()));
|
return (i ? i : ASSIMP_stricmp(a.c_str(),b.c_str()));
|
||||||
}
|
}
|
||||||
|
@ -179,10 +181,13 @@ inline int ASSIMP_stricmp(const std::string& a, const std::string& b)
|
||||||
* @param n Macimum number of characters to compare
|
* @param n Macimum number of characters to compare
|
||||||
* @return 0 if the given strings are identical
|
* @return 0 if the given strings are identical
|
||||||
*/
|
*/
|
||||||
inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n)
|
AI_FORCE_INLINE
|
||||||
{
|
int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n) {
|
||||||
ai_assert(NULL != s1 && NULL != s2);
|
ai_assert( NULL != s1 );
|
||||||
if (!n)return 0;
|
ai_assert( NULL != s2 );
|
||||||
|
if ( !n ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#if (defined _MSC_VER)
|
#if (defined _MSC_VER)
|
||||||
|
|
||||||
|
@ -213,14 +218,16 @@ inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n)
|
||||||
*
|
*
|
||||||
* todo: move somewhere where it fits better in than here
|
* todo: move somewhere where it fits better in than here
|
||||||
*/
|
*/
|
||||||
inline unsigned int integer_pow (unsigned int base, unsigned int power)
|
AI_FORCE_INLINE
|
||||||
{
|
unsigned int integer_pow( unsigned int base, unsigned int power ) {
|
||||||
unsigned int res = 1;
|
unsigned int res = 1;
|
||||||
for (unsigned int i = 0; i < power;++i)
|
for ( unsigned int i = 0; i < power; ++i ) {
|
||||||
res *= base;
|
res *= base;
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end of namespace
|
} // end of namespace
|
||||||
|
|
||||||
#endif // ! AI_STRINGCOMPARISON_H_INC
|
#endif // ! AI_STRINGCOMPARISON_H_INC
|
||||||
|
|
|
@ -42,6 +42,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#ifndef INCLUDED_AI_STRINGUTILS_H
|
#ifndef INCLUDED_AI_STRINGUTILS_H
|
||||||
#define INCLUDED_AI_STRINGUTILS_H
|
#define INCLUDED_AI_STRINGUTILS_H
|
||||||
|
|
||||||
|
#include <assimp/defs.h>
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
@ -55,7 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
/// @return The number of written characters if the buffer size was big enough. If an encoding error occurs, a negative number is returned.
|
/// @return The number of written characters if the buffer size was big enough. If an encoding error occurs, a negative number is returned.
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
|
|
||||||
inline
|
AI_FORCE_INLINE
|
||||||
int c99_ai_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) {
|
int c99_ai_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) {
|
||||||
int count(-1);
|
int count(-1);
|
||||||
if (0 != size) {
|
if (0 != size) {
|
||||||
|
@ -68,7 +70,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
AI_FORCE_INLINE
|
||||||
int ai_snprintf(char *outBuf, size_t size, const char *format, ...) {
|
int ai_snprintf(char *outBuf, size_t size, const char *format, ...) {
|
||||||
int count;
|
int count;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
@ -89,7 +91,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
/// @param value The value to write into the std::string.
|
/// @param value The value to write into the std::string.
|
||||||
/// @return The value as a std::string
|
/// @return The value as a std::string
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline
|
AI_FORCE_INLINE
|
||||||
std::string to_string( T value ) {
|
std::string to_string( T value ) {
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os << value;
|
os << value;
|
||||||
|
@ -102,7 +104,7 @@ std::string to_string( T value ) {
|
||||||
/// @param begin The first character of the string.
|
/// @param begin The first character of the string.
|
||||||
/// @param end The last character
|
/// @param end The last character
|
||||||
/// @return The float value, 0.0f in cas of an error.
|
/// @return The float value, 0.0f in cas of an error.
|
||||||
inline
|
AI_FORCE_INLINE
|
||||||
float ai_strtof( const char *begin, const char *end ) {
|
float ai_strtof( const char *begin, const char *end ) {
|
||||||
if ( nullptr == begin ) {
|
if ( nullptr == begin ) {
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
|
@ -124,7 +126,7 @@ float ai_strtof( const char *begin, const char *end ) {
|
||||||
/// @param toConvert Value to convert
|
/// @param toConvert Value to convert
|
||||||
/// @return The hexadecimal string, is empty in case of an error.
|
/// @return The hexadecimal string, is empty in case of an error.
|
||||||
template<class T>
|
template<class T>
|
||||||
inline
|
AI_FORCE_INLINE
|
||||||
std::string DecimalToHexa( T toConvert ) {
|
std::string DecimalToHexa( T toConvert ) {
|
||||||
std::string result;
|
std::string result;
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
|
@ -67,6 +67,7 @@ typedef enum aiMetadataType {
|
||||||
AI_DOUBLE = 4,
|
AI_DOUBLE = 4,
|
||||||
AI_AISTRING = 5,
|
AI_AISTRING = 5,
|
||||||
AI_AIVECTOR3D = 6,
|
AI_AIVECTOR3D = 6,
|
||||||
|
AI_META_MAX = 7,
|
||||||
|
|
||||||
#ifndef SWIG
|
#ifndef SWIG
|
||||||
FORCE_32BIT = INT_MAX
|
FORCE_32BIT = INT_MAX
|
||||||
|
@ -130,42 +131,103 @@ struct aiMetadata {
|
||||||
*/
|
*/
|
||||||
aiMetadata()
|
aiMetadata()
|
||||||
: mNumProperties(0)
|
: mNumProperties(0)
|
||||||
, mKeys(NULL)
|
, mKeys(nullptr)
|
||||||
, mValues(NULL) {
|
, mValues(nullptr) {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aiMetadata( const aiMetadata &rhs )
|
||||||
|
: mNumProperties( rhs.mNumProperties )
|
||||||
|
, mKeys( nullptr )
|
||||||
|
, mValues( nullptr ) {
|
||||||
|
mKeys = new aiString[ mNumProperties ];
|
||||||
|
for ( unsigned int i = 0; i < mNumProperties; ++i ) {
|
||||||
|
mKeys[ i ] = rhs.mKeys[ i ];
|
||||||
|
}
|
||||||
|
mValues = new aiMetadataEntry[ mNumProperties ];
|
||||||
|
for ( unsigned int i = 0; i < mNumProperties; ++i ) {
|
||||||
|
mValues[ i ].mType = rhs.mValues[ i ].mType;
|
||||||
|
switch ( rhs.mValues[ i ].mType ) {
|
||||||
|
case AI_BOOL:
|
||||||
|
mValues[ i ].mData = new bool( rhs.mValues[i].mData );
|
||||||
|
break;
|
||||||
|
case AI_INT32: {
|
||||||
|
int32_t v;
|
||||||
|
::memcpy( &v, rhs.mValues[ i ].mData, sizeof( int32_t ) );
|
||||||
|
mValues[ i ].mData = new int32_t( v );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AI_UINT64: {
|
||||||
|
uint64_t v;
|
||||||
|
::memcpy( &v, rhs.mValues[ i ].mData, sizeof( uint64_t ) );
|
||||||
|
mValues[ i ].mData = new uint64_t( v );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AI_FLOAT: {
|
||||||
|
float v;
|
||||||
|
::memcpy( &v, rhs.mValues[ i ].mData, sizeof( float ) );
|
||||||
|
mValues[ i ].mData = new float( v );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AI_DOUBLE: {
|
||||||
|
double v;
|
||||||
|
::memcpy( &v, rhs.mValues[ i ].mData, sizeof( double ) );
|
||||||
|
mValues[ i ].mData = new double( v );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AI_AISTRING: {
|
||||||
|
aiString v;
|
||||||
|
rhs.Get<aiString>( mKeys[ i ], v );
|
||||||
|
mValues[ i ].mData = new aiString( v );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AI_AIVECTOR3D: {
|
||||||
|
aiVector3D v;
|
||||||
|
rhs.Get<aiVector3D>( mKeys[ i ], v );
|
||||||
|
mValues[ i ].mData = new aiVector3D( v );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#ifndef SWIG
|
||||||
|
case FORCE_32BIT:
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The destructor.
|
* @brief The destructor.
|
||||||
*/
|
*/
|
||||||
~aiMetadata() {
|
~aiMetadata() {
|
||||||
delete [] mKeys;
|
delete [] mKeys;
|
||||||
mKeys = NULL;
|
mKeys = nullptr;
|
||||||
if (mValues) {
|
if (mValues) {
|
||||||
// Delete each metadata entry
|
// Delete each metadata entry
|
||||||
for (unsigned i=0; i<mNumProperties; ++i) {
|
for (unsigned i=0; i<mNumProperties; ++i) {
|
||||||
void* data = mValues[i].mData;
|
void* data = mValues[i].mData;
|
||||||
switch (mValues[i].mType) {
|
switch (mValues[i].mType) {
|
||||||
case AI_BOOL:
|
case AI_BOOL:
|
||||||
delete static_cast<bool*>(data);
|
delete static_cast< bool* >( data );
|
||||||
break;
|
break;
|
||||||
case AI_INT32:
|
case AI_INT32:
|
||||||
delete static_cast<int32_t*>(data);
|
delete static_cast< int32_t* >( data );
|
||||||
break;
|
break;
|
||||||
case AI_UINT64:
|
case AI_UINT64:
|
||||||
delete static_cast<uint64_t*>(data);
|
delete static_cast< uint64_t* >( data );
|
||||||
break;
|
break;
|
||||||
case AI_FLOAT:
|
case AI_FLOAT:
|
||||||
delete static_cast<float*>(data);
|
delete static_cast< float* >( data );
|
||||||
break;
|
break;
|
||||||
case AI_DOUBLE:
|
case AI_DOUBLE:
|
||||||
delete static_cast<double*>(data);
|
delete static_cast< double* >( data );
|
||||||
break;
|
break;
|
||||||
case AI_AISTRING:
|
case AI_AISTRING:
|
||||||
delete static_cast<aiString*>(data);
|
delete static_cast< aiString* >( data );
|
||||||
break;
|
break;
|
||||||
case AI_AIVECTOR3D:
|
case AI_AIVECTOR3D:
|
||||||
delete static_cast<aiVector3D*>(data);
|
delete static_cast< aiVector3D* >( data );
|
||||||
break;
|
break;
|
||||||
#ifndef SWIG
|
#ifndef SWIG
|
||||||
case FORCE_32BIT:
|
case FORCE_32BIT:
|
||||||
|
@ -177,7 +239,7 @@ struct aiMetadata {
|
||||||
|
|
||||||
// Delete the metadata array
|
// Delete the metadata array
|
||||||
delete [] mValues;
|
delete [] mValues;
|
||||||
mValues = NULL;
|
mValues = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,8 +270,8 @@ struct aiMetadata {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline void Add(const std::string& key, const T& value)
|
inline
|
||||||
{
|
void Add(const std::string& key, const T& value) {
|
||||||
aiString* new_keys = new aiString[mNumProperties + 1];
|
aiString* new_keys = new aiString[mNumProperties + 1];
|
||||||
aiMetadataEntry* new_values = new aiMetadataEntry[mNumProperties + 1];
|
aiMetadataEntry* new_values = new aiMetadataEntry[mNumProperties + 1];
|
||||||
|
|
||||||
|
@ -256,7 +318,7 @@ struct aiMetadata {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline
|
inline
|
||||||
bool Get( unsigned index, T& value ) {
|
bool Get( unsigned index, T& value ) const {
|
||||||
// In range assertion
|
// In range assertion
|
||||||
if ( index >= mNumProperties ) {
|
if ( index >= mNumProperties ) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -277,7 +339,7 @@ struct aiMetadata {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline
|
inline
|
||||||
bool Get( const aiString& key, T& value ) {
|
bool Get( const aiString& key, T& value ) const {
|
||||||
// Search for the given key
|
// Search for the given key
|
||||||
for ( unsigned int i = 0; i < mNumProperties; ++i ) {
|
for ( unsigned int i = 0; i < mNumProperties; ++i ) {
|
||||||
if ( mKeys[ i ] == key ) {
|
if ( mKeys[ i ] == key ) {
|
||||||
|
@ -288,7 +350,8 @@ struct aiMetadata {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline bool Get( const std::string& key, T& value ) {
|
inline
|
||||||
|
bool Get( const std::string& key, T& value ) const {
|
||||||
return Get(aiString(key), value);
|
return Get(aiString(key), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,7 +360,8 @@ struct aiMetadata {
|
||||||
/// \param [out] pKey - pointer to the key value.
|
/// \param [out] pKey - pointer to the key value.
|
||||||
/// \param [out] pEntry - pointer to the entry: type and value.
|
/// \param [out] pEntry - pointer to the entry: type and value.
|
||||||
/// \return false - if pIndex is out of range, else - true.
|
/// \return false - if pIndex is out of range, else - true.
|
||||||
inline bool Get(size_t index, const aiString*& key, const aiMetadataEntry*& entry) {
|
inline
|
||||||
|
bool Get(size_t index, const aiString*& key, const aiMetadataEntry*& entry) const {
|
||||||
if ( index >= mNumProperties ) {
|
if ( index >= mNumProperties ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,3 +181,74 @@ TEST_F( utMetadata, get_set_aiVector3D_Test ) {
|
||||||
EXPECT_TRUE( success );
|
EXPECT_TRUE( success );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F( utMetadata, copy_test ) {
|
||||||
|
m_data = aiMetadata::Alloc( AI_META_MAX );
|
||||||
|
bool bv = true;
|
||||||
|
m_data->Set( 0, "bool", bv );
|
||||||
|
int32_t i32v = -10;
|
||||||
|
m_data->Set( 1, "int32", i32v );
|
||||||
|
uint64_t ui64v = static_cast<uint64_t>( 10 );
|
||||||
|
m_data->Set( 2, "uint64", ui64v );
|
||||||
|
float fv = 1.0f;
|
||||||
|
m_data->Set( 3, "float", fv );
|
||||||
|
double dv = 2.0;
|
||||||
|
m_data->Set( 4, "double", dv );
|
||||||
|
const aiString strVal( std::string( "test" ) );
|
||||||
|
m_data->Set( 5, "aiString", strVal );
|
||||||
|
aiVector3D vecVal( 1, 2, 3 );
|
||||||
|
m_data->Set( 6, "aiVector3D", vecVal );
|
||||||
|
|
||||||
|
aiMetadata copy( *m_data );
|
||||||
|
EXPECT_EQ( 7, copy.mNumProperties );
|
||||||
|
|
||||||
|
// bool test
|
||||||
|
{
|
||||||
|
bool v;
|
||||||
|
EXPECT_TRUE( copy.Get( "bool", v ) );
|
||||||
|
EXPECT_EQ( bv, v );
|
||||||
|
}
|
||||||
|
|
||||||
|
// int32_t test
|
||||||
|
{
|
||||||
|
int32_t v;
|
||||||
|
bool ok = copy.Get( "int32", v );
|
||||||
|
EXPECT_TRUE( ok );
|
||||||
|
EXPECT_EQ( i32v, v );
|
||||||
|
}
|
||||||
|
|
||||||
|
// uint64_t test
|
||||||
|
{
|
||||||
|
uint64_t v;
|
||||||
|
bool ok = copy.Get( "uint64", v );
|
||||||
|
EXPECT_TRUE( ok );
|
||||||
|
EXPECT_EQ( ui64v, v );
|
||||||
|
}
|
||||||
|
|
||||||
|
// float test
|
||||||
|
{
|
||||||
|
float v;
|
||||||
|
EXPECT_TRUE( copy.Get( "float", v ) );
|
||||||
|
EXPECT_EQ( fv, v );
|
||||||
|
}
|
||||||
|
|
||||||
|
// double test
|
||||||
|
{
|
||||||
|
double v;
|
||||||
|
EXPECT_TRUE( copy.Get( "double", v ) );
|
||||||
|
EXPECT_EQ( dv, v );
|
||||||
|
}
|
||||||
|
|
||||||
|
// bool test
|
||||||
|
{
|
||||||
|
aiString v;
|
||||||
|
EXPECT_TRUE( copy.Get( "aiString", v ) );
|
||||||
|
EXPECT_EQ( strVal, v );
|
||||||
|
}
|
||||||
|
|
||||||
|
// bool test
|
||||||
|
{
|
||||||
|
aiVector3D v;
|
||||||
|
EXPECT_TRUE( copy.Get( "aiVector3D", v ) );
|
||||||
|
EXPECT_EQ( vecVal, v );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue