Read embedded textures from Collada ZAE

pull/2545/head
RichardTea 2019-07-12 14:46:48 +01:00
parent ddd1e770b9
commit 2a72c9b616
5 changed files with 48 additions and 27 deletions

View File

@ -580,15 +580,11 @@ struct Image
{ {
std::string mFileName; std::string mFileName;
/** If image file name is zero, embedded image data /** Embedded image data */
*/
std::vector<uint8_t> mImageData; std::vector<uint8_t> mImageData;
/** If image file name is zero, file format of /** File format hint ofembedded image data */
* embedded image data.
*/
std::string mEmbeddedFormat; std::string mEmbeddedFormat;
}; };
/** An animation channel. */ /** An animation channel. */

View File

@ -235,6 +235,9 @@ void ColladaLoader::InternReadFile(const std::string& pFile, aiScene* pScene, IO
// store all materials // store all materials
StoreSceneMaterials(pScene); StoreSceneMaterials(pScene);
// store all textures
StoreSceneTextures(pScene);
// store all lights // store all lights
StoreSceneLights(pScene); StoreSceneLights(pScene);
@ -927,8 +930,7 @@ void ColladaLoader::StoreSceneLights(aiScene* pScene)
void ColladaLoader::StoreSceneTextures(aiScene* pScene) void ColladaLoader::StoreSceneTextures(aiScene* pScene)
{ {
pScene->mNumTextures = static_cast<unsigned int>(mTextures.size()); pScene->mNumTextures = static_cast<unsigned int>(mTextures.size());
if (mTextures.size() > 0) if (mTextures.size() > 0) {
{
pScene->mTextures = new aiTexture*[mTextures.size()]; pScene->mTextures = new aiTexture*[mTextures.size()];
std::copy(mTextures.begin(), mTextures.end(), pScene->mTextures); std::copy(mTextures.begin(), mTextures.end(), pScene->mTextures);
mTextures.clear(); mTextures.clear();
@ -1728,7 +1730,7 @@ void ColladaLoader::BuildMaterials(ColladaParser& pParser, aiScene* /*pScene*/)
mat->AddProperty(&colSpecular, 1, AI_MATKEY_COLOR_SPECULAR); mat->AddProperty(&colSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
const ai_real specExp = 5.0; const ai_real specExp = 5.0;
mat->AddProperty(&specExp, 1, AI_MATKEY_SHININESS); mat->AddProperty(&specExp, 1, AI_MATKEY_SHININESS);
} }
#endif #endif
} }
@ -1766,14 +1768,19 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser& pParse
} }
// if this is an embedded texture image setup an aiTexture for it // if this is an embedded texture image setup an aiTexture for it
if (imIt->second.mFileName.empty()) if (!imIt->second.mImageData.empty())
{ {
if (imIt->second.mImageData.empty()) {
throw DeadlyImportError("Collada: Invalid texture, no data or file reference given");
}
aiTexture* tex = new aiTexture(); aiTexture* tex = new aiTexture();
// Store embedded texture name reference
tex->mFilename.Set(imIt->second.mFileName.c_str());
result.Set(imIt->second.mFileName);
// TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
// result.data[0] = '*';
// result.length = 1 + ASSIMP_itoa10(result.data + 1, static_cast<unsigned int>(MAXLEN - 1), static_cast<int32_t>(mTextures.size()));
// setup format hint // setup format hint
if (imIt->second.mEmbeddedFormat.length() > 3) { if (imIt->second.mEmbeddedFormat.length() > 3) {
ASSIMP_LOG_WARN("Collada: texture format hint is too long, truncating to 3 characters"); ASSIMP_LOG_WARN("Collada: texture format hint is too long, truncating to 3 characters");
@ -1786,20 +1793,15 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser& pParse
tex->pcData = (aiTexel*)new char[tex->mWidth]; tex->pcData = (aiTexel*)new char[tex->mWidth];
memcpy(tex->pcData, &imIt->second.mImageData[0], tex->mWidth); memcpy(tex->pcData, &imIt->second.mImageData[0], tex->mWidth);
// TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
// In FBX files textures are now stored internally by Assimp with their filename included
// Now Assimp can lookup through the loaded textures after all data is processed
// We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
// This may occur on this case too, it has to be studied
// setup texture reference string
result.data[0] = '*';
result.length = 1 + ASSIMP_itoa10(result.data + 1, static_cast<unsigned int>(MAXLEN - 1), static_cast<int32_t>(mTextures.size()));
// and add this texture to the list // and add this texture to the list
mTextures.push_back(tex); mTextures.push_back(tex);
} }
else else
{ {
if (imIt->second.mFileName.empty()) {
throw DeadlyImportError("Collada: Invalid texture, no data or file reference given");
}
result.Set(imIt->second.mFileName); result.Set(imIt->second.mFileName);
ConvertPath(result); ConvertPath(result);
} }

View File

@ -100,14 +100,14 @@ protected:
/** Return importer meta information. /** Return importer meta information.
* See #BaseImporter::GetInfo for the details * See #BaseImporter::GetInfo for the details
*/ */
const aiImporterDesc* GetInfo () const; const aiImporterDesc* GetInfo () const override;
void SetupProperties(const Importer* pImp); void SetupProperties(const Importer* pImp) override;
/** Imports the given file into the given scene structure. /** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details * See BaseImporter::InternReadFile() for details
*/ */
void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override;
/** Recursively constructs a scene node for the given parser node and returns it. */ /** Recursively constructs a scene node for the given parser node and returns it. */
aiNode* BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode); aiNode* BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode);

