// ----------------------------------------------------------------------------------- // Write a binary model dump void WriteBinaryDump(const aiScene* scene, FILE* _out, const char* src, const char* cmd, bool _shortened, bool compressed, ImportData& imp) { out = _out; shortened = _shortened; time_t tt = time(NULL); tm* p = gmtime(&tt); // header fprintf(out,"ASSIMP.binary-dump.%s",asctime(p)); // == 44 bytes Write<unsigned int>(ASSBIN_VERSION_MAJOR); Write<unsigned int>(ASSBIN_VERSION_MINOR); Write<unsigned int>(aiGetVersionRevision()); Write<unsigned int>(aiGetCompileFlags()); Write<uint16_t>(shortened); Write<uint16_t>(compressed); // == 20 bytes char buff[256]; strncpy(buff,src,256); fwrite(buff,256,1,out); strncpy(buff,cmd,128); fwrite(buff,128,1,out); // leave 64 bytes free for future extensions memset(buff,0xcd,64); fwrite(buff,64,1,out); // == 435 bytes // ==== total header size: 512 bytes assert(ftell(out)==ASSBIN_HEADER_LENGTH); // Up to here the data is uncompressed. For compressed files, the rest // is compressed using standard DEFLATE from zlib. WriteBinaryScene(scene); }
// ------------------------------------------------------------------------------ // Application entry point int main (int argc, char* argv[]) { if (argc <= 1) { printf("assimp: No command specified. Use \'assimp help\' for a detailed command list\n"); return 0; } // assimp version // Display version information if (! strcmp(argv[1], "version")) { const unsigned int flags = aiGetCompileFlags(); printf(AICMD_MSG_ABOUT, aiGetVersionMajor(), aiGetVersionMinor(), (flags & ASSIMP_CFLAGS_DEBUG ? "-debug " : ""), (flags & ASSIMP_CFLAGS_NOBOOST ? "-noboost " : ""), (flags & ASSIMP_CFLAGS_SHARED ? "-shared " : ""), (flags & ASSIMP_CFLAGS_SINGLETHREADED ? "-st " : ""), (flags & ASSIMP_CFLAGS_STLPORT ? "-stlport " : ""), aiGetVersionRevision()); return 0; } // assimp help // Display some basic help (--help and -h work as well // because people could try them intuitively) if (!strcmp(argv[1], "help") || !strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")) { printf("%s",AICMD_MSG_HELP); return 0; } // assimp cmpdump // Compare two mini model dumps (regression suite) if (! strcmp(argv[1], "cmpdump")) { return Assimp_CompareDump (&argv[2],argc-2); } // construct global importer and exporter instances Assimp::Importer imp; imp.SetPropertyBool("GLOB_MEASURE_TIME",true); globalImporter = &imp; #ifndef ASSIMP_BUILD_NO_EXPORT // Assimp::Exporter exp; globalExporter = &exp; #endif // assimp listext // List all file extensions supported by Assimp if (! strcmp(argv[1], "listext")) { aiString s; imp.GetExtensionList(s); printf("%s\n",s.data); return 0; } #ifndef ASSIMP_BUILD_NO_EXPORT // assimp listexport // List all export file formats supported by Assimp (not the file extensions, just the format identifiers!) if (! strcmp(argv[1], "listexport")) { aiString s; for(size_t i = 0, end = exp.GetExportFormatCount(); i < end; ++i) { const aiExportFormatDesc* const e = exp.GetExportFormatDescription(i); s.Append( e->id ); if (i!=end-1) { s.Append("\n"); } } printf("%s\n",s.data); return 0; } // assimp exportinfo // stat an export format if (! strcmp(argv[1], "exportinfo")) { aiString s; if (argc<3) { printf("Expected file format id\n"); return -11; } for(size_t i = 0, end = exp.GetExportFormatCount(); i < end; ++i) { const aiExportFormatDesc* const e = exp.GetExportFormatDescription(i); if (!strcmp(e->id,argv[2])) { printf("%s\n%s\n%s\n",e->id,e->fileExtension,e->description); return 0; } } printf("Unknown file format id: \'%s\'\n",argv[2]); return -12; } // assimp export // Export a model to a file if (! strcmp(argv[1], "export")) { return Assimp_Export (&argv[2],argc-2); } #endif // assimp knowext // Check whether a particular file extension is known by us, return 0 on success if (! strcmp(argv[1], "knowext")) { if (argc<3) { printf("Expected file extension"); return -10; } const bool b = imp.IsExtensionSupported(argv[2]); printf("File extension \'%s\' is %sknown\n",argv[2],(b?"":"not ")); return b?0:-1; } // assimp info // Print basic model statistics if (! strcmp(argv[1], "info")) { return Assimp_Info ((const char**)&argv[2],argc-2); } // assimp dump // Dump a model to a file if (! strcmp(argv[1], "dump")) { return Assimp_Dump (&argv[2],argc-2); } // assimp extract // Extract an embedded texture from a file if (! strcmp(argv[1], "extract")) { return Assimp_Extract (&argv[2],argc-2); } // assimp testbatchload // Used by /test/other/streamload.py to load a list of files // using the same importer instance to check for incompatible // importers. if (! strcmp(argv[1], "testbatchload")) { return Assimp_TestBatchLoad (&argv[2],argc-2); } printf("Unrecognized command. Use \'assimp help\' for a detailed command list\n"); return 1; }
// ----------------------------------------------------------------------------------- // Write a binary model dump void WriteBinaryDump(const aiScene* scene, FILE* out, const char* src, const char* cmd, bool shortened, bool compressed, ImportData& imp) { time_t tt = ::time(NULL); tm* p = ::gmtime(&tt); // header ::fprintf(out,"ASSIMP.binary-dump.%s.",::asctime(p)); // == 45 bytes WriteInteger(aiGetVersionMajor(),out); WriteInteger(aiGetVersionMinor(),out); WriteInteger(aiGetVersionRevision(),out); WriteInteger(aiGetCompileFlags(),out); WriteShort(shortened,out); WriteShort(compressed,out); // == 20 bytes char buff[256]; ::strncpy(buff,src,256); ::fwrite(buff,256,1,out); ::strncpy(buff,cmd,128); ::fwrite(buff,128,1,out); // leave 41 bytes free for future extensions ::memset(buff,0xcd,41); ::fwrite(buff,32,1,out); // == 435 bytes // ==== total header size: 500 bytes // Up to here the data is uncompressed. For compressed files, the rest // is compressed using standard DEFLATE from zlib. // basic scene information WriteInteger(scene->mFlags,out); WriteInteger(scene->mNumAnimations,out); WriteInteger(scene->mNumTextures,out); WriteInteger(scene->mNumMaterials,out); WriteInteger(scene->mNumCameras,out); WriteInteger(scene->mNumLights,out); WriteInteger(scene->mNumMeshes,out); // write node graph WriteBinaryNode(scene->mRootNode,out); // write materials for (unsigned int i = 0; i< scene->mNumMaterials; ++i) { const aiMaterial* mat = scene->mMaterials[i]; WriteMagic("#MA",out); WriteInteger(mat->mNumProperties,out); for (unsigned int a = 0; a < mat->mNumProperties;++a) { const aiMaterialProperty* prop = mat->mProperties[a]; WriteMagic("#MP",out); WriteAiString(prop->mKey,out); WriteInteger(prop->mSemantic,out); WriteInteger(prop->mIndex,out); WriteInteger(prop->mDataLength,out); ::fwrite(prop->mData,prop->mDataLength,1,out); } } // write cameras for (unsigned int i = 0; i < scene->mNumCameras;++i) { const aiCamera* cam = scene->mCameras[i]; WriteMagic("#CA",out); WriteAiString(cam->mName,out); WriteVec3(cam->mPosition,out); WriteVec3(cam->mLookAt,out); WriteVec3(cam->mUp,out); WriteFloat(cam->mClipPlaneNear,out); WriteFloat(cam->mClipPlaneFar,out); WriteFloat(cam->mHorizontalFOV,out); WriteFloat(cam->mAspect,out); } // write lights for (unsigned int i = 0; i < scene->mNumLights;++i) { const aiLight* l = scene->mLights[i]; WriteMagic("#LI",out); WriteAiString(l->mName,out); WriteInteger(l->mType,out); WriteVec3((const aiVector3D&)l->mColorDiffuse,out); WriteVec3((const aiVector3D&)l->mColorSpecular,out); WriteVec3((const aiVector3D&)l->mColorAmbient,out); if (l->mType != aiLightSource_DIRECTIONAL) { WriteVec3(l->mPosition,out); WriteFloat(l->mAttenuationLinear,out); WriteFloat(l->mAttenuationConstant,out); WriteFloat(l->mAttenuationQuadratic,out); } if (l->mType != aiLightSource_POINT) { WriteVec3(l->mDirection,out); } if (l->mType == aiLightSource_SPOT) { WriteFloat(l->mAttenuationConstant,out); WriteFloat(l->mAttenuationQuadratic,out); } } // write all animations for (unsigned int i = 0; i < scene->mNumAnimations;++i) { const aiAnimation* anim = scene->mAnimations[i]; WriteMagic("#AN",out); WriteAiString (anim->mName,out); WriteDouble (anim->mTicksPerSecond,out); WriteDouble (anim->mDuration,out); WriteInteger(anim->mNumChannels,out); for (unsigned int a = 0; a < anim->mNumChannels;++a) { const aiNodeAnim* nd = anim->mChannels[a]; WriteMagic("#NA",out); WriteAiString(nd->mNodeName,out); WriteInteger(nd->mPreState,out); WriteInteger(nd->mPostState,out); WriteInteger(nd->mNumPositionKeys,out); WriteInteger(nd->mNumRotationKeys,out); WriteInteger(nd->mNumScalingKeys,out); if (nd->mPositionKeys) { if (shortened) { WriteBounds(nd->mPositionKeys,nd->mNumPositionKeys,out); } // else write as usual else ::fwrite(nd->mPositionKeys,sizeof(aiVectorKey),nd->mNumPositionKeys,out); } if (nd->mRotationKeys) { if (shortened) { WriteBounds(nd->mRotationKeys,nd->mNumRotationKeys,out); } // else write as usual else ::fwrite(nd->mRotationKeys,sizeof(aiQuatKey),nd->mNumRotationKeys,out); } if (nd->mScalingKeys) { if (shortened) { WriteBounds(nd->mScalingKeys,nd->mNumScalingKeys,out); } // else write as usual else ::fwrite(nd->mScalingKeys,sizeof(aiVectorKey),nd->mNumScalingKeys,out); } } } // write all meshes for (unsigned int i = 0; i < scene->mNumMeshes;++i) { const aiMesh* mesh = scene->mMeshes[i]; WriteMagic("#ME",out); WriteInteger(mesh->mPrimitiveTypes,out); WriteInteger(mesh->mNumBones,out); WriteInteger(mesh->mNumFaces,out); WriteInteger(mesh->mNumVertices,out); // write bones if (mesh->mNumBones) { for (unsigned int a = 0; a < mesh->mNumBones;++a) { const aiBone* b = mesh->mBones[a]; WriteMagic("#BN",out); WriteAiString(b->mName,out); WriteMat4x4(b->mOffsetMatrix,out); WriteInteger(b->mNumWeights,out); // for the moment we write dumb min/max values for the bones, too. // maybe I'll add a better, hash-like solution later if (shortened) { WriteBounds(b->mWeights,b->mNumWeights,out); } // else write as usual else ::fwrite(b->mWeights,sizeof(aiVertexWeight),b->mNumWeights,out); } } // write faces. There are no floating-point calculations involved // in these, so we can write a simple hash over the face data // to the dump file. We generate a single 32 Bit hash for 512 faces // using Assimp's standard hashing function. if (shortened) { unsigned int processed = 0; for (unsigned int job;job = std::min(mesh->mNumFaces-processed,512u);processed += job) { unsigned int hash = 0; for (unsigned int a = 0; a < job;++a) { const aiFace& f = mesh->mFaces[processed+a]; hash = SuperFastHash((const char*)&f.mNumIndices,sizeof(unsigned int),hash); hash = SuperFastHash((const char*) f.mIndices,f.mNumIndices*sizeof(unsigned int),hash); } WriteInteger(hash,out); } } else // else write as usual { for (unsigned int i = 0; i < mesh->mNumFaces;++i) { const aiFace& f = mesh->mFaces[i]; WriteInteger(f.mNumIndices,out); for (unsigned int a = 0; a < f.mNumIndices;++a) WriteInteger(f.mIndices[a],out); } } // first of all, write bits for all existent vertex components unsigned int c = 0; if (mesh->mVertices) c |= 1; if (mesh->mNormals) c |= 2; if (mesh->mTangents && mesh->mBitangents) c |= 4; for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) { if (!mesh->mTextureCoords[n])break; c |= (8 << n); } for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) { if (!mesh->mColors[n])break; c |= (16 << n); } WriteInteger(c,out); aiVector3D minVec, maxVec; if (mesh->mVertices) { if (shortened) { WriteBounds(mesh->mVertices,mesh->mNumVertices,out); } // else write as usual else ::fwrite(mesh->mVertices,12*mesh->mNumVertices,1,out); } if (mesh->mNormals) { if (shortened) { WriteBounds(mesh->mNormals,mesh->mNumVertices,out); } // else write as usual else ::fwrite(mesh->mNormals,12*mesh->mNumVertices,1,out); } if (mesh->mTangents && mesh->mBitangents) { if (shortened) { WriteBounds(mesh->mTangents,mesh->mNumVertices,out); WriteBounds(mesh->mBitangents,mesh->mNumVertices,out); } // else write as usual else { ::fwrite(mesh->mTangents,12*mesh->mNumVertices,1,out); ::fwrite(mesh->mBitangents,12*mesh->mNumVertices,1,out); } } for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) { if (!mesh->mTextureCoords[n])break; // write number of UV components WriteInteger(mesh->mNumUVComponents[n],out); if (shortened) { WriteBounds(mesh->mTextureCoords[n],mesh->mNumVertices,out); } // else write as usual else ::fwrite(mesh->mTextureCoords[n],12*mesh->mNumVertices,1,out); } for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) { if (!mesh->mColors[n]) break; if (shortened) { WriteBounds(mesh->mColors[n],mesh->mNumVertices,out); } // else write as usual else ::fwrite(mesh->mColors[n],16*mesh->mNumVertices,1,out); } } }
TEST_F( utVersion, aiGetCompileFlagsTest ) { EXPECT_NE( aiGetCompileFlags(), 0U ); }