3mf: use correct material assignment in case of multi-materials.

pull/1832/head
Kim Kulling 2018-03-09 11:40:45 +01:00
parent 54ca88b466
commit 69742670dd
7 changed files with 110 additions and 61 deletions

View File

@ -74,6 +74,7 @@ namespace XmlTag {
// Material definitions
static const std::string basematerials = "basematerials";
static const std::string basematerials_id = "id";
static const std::string basematerials_base = "base";
static const std::string basematerials_name = "name";
static const std::string basematerials_displaycolor = "displaycolor";

View File

@ -115,13 +115,12 @@ void BaseImporter::SetupProperties(const Importer* /*pImp*/)
}
// ------------------------------------------------------------------------------------------------
void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
{
void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
const aiImporterDesc* desc = GetInfo();
ai_assert(desc != NULL);
ai_assert(desc != nullptr);
const char* ext = desc->mFileExtensions;
ai_assert(ext != NULL);
ai_assert(ext != nullptr );
const char* last = ext;
do {
@ -145,12 +144,13 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
unsigned int searchBytes /* = 200 */,
bool tokensSol /* false */)
{
ai_assert( NULL != tokens );
ai_assert( nullptr != tokens );
ai_assert( 0 != numTokens );
ai_assert( 0 != searchBytes);
if (!pIOHandler)
if ( nullptr == pIOHandler ) {
return false;
}
std::unique_ptr<IOStream> pStream (pIOHandler->Open(pFile));
if (pStream.get() ) {
@ -179,9 +179,9 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
*cur2 = '\0';
std::string token;
for (unsigned int i = 0; i < numTokens;++i) {
for (unsigned int i = 0; i < numTokens; ++i ) {
ai_assert( nullptr != tokens[i] );
size_t len( strlen( tokens[ i ] ) );
const size_t len( strlen( tokens[ i ] ) );
token.clear();
const char *ptr( tokens[ i ] );
for ( size_t tokIdx = 0; tokIdx < len; ++tokIdx ) {

View File

@ -126,7 +126,6 @@ bool D3MFExporter::exportArchive( const char *file ) {
return ok;
}
bool D3MFExporter::exportContentTypes() {
mContentOutput.clear();
@ -177,6 +176,8 @@ bool D3MFExporter::export3DModel() {
mModelOutput << "<" << XmlTag::resources << ">";
mModelOutput << std::endl;
writeBaseMaterials();
writeObjects();
@ -203,6 +204,10 @@ void D3MFExporter::writeHeader() {
mModelOutput << std::endl;
}
void D3MFExporter::writeBaseMaterials() {
}
void D3MFExporter::writeObjects() {
if ( nullptr == mScene->mRootNode ) {
return;

View File

@ -76,6 +76,7 @@ public:
protected:
void writeHeader();
void writeBaseMaterials();
void writeObjects();
void writeMesh( aiMesh *mesh );
void writeVertex( const aiVector3D &pos );

View File

@ -70,9 +70,14 @@ namespace D3MF {
class XmlSerializer {
public:
using MatArray = std::vector<aiMaterial*>;
using MatId2MatArray = std::map<unsigned int, std::vector<unsigned int>>;
XmlSerializer(XmlReader* xmlReader)
: mMeshes()
, mMaterials()
, mMatArray()
, mActiveMatGroup( 99999999 )
, mMatId2MatArray()
, xmlReader(xmlReader){
// empty
}
@ -109,10 +114,10 @@ public:
std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes);
scene->mNumMaterials = mMaterials.size();
scene->mNumMaterials = mMatArray.size();
if ( 0 != scene->mNumMaterials ) {
scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ];
std::copy( mMaterials.begin(), mMaterials.end(), scene->mMaterials );
std::copy( mMatArray.begin(), mMatArray.end(), scene->mMaterials );
}
scene->mRootNode->mNumChildren = static_cast<unsigned int>(children.size());
scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren]();
@ -162,7 +167,7 @@ private:
return node.release();
}
aiMesh* ReadMesh() {
aiMesh *ReadMesh() {
aiMesh* mesh = new aiMesh();
while(ReadToEndElement(D3MF::XmlTag::mesh)) {
if(xmlReader->getNodeName() == D3MF::XmlTag::vertices) {
@ -177,7 +182,6 @@ private:
void ImportVertices(aiMesh* mesh) {
std::vector<aiVector3D> vertices;
while(ReadToEndElement(D3MF::XmlTag::vertices)) {
if(xmlReader->getNodeName() == D3MF::XmlTag::vertex) {
vertices.push_back(ReadVertex());
@ -234,8 +238,27 @@ private:
}
void ReadBaseMaterials() {
std::vector<unsigned int> MatIdArray;
const char *baseMaterialId( xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_id.c_str() ) );
if ( nullptr != baseMaterialId ) {
unsigned int id = std::atoi( baseMaterialId );
const size_t newMatIdx( mMatArray.size() );
if ( id != mActiveMatGroup ) {
mActiveMatGroup = id;
MatId2MatArray::const_iterator it( mMatId2MatArray.find( id ) );
if ( mMatId2MatArray.end() == it ) {
MatIdArray.clear();
mMatId2MatArray[ id ] = MatIdArray;
} else {
MatIdArray = it->second;
}
}
MatIdArray.push_back( newMatIdx );
mMatId2MatArray[ mActiveMatGroup ] = MatIdArray;
}
while ( ReadToEndElement( D3MF::XmlTag::basematerials ) ) {
mMaterials.push_back( readMaterialDef() );
mMatArray.push_back( readMaterialDef() );
xmlReader->read();
}
}
@ -285,24 +308,37 @@ private:
return true;
}
void assignDiffuseColor( aiMaterial *mat ) {
const char *color = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_displaycolor.c_str() );
aiColor4D diffuse;
if ( parseColor( color, diffuse ) ) {
mat->AddProperty<aiColor4D>( &diffuse, 1, AI_MATKEY_COLOR_DIFFUSE );
}
}
aiMaterial *readMaterialDef() {
aiMaterial *mat( nullptr );
const char *name( nullptr );
const char *color( nullptr );
const std::string nodeName( xmlReader->getNodeName() );
if ( nodeName == D3MF::XmlTag::basematerials_base ) {
name = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_name.c_str() );
std::string stdMatName;
aiString matName;
matName.Set( name );
std::string strId( to_string( mActiveMatGroup ) );
stdMatName += "id";
stdMatName += strId;
stdMatName += "_";
if ( nullptr != name ) {
stdMatName += std::string( name );
} else {
stdMatName += "basemat";
}
matName.Set( stdMatName );
mat = new aiMaterial;
mat->AddProperty( &matName, AI_MATKEY_NAME );
color = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_displaycolor.c_str() );
aiColor4D diffuse;
if ( parseColor( color, diffuse ) ) {
mat->AddProperty<aiColor4D>( &diffuse, 1, AI_MATKEY_COLOR_DIFFUSE );
}
assignDiffuseColor( mat );
}
return mat;
@ -339,7 +375,9 @@ private:
private:
std::vector<aiMesh*> mMeshes;
std::vector<aiMaterial*> mMaterials;
MatArray mMatArray;
unsigned int mActiveMatGroup;
MatId2MatArray mMatId2MatArray;
XmlReader* xmlReader;
};
@ -370,14 +408,16 @@ D3MFImporter::~D3MFImporter() {
// empty
}
bool D3MFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(pFile);
bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension( GetExtension( filename ) );
if(extension == Extension ) {
return true;
} else if ( !extension.length() || checkSig ) {
if (nullptr == pIOHandler ) {
return true;
if ( nullptr == pIOHandler ) {
return false;
}
D3MF::D3MFOpcPackage opcPackage( pIOHandler, filename );
return opcPackage.validate();
}
return false;

View File

@ -247,13 +247,13 @@ private:
// ------------------------------------------------------------------------------------------------
// Constructor.
D3MFZipArchive::D3MFZipArchive(IOSystem* pIOHandler, const std::string& rFile)
: m_ZipFileHandle(NULL)
: m_ZipFileHandle( nullptr )
, m_ArchiveMap() {
if (! rFile.empty()) {
zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler);
m_ZipFileHandle = unzOpen2(rFile.c_str(), &mapping);
if(m_ZipFileHandle != NULL) {
if(m_ZipFileHandle != nullptr ) {
mapArchive();
}
}
@ -267,32 +267,32 @@ D3MFZipArchive::~D3MFZipArchive() {
}
m_ArchiveMap.clear();
if(m_ZipFileHandle != NULL) {
if(m_ZipFileHandle != nullptr) {
unzClose(m_ZipFileHandle);
m_ZipFileHandle = NULL;
m_ZipFileHandle = nullptr;
}
}
// ------------------------------------------------------------------------------------------------
// Returns true, if the archive is already open.
bool D3MFZipArchive::isOpen() const {
return (m_ZipFileHandle != NULL);
return (m_ZipFileHandle != nullptr );
}
// ------------------------------------------------------------------------------------------------
// Returns true, if the filename is part of the archive.
bool D3MFZipArchive::Exists(const char* pFile) const {
ai_assert(pFile != NULL);
ai_assert(pFile != nullptr );
bool exist = false;
if ( pFile == nullptr ) {
return false;
}
if (pFile != NULL) {
std::string rFile(pFile);
std::map<std::string, ZipFile*>::const_iterator it = m_ArchiveMap.find(rFile);
if(it != m_ArchiveMap.end()) {
exist = true;
}
std::string rFile(pFile);
std::map<std::string, ZipFile*>::const_iterator it = m_ArchiveMap.find(rFile);
bool exist( false );
if(it != m_ArchiveMap.end()) {
exist = true;
}
return exist;
@ -434,8 +434,8 @@ public:
std::vector<OpcPackageRelationshipPtr> m_relationShips;
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
: mRootStream(nullptr)
, mZipArchive() {
@ -460,7 +460,7 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
if ( rootFile.size() > 0 && rootFile[ 0 ] == '/' ) {
rootFile = rootFile.substr( 1 );
if ( rootFile[ 0 ] == '/' ) {
// deal with zipbug
// deal with zip-bug
rootFile = rootFile.substr( 1 );
}
}
@ -470,18 +470,9 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
mRootStream = mZipArchive->Open(rootFile.c_str());
ai_assert( mRootStream != nullptr );
if ( nullptr == mRootStream ) {
throw DeadlyExportError( "Cannot open rootfile in archive : " + rootFile );
throw DeadlyExportError( "Cannot open root-file in archive : " + rootFile );
}
// const size_t size = zipArchive->FileSize();
// m_Data.resize( size );
// const size_t readSize = pMapFile->Read( &m_Data[0], sizeof( char ), size );
// if ( readSize != size )
// {
// m_Data.clear();
// return false;
// }
mZipArchive->Close( fileStream );
} else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) {
@ -498,6 +489,16 @@ IOStream* D3MFOpcPackage::RootStream() const {
return mRootStream;
}
static const std::string ModelRef = "3D/3dmodel.model";
bool D3MFOpcPackage::validate() {
if ( nullptr == mRootStream || nullptr == mZipArchive ) {
return false;
}
return mZipArchive->Exists( ModelRef.c_str() );
}
std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) {
std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(stream));
std::unique_ptr<XmlReader> xml(irr::io::createIrrXMLReader(xmlStream.get()));
@ -508,14 +509,14 @@ std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) {
return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;
});
if(itr == reader.m_relationShips.end())
throw DeadlyImportError("Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE);
if ( itr == reader.m_relationShips.end() ) {
throw DeadlyImportError( "Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE );
}
return (*itr)->target;
}
} // Namespace D3MF
} // Namespace Assimp
#endif //ASSIMP_BUILD_NO_3MF_IMPORTER

View File

@ -51,8 +51,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
namespace D3MF {
typedef irr::io::IrrXMLReader XmlReader;
typedef std::shared_ptr<XmlReader> XmlReaderPtr;
using XmlReader = irr::io::IrrXMLReader ;
using XmlReaderPtr = std::shared_ptr<XmlReader> ;
struct OpcPackageRelationship {
std::string id;
@ -67,6 +67,7 @@ public:
D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile);
~D3MFOpcPackage();
IOStream* RootStream() const;
bool validate();
protected:
std::string ReadPackageRootRelationship(IOStream* stream);
@ -76,7 +77,7 @@ private:
std::unique_ptr<D3MFZipArchive> mZipArchive;
};
}
}
} // Namespace D3MF
} // Namespace Assimp
#endif // D3MFOPCPACKAGE_H