int CsceneRender::loadAssimpModel(const string & modelFile, const bool wireFrame) { // Import model file const aiScene* scene = importer.ReadFile( modelFile, aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType); if ( !scene ) // If the import failed, report it { std::cout << importer.GetErrorString() << std::endl; return -1; } else //if scene != NULL, import suceed, so associates the scene to the model List { //Sets modelList glutSetWindow(winId); glNewList(modelList, GL_COMPILE); //Draw the model, only polygon faces, filled with orange glColor3f(5.,3.,0.); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); this->recursiveAssimpRender(scene, scene->mRootNode); //if wireFrame, redraw the model but only the polygon line borders in black if (wireFrame) { glColor4f(0.,0.,0.,0.1); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); this->recursiveAssimpRender(scene, scene->mRootNode); } glEndList(); glFinish(); //finish all openGL work // We're done. Everything will be cleaned up by the importer destructor std::cout << "Model loaded successfully by Assimp::Importer"; std::cout << " (Version: " << aiGetVersionMajor() << "." << aiGetVersionMinor() << ")" << std::endl; return 1; } }
// ------------------------------------------------------------------------------------------------ PlyExporter::PlyExporter(const char* _filename, const aiScene* pScene, bool binary) : filename(_filename) , endl("\n") { // make sure that all formatting happens using the standard, C locale and not the user's current locale const std::locale& l = std::locale("C"); mOutput.imbue(l); unsigned int faces = 0u, vertices = 0u, components = 0u; for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { const aiMesh& m = *pScene->mMeshes[i]; faces += m.mNumFaces; vertices += m.mNumVertices; if (m.HasNormals()) { components |= PLY_EXPORT_HAS_NORMALS; } if (m.HasTangentsAndBitangents()) { components |= PLY_EXPORT_HAS_TANGENTS_BITANGENTS; } for (unsigned int t = 0; m.HasTextureCoords(t); ++t) { components |= PLY_EXPORT_HAS_TEXCOORDS << t; } for (unsigned int t = 0; m.HasVertexColors(t); ++t) { components |= PLY_EXPORT_HAS_COLORS << t; } } mOutput << "ply" << endl; if (binary) { #if (defined AI_BUILD_BIG_ENDIAN) mOutput << "format binary_big_endian 1.0" << endl; #else mOutput << "format binary_little_endian 1.0" << endl; #endif } else { mOutput << "format ascii 1.0" << endl; } mOutput << "comment Created by Open Asset Import Library - http://assimp.sf.net (v" << aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.' << aiGetVersionRevision() << ")" << endl; mOutput << "element vertex " << vertices << endl; mOutput << "property float x" << endl; mOutput << "property float y" << endl; mOutput << "property float z" << endl; if(components & PLY_EXPORT_HAS_NORMALS) { mOutput << "property float nx" << endl; mOutput << "property float ny" << endl; mOutput << "property float nz" << endl; } // write texcoords first, just in case an importer does not support tangents // bitangents and just skips over the rest of the line upon encountering // unknown fields (Ply leaves pretty much every vertex component open, // but in reality most importers only know about vertex positions, normals // and texture coordinates). for (unsigned int n = PLY_EXPORT_HAS_TEXCOORDS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_TEXTURECOORDS; n <<= 1, ++c) { if (!c) { mOutput << "property float s" << endl; mOutput << "property float t" << endl; } else { mOutput << "property float s" << c << endl; mOutput << "property float t" << c << endl; } } for (unsigned int n = PLY_EXPORT_HAS_COLORS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_COLOR_SETS; n <<= 1, ++c) { if (!c) { mOutput << "property float r" << endl; mOutput << "property float g" << endl; mOutput << "property float b" << endl; mOutput << "property float a" << endl; } else { mOutput << "property float r" << c << endl; mOutput << "property float g" << c << endl; mOutput << "property float b" << c << endl; mOutput << "property float a" << c << endl; } } if(components & PLY_EXPORT_HAS_TANGENTS_BITANGENTS) { mOutput << "property float tx" << endl; mOutput << "property float ty" << endl; mOutput << "property float tz" << endl; mOutput << "property float bx" << endl; mOutput << "property float by" << endl; mOutput << "property float bz" << endl; } mOutput << "element face " << faces << endl; // uchar seems to be the most common type for the number of indices per polygon and int seems to be most common for the vertex indices. // For instance, MeshLab fails to load meshes in which both types are uint. Houdini seems to have problems as well. // Obviously, using uchar will not work for meshes with polygons with more than 255 indices, but how realistic is this case? mOutput << "property list uchar int vertex_index" << endl; mOutput << "end_header" << endl; for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { if (binary) { WriteMeshVertsBinary(pScene->mMeshes[i], components); } else { WriteMeshVerts(pScene->mMeshes[i], components); } } for (unsigned int i = 0, ofs = 0; i < pScene->mNumMeshes; ++i) { if (binary) { WriteMeshIndicesBinary(pScene->mMeshes[i], ofs); } else { WriteMeshIndices(pScene->mMeshes[i], ofs); } ofs += pScene->mMeshes[i]->mNumVertices; } }
// ------------------------------------------------------------------------------ // 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 text model dump void WriteDump(const aiScene* scene, FILE* out, const char* src, const char* cmd, bool shortened) { time_t tt = ::time(NULL); tm* p = ::gmtime(&tt); std::string c = cmd; std::string::size_type s; // https://sourceforge.net/tracker/?func=detail&aid=3167364&group_id=226462&atid=1067632 // -- not allowed in XML comments while((s = c.find("--")) != std::string::npos) { c[s] = '?'; } aiString name; // write header fprintf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" "<ASSIMP format_id=\"1\">\n\n" "<!-- XML Model dump produced by assimp dump\n" " Library version: %i.%i.%i\n" " Source: %s\n" " Command line: %s\n" " %s\n" "-->" " \n\n" "<Scene flags=\"%i\" postprocessing=\"%i\">\n", aiGetVersionMajor(),aiGetVersionMinor(),aiGetVersionRevision(),src,c.c_str(),asctime(p), scene->mFlags, 0 /*globalImporter->GetEffectivePostProcessing()*/); // write the node graph WriteNode(scene->mRootNode, out, 0); #if 0 // write cameras for (unsigned int i = 0; i < scene->mNumCameras;++i) { aiCamera* cam = scene->mCameras[i]; ConvertName(name,cam->mName); // camera header fprintf(out,"\t<Camera parent=\"%s\">\n" "\t\t<Vector3 name=\"up\" > %0 8f %0 8f %0 8f </Vector3>\n" "\t\t<Vector3 name=\"lookat\" > %0 8f %0 8f %0 8f </Vector3>\n" "\t\t<Vector3 name=\"pos\" > %0 8f %0 8f %0 8f </Vector3>\n" "\t\t<Float name=\"fov\" > %f </Float>\n" "\t\t<Float name=\"aspect\" > %f </Float>\n" "\t\t<Float name=\"near_clip\" > %f </Float>\n" "\t\t<Float name=\"far_clip\" > %f </Float>\n" "\t</Camera>\n", name.data, cam->mUp.x,cam->mUp.y,cam->mUp.z, cam->mLookAt.x,cam->mLookAt.y,cam->mLookAt.z, cam->mPosition.x,cam->mPosition.y,cam->mPosition.z, cam->mHorizontalFOV,cam->mAspect,cam->mClipPlaneNear,cam->mClipPlaneFar,i); } // write lights for (unsigned int i = 0; i < scene->mNumLights;++i) { aiLight* l = scene->mLights[i]; ConvertName(name,l->mName); // light header fprintf(out,"\t<Light parent=\"%s\"> type=\"%s\"\n" "\t\t<Vector3 name=\"diffuse\" > %0 8f %0 8f %0 8f </Vector3>\n" "\t\t<Vector3 name=\"specular\" > %0 8f %0 8f %0 8f </Vector3>\n" "\t\t<Vector3 name=\"ambient\" > %0 8f %0 8f %0 8f </Vector3>\n", name.data, (l->mType == aiLightSource_DIRECTIONAL ? "directional" : (l->mType == aiLightSource_POINT ? "point" : "spot" )), l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b, l->mColorSpecular.r,l->mColorSpecular.g,l->mColorSpecular.b, l->mColorAmbient.r, l->mColorAmbient.g, l->mColorAmbient.b); if (l->mType != aiLightSource_DIRECTIONAL) { fprintf(out, "\t\t<Vector3 name=\"pos\" > %0 8f %0 8f %0 8f </Vector3>\n" "\t\t<Float name=\"atten_cst\" > %f </Float>\n" "\t\t<Float name=\"atten_lin\" > %f </Float>\n" "\t\t<Float name=\"atten_sqr\" > %f </Float>\n", l->mPosition.x,l->mPosition.y,l->mPosition.z, l->mAttenuationConstant,l->mAttenuationLinear,l->mAttenuationQuadratic); } if (l->mType != aiLightSource_POINT) { fprintf(out, "\t\t<Vector3 name=\"lookat\" > %0 8f %0 8f %0 8f </Vector3>\n", l->mDirection.x,l->mDirection.y,l->mDirection.z); } if (l->mType == aiLightSource_SPOT) { fprintf(out, "\t\t<Float name=\"cone_out\" > %f </Float>\n" "\t\t<Float name=\"cone_inn\" > %f </Float>\n", l->mAngleOuterCone,l->mAngleInnerCone); } fprintf(out,"\t</Light>\n"); } #endif // write textures if (scene->mNumTextures) { fprintf(out,"<TextureList num=\"%i\">\n",scene->mNumTextures); for (unsigned int i = 0; i < scene->mNumTextures;++i) { aiTexture* tex = scene->mTextures[i]; bool compressed = (tex->mHeight == 0); // mesh header fprintf(out,"\t<Texture width=\"%i\" height=\"%i\" compressed=\"%s\"> \n", (compressed ? -1 : tex->mWidth),(compressed ? -1 : tex->mHeight), (compressed ? "true" : "false")); if (compressed) { fprintf(out,"\t\t<Data length=\"%i\"> \n",tex->mWidth); if (!shortened) { for (unsigned int n = 0; n < tex->mWidth;++n) { fprintf(out,"\t\t\t%2x",reinterpret_cast<uint8_t*>(tex->pcData)[n]); if (n && !(n % 50)) { fprintf(out,"\n"); } } } } else if (!shortened){ fprintf(out,"\t\t<Data length=\"%i\"> \n",tex->mWidth*tex->mHeight*4); // const unsigned int width = (unsigned int)log10((double)std::max(tex->mHeight,tex->mWidth))+1; for (unsigned int y = 0; y < tex->mHeight;++y) { for (unsigned int x = 0; x < tex->mWidth;++x) { aiTexel* tx = tex->pcData + y*tex->mWidth+x; unsigned int r = tx->r,g=tx->g,b=tx->b,a=tx->a; fprintf(out,"\t\t\t%2x %2x %2x %2x",r,g,b,a); // group by four for readibility if (0 == (x+y*tex->mWidth) % 4) fprintf(out,"\n"); } } } fprintf(out,"\t\t</Data>\n\t</Texture>\n"); } fprintf(out,"</TextureList>\n"); } // write materials if (scene->mNumMaterials) { fprintf(out,"<MaterialList num=\"%i\">\n",scene->mNumMaterials); for (unsigned int i = 0; i< scene->mNumMaterials; ++i) { const aiMaterial* mat = scene->mMaterials[i]; fprintf(out,"\t<Material>\n"); fprintf(out,"\t\t<MatPropertyList num=\"%i\">\n",mat->mNumProperties); for (unsigned int n = 0; n < mat->mNumProperties;++n) { const aiMaterialProperty* prop = mat->mProperties[n]; const char* sz = ""; if (prop->mType == aiPTI_Float) { sz = "float"; } else if (prop->mType == aiPTI_Integer) { sz = "integer"; } else if (prop->mType == aiPTI_String) { sz = "string"; } else if (prop->mType == aiPTI_Buffer) { sz = "binary_buffer"; } fprintf(out,"\t\t\t<MatProperty key=\"%s\" \n\t\t\ttype=\"%s\" tex_usage=\"%s\" tex_index=\"%i\"", prop->mKey.data, sz, ::TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex); if (prop->mType == aiPTI_Float) { fprintf(out," size=\"%i\">\n\t\t\t\t", static_cast<int>(prop->mDataLength/sizeof(float))); for (unsigned int p = 0; p < prop->mDataLength/sizeof(float);++p) { fprintf(out,"%f ",*((float*)(prop->mData+p*sizeof(float)))); } } else if (prop->mType == aiPTI_Integer) { fprintf(out," size=\"%i\">\n\t\t\t\t", static_cast<int>(prop->mDataLength/sizeof(int))); for (unsigned int p = 0; p < prop->mDataLength/sizeof(int);++p) { fprintf(out,"%i ",*((int*)(prop->mData+p*sizeof(int)))); } } else if (prop->mType == aiPTI_Buffer) { fprintf(out," size=\"%i\">\n\t\t\t\t", static_cast<int>(prop->mDataLength)); for (unsigned int p = 0; p < prop->mDataLength;++p) { fprintf(out,"%2x ",prop->mData[p]); if (p && 0 == p%30) { fprintf(out,"\n\t\t\t\t"); } } } else if (prop->mType == aiPTI_String) { fprintf(out,">\n\t\t\t\"%s\"",prop->mData+4 /* skip length */); } fprintf(out,"\n\t\t\t</MatProperty>\n"); } fprintf(out,"\t\t</MatPropertyList>\n"); fprintf(out,"\t</Material>\n"); } fprintf(out,"</MaterialList>\n"); } // write animations if (scene->mNumAnimations) { fprintf(out,"<AnimationList num=\"%i\">\n",scene->mNumAnimations); for (unsigned int i = 0; i < scene->mNumAnimations;++i) { aiAnimation* anim = scene->mAnimations[i]; // anim header ConvertName(name,anim->mName); fprintf(out,"\t<Animation name=\"%s\" duration=\"%e\" tick_cnt=\"%e\">\n", name.data, anim->mDuration, anim->mTicksPerSecond); // write bone animation channels if (anim->mNumChannels) { fprintf(out,"\t\t<NodeAnimList num=\"%i\">\n",anim->mNumChannels); for (unsigned int n = 0; n < anim->mNumChannels;++n) { aiNodeAnim* nd = anim->mChannels[n]; // node anim header ConvertName(name,nd->mNodeName); fprintf(out,"\t\t\t<NodeAnim node=\"%s\">\n",name.data); if (!shortened) { // write position keys if (nd->mNumPositionKeys) { fprintf(out,"\t\t\t\t<PositionKeyList num=\"%i\">\n",nd->mNumPositionKeys); for (unsigned int a = 0; a < nd->mNumPositionKeys;++a) { aiVectorKey* vc = nd->mPositionKeys+a; fprintf(out,"\t\t\t\t\t<PositionKey time=\"%e\">\n" "\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t</PositionKey>\n", vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z); } fprintf(out,"\t\t\t\t</PositionKeyList>\n"); } // write scaling keys if (nd->mNumScalingKeys) { fprintf(out,"\t\t\t\t<ScalingKeyList num=\"%i\">\n",nd->mNumScalingKeys); for (unsigned int a = 0; a < nd->mNumScalingKeys;++a) { aiVectorKey* vc = nd->mScalingKeys+a; fprintf(out,"\t\t\t\t\t<ScalingKey time=\"%e\">\n" "\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t</ScalingKey>\n", vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z); } fprintf(out,"\t\t\t\t</ScalingKeyList>\n"); } // write rotation keys if (nd->mNumRotationKeys) { fprintf(out,"\t\t\t\t<RotationKeyList num=\"%i\">\n",nd->mNumRotationKeys); for (unsigned int a = 0; a < nd->mNumRotationKeys;++a) { aiQuatKey* vc = nd->mRotationKeys+a; fprintf(out,"\t\t\t\t\t<RotationKey time=\"%e\">\n" "\t\t\t\t\t\t%0 8f %0 8f %0 8f %0 8f\n\t\t\t\t\t</RotationKey>\n", vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z,vc->mValue.w); } fprintf(out,"\t\t\t\t</RotationKeyList>\n"); } } fprintf(out,"\t\t\t</NodeAnim>\n"); } fprintf(out,"\t\t</NodeAnimList>\n"); } fprintf(out,"\t</Animation>\n"); } fprintf(out,"</AnimationList>\n"); } // write meshes if (scene->mNumMeshes) { fprintf(out,"<MeshList num=\"%i\">\n",scene->mNumMeshes); for (unsigned int i = 0; i < scene->mNumMeshes;++i) { aiMesh* mesh = scene->mMeshes[i]; // const unsigned int width = (unsigned int)log10((double)mesh->mNumVertices)+1; // mesh header fprintf(out,"\t<Mesh types=\"%s %s %s %s\" material_index=\"%i\">\n", (mesh->mPrimitiveTypes & aiPrimitiveType_POINT ? "points" : ""), (mesh->mPrimitiveTypes & aiPrimitiveType_LINE ? "lines" : ""), (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE ? "triangles" : ""), (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON ? "polygons" : ""), mesh->mMaterialIndex); // bones if (mesh->mNumBones) { fprintf(out,"\t\t<BoneList num=\"%i\">\n",mesh->mNumBones); for (unsigned int n = 0; n < mesh->mNumBones;++n) { aiBone* bone = mesh->mBones[n]; ConvertName(name,bone->mName); // bone header fprintf(out,"\t\t\t<Bone name=\"%s\">\n" "\t\t\t\t<Matrix4> \n" "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" "\t\t\t\t</Matrix4> \n", name.data, bone->mOffsetMatrix.a1,bone->mOffsetMatrix.a2,bone->mOffsetMatrix.a3,bone->mOffsetMatrix.a4, bone->mOffsetMatrix.b1,bone->mOffsetMatrix.b2,bone->mOffsetMatrix.b3,bone->mOffsetMatrix.b4, bone->mOffsetMatrix.c1,bone->mOffsetMatrix.c2,bone->mOffsetMatrix.c3,bone->mOffsetMatrix.c4, bone->mOffsetMatrix.d1,bone->mOffsetMatrix.d2,bone->mOffsetMatrix.d3,bone->mOffsetMatrix.d4); if (!shortened && bone->mNumWeights) { fprintf(out,"\t\t\t\t<WeightList num=\"%i\">\n",bone->mNumWeights); // bone weights for (unsigned int a = 0; a < bone->mNumWeights;++a) { aiVertexWeight* wght = bone->mWeights+a; fprintf(out,"\t\t\t\t\t<Weight index=\"%i\">\n\t\t\t\t\t\t%f\n\t\t\t\t\t</Weight>\n", wght->mVertexId,wght->mWeight); } fprintf(out,"\t\t\t\t</WeightList>\n"); } fprintf(out,"\t\t\t</Bone>\n"); } fprintf(out,"\t\t</BoneList>\n"); } // faces if (!shortened && mesh->mNumFaces) { fprintf(out,"\t\t<FaceList num=\"%i\">\n",mesh->mNumFaces); for (unsigned int n = 0; n < mesh->mNumFaces; ++n) { aiFace& f = mesh->mFaces[n]; fprintf(out,"\t\t\t<Face num=\"%i\">\n" "\t\t\t\t",f.mNumIndices); for (unsigned int j = 0; j < f.mNumIndices;++j) fprintf(out,"%i ",f.mIndices[j]); fprintf(out,"\n\t\t\t</Face>\n"); } fprintf(out,"\t\t</FaceList>\n"); } // vertex positions if (mesh->HasPositions()) { fprintf(out,"\t\t<Positions num=\"%i\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices); if (!shortened) { for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { fprintf(out,"\t\t%0 8f %0 8f %0 8f\n", mesh->mVertices[n].x, mesh->mVertices[n].y, mesh->mVertices[n].z); } } fprintf(out,"\t\t</Positions>\n"); } // vertex normals if (mesh->HasNormals()) { fprintf(out,"\t\t<Normals num=\"%i\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices); if (!shortened) { for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { fprintf(out,"\t\t%0 8f %0 8f %0 8f\n", mesh->mNormals[n].x, mesh->mNormals[n].y, mesh->mNormals[n].z); } } else { } fprintf(out,"\t\t</Normals>\n"); } // vertex tangents and bitangents if (mesh->HasTangentsAndBitangents()) { fprintf(out,"\t\t<Tangents num=\"%i\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices); if (!shortened) { for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { fprintf(out,"\t\t%0 8f %0 8f %0 8f\n", mesh->mTangents[n].x, mesh->mTangents[n].y, mesh->mTangents[n].z); } } fprintf(out,"\t\t</Tangents>\n"); fprintf(out,"\t\t<Bitangents num=\"%i\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices); if (!shortened) { for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { fprintf(out,"\t\t%0 8f %0 8f %0 8f\n", mesh->mBitangents[n].x, mesh->mBitangents[n].y, mesh->mBitangents[n].z); } } fprintf(out,"\t\t</Bitangents>\n"); } // texture coordinates for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { if (!mesh->mTextureCoords[a]) break; fprintf(out,"\t\t<TextureCoords num=\"%i\" set=\"%i\" num_components=\"%i\"> \n",mesh->mNumVertices, a,mesh->mNumUVComponents[a]); if (!shortened) { if (mesh->mNumUVComponents[a] == 3) { for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { fprintf(out,"\t\t%0 8f %0 8f %0 8f\n", mesh->mTextureCoords[a][n].x, mesh->mTextureCoords[a][n].y, mesh->mTextureCoords[a][n].z); } } else { for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { fprintf(out,"\t\t%0 8f %0 8f\n", mesh->mTextureCoords[a][n].x, mesh->mTextureCoords[a][n].y); } } } fprintf(out,"\t\t</TextureCoords>\n"); } // vertex colors for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a) { if (!mesh->mColors[a]) break; fprintf(out,"\t\t<Colors num=\"%i\" set=\"%i\" num_components=\"4\"> \n",mesh->mNumVertices,a); if (!shortened) { for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { fprintf(out,"\t\t%0 8f %0 8f %0 8f %0 8f\n", mesh->mColors[a][n].r, mesh->mColors[a][n].g, mesh->mColors[a][n].b, mesh->mColors[a][n].a); } } fprintf(out,"\t\t</Color>\n"); } fprintf(out,"\t</Mesh>\n"); } fprintf(out,"</MeshList>\n"); } fprintf(out,"</Scene>\n</ASSIMP>"); }
// ----------------------------------------------------------------------------------- // Write a text model dump void WriteDump(const aiScene* scene, FILE* out, const char* src, const char* cmd, bool shortened) { time_t tt = ::time(NULL); tm* p = ::gmtime(&tt); aiString name; // write header ::fprintf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" "<ASSIMP >\n\n" "<!-- XML Model dump produced by assimp dump\n" " Library version: %i.%i.%i\n" " Source: %s\n" " Command line: %s\n" " %s\n" "-->" " \n\n" "<Scene NumberOfMeshes=\"%i\" NumberOfMaterials=\"%i\" NumberOfTextures=\"%i\" NumberOfCameras=\"%i\" NumberOfLights=\"%i\" NumberOfAnimations=\"%i\">\n", aiGetVersionMajor(),aiGetVersionMinor(),aiGetVersionRevision(),src,cmd,::asctime(p), scene->mNumMeshes, scene->mNumMaterials,scene->mNumTextures, scene->mNumCameras,scene->mNumLights,scene->mNumAnimations); // write the node graph WriteNode(scene->mRootNode, out, 1); // write cameras for (unsigned int i = 0; i < scene->mNumCameras;++i) { aiCamera* cam = scene->mCameras[i]; ConvertName(name,cam->mName); // camera header ::fprintf(out,"\t<Camera parent=\"%s\">\n" "\t\t<Vector3 name=\"up\" > %0 8f %0 8f %0 8f </Vector3>\n" "\t\t<Vector3 name=\"lookat\" > %0 8f %0 8f %0 8f </Vector3>\n" "\t\t<Vector3 name=\"pos\" > %0 8f %0 8f %0 8f </Vector3>\n" "\t\t<Float name=\"fov\" > %f </Float>\n" "\t\t<Float name=\"aspect\" > %f </Float>\n" "\t\t<Float name=\"near_clip\" > %f </Float>\n" "\t\t<Float name=\"far_clip\" > %f </Float>\n" "\t</Camera>\n", name.data, cam->mUp.x,cam->mUp.y,cam->mUp.z, cam->mLookAt.x,cam->mLookAt.y,cam->mLookAt.z, cam->mPosition.x,cam->mPosition.y,cam->mPosition.z, cam->mHorizontalFOV,cam->mAspect,cam->mClipPlaneNear,cam->mClipPlaneFar,i); } // write lights for (unsigned int i = 0; i < scene->mNumLights;++i) { aiLight* l = scene->mLights[i]; ConvertName(name,l->mName); // light header ::fprintf(out,"\t<Light parent=\"%s\"> type=\"%s\"\n" "\t\t<Vector3 name=\"diffuse\" > %0 8f %0 8f %0 8f </Vector3>\n" "\t\t<Vector3 name=\"specular\" > %0 8f %0 8f %0 8f </Vector3>\n" "\t\t<Vector3 name=\"ambient\" > %0 8f %0 8f %0 8f </Vector3>\n", name.data, (l->mType == aiLightSource_DIRECTIONAL ? "directional" : (l->mType == aiLightSource_POINT ? "point" : "spot" )), l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b, l->mColorSpecular.r,l->mColorSpecular.g,l->mColorSpecular.b, l->mColorAmbient.r, l->mColorAmbient.g, l->mColorAmbient.b); if (l->mType != aiLightSource_DIRECTIONAL) { ::fprintf(out, "\t\t<Vector3 name=\"pos\" > %0 8f %0 8f %0 8f </Vector3>\n" "\t\t<Float name=\"atten_cst\" > %f </Float>\n" "\t\t<Float name=\"atten_lin\" > %f </Float>\n" "\t\t<Float name=\"atten_sqr\" > %f </Float>\n", l->mPosition.x,l->mPosition.y,l->mPosition.z, l->mAttenuationConstant,l->mAttenuationLinear,l->mAttenuationQuadratic); } if (l->mType != aiLightSource_POINT) { ::fprintf(out, "\t\t<Vector3 name=\"lookat\" > %0 8f %0 8f %0 8f </Vector3>\n", l->mDirection.x,l->mDirection.y,l->mDirection.z); } if (l->mType == aiLightSource_SPOT) { ::fprintf(out, "\t\t<Float name=\"cone_out\" > %f </Float>\n" "\t\t<Float name=\"cone_inn\" > %f </Float>\n", l->mAngleOuterCone,l->mAngleInnerCone); } ::fprintf(out,"\t</Light>\n"); } // write textures for (unsigned int i = 0; i < scene->mNumTextures;++i) { aiTexture* tex = scene->mTextures[i]; bool compressed = (tex->mHeight == 0); // mesh header ::fprintf(out,"\t<Texture> \n" "\t\t<Integer name=\"width\" > %i </Integer>\n", "\t\t<Integer name=\"height\" > %i </Integer>\n", "\t\t<Boolean name=\"compressed\" > %s </Boolean>\n", (compressed ? -1 : tex->mWidth),(compressed ? -1 : tex->mHeight), (compressed ? "true" : "false")); if (compressed) { ::fprintf(out,"\t\t<Data length=\"%i\"> %i \n",tex->mWidth); if (!shortened) { for (unsigned int n = 0; n < tex->mWidth;++n) { ::fprintf(out,"\t\t\t%2x",tex->pcData[n]); if (n && !(n % 50)) ::fprintf(out,"\n"); } } } else if (!shortened){ ::fprintf(out,"\t\t<Data length=\"%i\"> %i \n",tex->mWidth*tex->mHeight*4); const unsigned int width = (unsigned int)log10((double)std::max(tex->mHeight,tex->mWidth))+1; for (unsigned int y = 0; y < tex->mHeight;++y) { for (unsigned int x = 0; x < tex->mWidth;++x) { aiTexel* tx = tex->pcData + y*tex->mWidth+x; unsigned int r = tx->r,g=tx->g,b=tx->b,a=tx->a; ::fprintf(out,"\t\t\t%2x %2x %2x %2x",r,g,b,a); // group by four for readibility if (0 == (x+y*tex->mWidth) % 4) ::fprintf(out,"\n"); } } } ::fprintf(out,"\t\t</Data>\n\t</Texture>\n"); } // write materials for (unsigned int i = 0; i< scene->mNumMaterials; ++i) { const aiMaterial* mat = scene->mMaterials[i]; ::fprintf(out, "\t<Material NumberOfProperties=\"%i\">\n",mat->mNumProperties); for (unsigned int n = 0; n < mat->mNumProperties;++n) { const aiMaterialProperty* prop = mat->mProperties[n]; const char* sz = ""; if (prop->mType == aiPTI_Float) sz = "float"; else if (prop->mType == aiPTI_Integer) sz = "integer"; else if (prop->mType == aiPTI_String) sz = "string"; else if (prop->mType == aiPTI_Buffer) sz = "binary_buffer"; ::fprintf(out, "\t\t<MatProperty key=\"%s\" \n\t\t\ttype=\"%s\" tex_usage=\"%s\" tex_index=\"%i\"", prop->mKey.data, sz, TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex); if (prop->mType == aiPTI_Float) { ::fprintf(out, " size=\"%i\">\n\t\t\t", prop->mDataLength/sizeof(float)); for (unsigned int p = 0; p < prop->mDataLength/sizeof(float);++p) ::fprintf(out,"%f ",*((float*)(prop->mData+p*sizeof(float)))); } else if (prop->mType == aiPTI_Integer) { ::fprintf(out, " size=\"%i\">\n\t\t\t", prop->mDataLength/sizeof(int)); for (unsigned int p = 0; p < prop->mDataLength/sizeof(int);++p) ::fprintf(out,"%i ",*((int*)(prop->mData+p*sizeof(int)))); } else if (prop->mType == aiPTI_Buffer) { ::fprintf(out, " size=\"%i\">\n\t\t\t", prop->mDataLength); for (unsigned int p = 0; p < prop->mDataLength;++p) { ::fprintf(out,"%2x ",prop->mData[p]); if (p && 0 == p%30) ::fprintf(out,"\n\t\t\t"); } } else if (prop->mType == aiPTI_String) { ::fprintf(out,">\n\t\t\t\"%s\"",prop->mData+4 /* skip length */); } ::fprintf(out,"\n\t\t</MatProperty>\n"); } ::fprintf(out,"\t</Material>\n"); } // write animations for (unsigned int i = 0; i < scene->mNumAnimations;++i) { aiAnimation* anim = scene->mAnimations[i]; // anim header ConvertName(name,anim->mName); ::fprintf(out,"\t<Animation name=\"%s\">\n" "\t\t<Integer name=\"num_chan\" > %i </Integer>\n" "\t\t<Float name=\"duration\" > %e </Float>\n" "\t\t<Float name=\"tick_cnt\" > %e </Float>\n", name.data, anim->mNumChannels,anim->mDuration, anim->mTicksPerSecond); // write bone animation channels for (unsigned int n = 0; n < anim->mNumChannels;++n) { aiNodeAnim* nd = anim->mChannels[n]; // node anim header ConvertName(name,nd->mNodeName); ::fprintf(out,"\t\t<Channel node=\"%s\">\n" "\t\t\t<Integer name=\"num_pos_keys\" > %i </Integer>\n" "\t\t\t<Integer name=\"num_scl_keys\" > %i </Integer>\n" "\t\t\t<Integer name=\"num_rot_keys\" > %i </Integer>\n", name.data,nd->mNumPositionKeys,nd->mNumScalingKeys,nd->mNumRotationKeys); if (!shortened) { // write position keys for (unsigned int a = 0; a < nd->mNumPositionKeys;++a) { aiVectorKey* vc = nd->mPositionKeys+a; ::fprintf(out,"\t\t\t<PositionKey time=\"%e\">\n" "\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t</PositionKey>\n", vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z,a); } // write scaling keys for (unsigned int a = 0; a < nd->mNumScalingKeys;++a) { aiVectorKey* vc = nd->mScalingKeys+a; ::fprintf(out,"\t\t\t<ScalingKey time=\"%e\">\n" "\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t</ScalingKey>\n", vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z,a); } // write rotation keys for (unsigned int a = 0; a < nd->mNumRotationKeys;++a) { aiQuatKey* vc = nd->mRotationKeys+a; ::fprintf(out,"\t\t\t<RotationKey time=\"%e\">\n" "\t\t\t\t%0 8f %0 8f %0 8f %0 8f\n\t\t\t</RotationKey>\n", vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z,vc->mValue.w,a); } } ::fprintf(out,"\t\t</Channel>\n",n); } ::fprintf(out,"\t</Animation>\n",i); } // write meshes for (unsigned int i = 0; i < scene->mNumMeshes;++i) { aiMesh* mesh = scene->mMeshes[i]; const unsigned int width = (unsigned int)log10((double)mesh->mNumVertices)+1; // mesh header ::fprintf(out,"\t<Mesh types=\"%s %s %s %s\">\n" "\t\t<Integer name=\"num_verts\" > %i </Integer>\n" "\t\t<Integer name=\"num_faces\" > %i </Integer>\n", (mesh->mPrimitiveTypes & aiPrimitiveType_POINT ? "points" : ""), (mesh->mPrimitiveTypes & aiPrimitiveType_LINE ? "lines" : ""), (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE ? "triangles" : ""), (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON ? "polygons" : ""), mesh->mNumVertices,mesh->mNumFaces); // bones for (unsigned int n = 0; n < mesh->mNumBones;++n) { aiBone* bone = mesh->mBones[n]; ConvertName(name,bone->mName); // bone header ::fprintf(out,"\t\t<Bone name=\"%s\">\n" "\t\t\t<Matrix4 name=\"offset\" > \n" "\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" "\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" "\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" "\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" "\t\t\t</Matrix4> \n" "\t\t\t<Integer name=\"num_weights\" > %i </Integer>\n", name.data, bone->mOffsetMatrix.a1,bone->mOffsetMatrix.a2,bone->mOffsetMatrix.a3,bone->mOffsetMatrix.a4, bone->mOffsetMatrix.b1,bone->mOffsetMatrix.b2,bone->mOffsetMatrix.b3,bone->mOffsetMatrix.b4, bone->mOffsetMatrix.c1,bone->mOffsetMatrix.c2,bone->mOffsetMatrix.c3,bone->mOffsetMatrix.c4, bone->mOffsetMatrix.d1,bone->mOffsetMatrix.d2,bone->mOffsetMatrix.d3,bone->mOffsetMatrix.d4, bone->mNumWeights); if (!shortened) { // bone weights for (unsigned int a = 0; a < bone->mNumWeights;++a) { aiVertexWeight* wght = bone->mWeights+a; ::fprintf(out,"\t\t\t<VertexWeight index=\"%i\">\n\t\t\t\t%f\n\t\t\t</VertexWeight>\n", wght->mVertexId,wght->mWeight); } } ::fprintf(out,"\t\t</Bone>\n",n); } // faces if (!shortened) { for (unsigned int n = 0; n < mesh->mNumFaces; ++n) { aiFace& f = mesh->mFaces[n]; ::fprintf(out,"\t\t<Face num_indices=\"%i\">\n" "\t\t\t",f.mNumIndices); for (unsigned int j = 0; j < f.mNumIndices;++j) ::fprintf(out,"%i ",f.mIndices[j]); ::fprintf(out,"\n\t\t</Face>\n"); } } // vertex positions if (mesh->HasPositions()) { ::fprintf(out,"\t\t<Positions> \n"); if (!shortened) { for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { ::fprintf(out,"\t\t%0 8f %0 8f %0 8f\n", mesh->mVertices[n].x, mesh->mVertices[n].y, mesh->mVertices[n].z); } } else { } ::fprintf(out,"\t\t</Positions>\n"); } // vertex normals if (mesh->HasNormals()) { ::fprintf(out,"\t\t<Normals> \n"); if (!shortened) { for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { ::fprintf(out,"\t\t%0 8f %0 8f %0 8f\n", mesh->mNormals[n].x, mesh->mNormals[n].y, mesh->mNormals[n].z); } } else { } ::fprintf(out,"\t\t</Normals>\n"); } // vertex tangents and bitangents if (mesh->HasTangentsAndBitangents()) { ::fprintf(out,"\t\t<Tangents> \n"); if (!shortened) { for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { ::fprintf(out,"\t\t%0 8f %0 8f %0 8f \t %0 8f %0 8f %0 8f\n", mesh->mTangents[n].x, mesh->mTangents[n].y, mesh->mTangents[n].z, mesh->mBitangents[n].x, mesh->mBitangents[n].y, mesh->mBitangents[n].z); } } else { } ::fprintf(out,"\t\t</Tangents>\n"); } // texture coordinates for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { if (!mesh->mTextureCoords[a]) break; ::fprintf(out,"\t\t<TextureCoords set=\"%i\" num_components=\"%i\"> \n",a,mesh->mNumUVComponents[a]); if (!shortened) { for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { ::fprintf(out,"\t\t%0 8f %0 8f %0 8f\n", mesh->mTextureCoords[a][n].x, mesh->mTextureCoords[a][n].y, mesh->mTextureCoords[a][n].z); } } else { } ::fprintf(out,"\t\t</TextureCoords>\n"); } // vertex colors for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a) { if (!mesh->mColors[a]) break; //::fprintf(out,"\t\t<Colors set=\"%i\"> \n",a); if (!shortened) { for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { ::fprintf(out,"\t\t%0 8f %0 8f %0 8f %0 8f\n", mesh->mColors[a][n].r, mesh->mColors[a][n].g, mesh->mColors[a][n].b, mesh->mColors[a][n].a); } } else { } ::fprintf(out,"\t\t</Color>\n"); } ::fprintf(out,"\t</Mesh>\n"); } ::fprintf(out,"</Scene>\n</ASSIMP>"); }
// ----------------------------------------------------------------------------------- // 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, aiGetVersionMajorTest ) { EXPECT_EQ( aiGetVersionMajor(), 4U ); }