View File

@ -132,7 +132,7 @@ ColladaParser::ColladaParser(IOSystem* pIOHandler, const std::string& pFile)
// read embedded textures // read embedded textures
if (zip_archive && zip_archive->isOpen()) { if (zip_archive && zip_archive->isOpen()) {
// TODO ReadEmbeddedTextures(*zip_archive);
} }
} }
@ -3056,6 +3056,26 @@ void ColladaParser::ReadMaterialVertexInputBinding(Collada::SemanticMappingTable
} }
} }
void Assimp::ColladaParser::ReadEmbeddedTextures(ZipArchiveIOSystem& zip_archive)
{
// Attempt to load any undefined Collada::Image in ImageLibrary
for (ImageLibrary::iterator it = mImageLibrary.begin(); it != mImageLibrary.end(); ++it) {
Collada::Image &image = (*it).second;
if (image.mImageData.empty()) {
std::unique_ptr<IOStream> image_file(zip_archive.Open(image.mFileName.c_str()));
if (image_file) {
image.mImageData.resize(image_file->FileSize());
image_file->Read(image.mImageData.data(), image_file->FileSize(), 1);
image.mEmbeddedFormat = BaseImporter::GetExtension(image.mFileName);
if (image.mEmbeddedFormat == "jpeg") {
image.mEmbeddedFormat = "jpg";
}
}
}
}
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads a mesh reference in a node and adds it to the node's mesh list // Reads a mesh reference in a node and adds it to the node's mesh list
void ColladaParser::ReadNodeGeometry(Node* pNode) void ColladaParser::ReadNodeGeometry(Node* pNode)

View File

@ -239,6 +239,9 @@ namespace Assimp
// Processes bind_vertex_input and bind elements // Processes bind_vertex_input and bind elements
void ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl); void ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl);
/** Reads embedded textures from a ZAE archive*/
void ReadEmbeddedTextures(ZipArchiveIOSystem &zip_archive);
protected: protected:
/** Aborts the file reading with an exception */ /** Aborts the file reading with an exception */
AI_WONT_RETURN void ThrowException( const std::string& pError) const AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void ThrowException( const std::string& pError) const AI_WONT_RETURN_SUFFIX;