// ----------------------------------------------------------------------------------- uint32_t WriteBinaryScene(const aiScene* scene) { uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AISCENE); // basic scene information len += Write<unsigned int>(scene->mFlags); len += Write<unsigned int>(scene->mNumMeshes); len += Write<unsigned int>(scene->mNumMaterials); len += Write<unsigned int>(scene->mNumAnimations); len += Write<unsigned int>(scene->mNumTextures); len += Write<unsigned int>(scene->mNumLights); len += Write<unsigned int>(scene->mNumCameras); // write node graph len += WriteBinaryNode(scene->mRootNode)+8; // write all meshes for (unsigned int i = 0; i < scene->mNumMeshes;++i) { const aiMesh* mesh = scene->mMeshes[i]; len += WriteBinaryMesh(mesh)+8; } // write materials for (unsigned int i = 0; i< scene->mNumMaterials; ++i) { const aiMaterial* mat = scene->mMaterials[i]; len += WriteBinaryMaterial(mat)+8; } // write all animations for (unsigned int i = 0; i < scene->mNumAnimations;++i) { const aiAnimation* anim = scene->mAnimations[i]; len += WriteBinaryAnim(anim)+8; } // write all textures for (unsigned int i = 0; i < scene->mNumTextures;++i) { const aiTexture* mesh = scene->mTextures[i]; len += WriteBinaryTexture(mesh)+8; } // write lights for (unsigned int i = 0; i < scene->mNumLights;++i) { const aiLight* l = scene->mLights[i]; len += WriteBinaryLight(l)+8; } // write cameras for (unsigned int i = 0; i < scene->mNumCameras;++i) { const aiCamera* cam = scene->mCameras[i]; len += WriteBinaryCamera(cam)+8; } ChangeInteger(old,len); return len; }
// ----------------------------------------------------------------------------------- // Write a single node in a binary dump void WriteBinaryNode(const aiNode* node, FILE* out) { WriteMagic("#ND",out); WriteAiString(node->mName,out); WriteMat4x4(node->mTransformation,out); WriteInteger(node->mNumMeshes,out); for (unsigned int i = 0; i < node->mNumMeshes;++i) WriteInteger(node->mMeshes[i],out); WriteInteger(node->mNumChildren,out); for (unsigned int i = 0; i < node->mNumChildren;++i) WriteBinaryNode(node->mChildren[i],out); }
// ----------------------------------------------------------------------------------- uint32_t WriteBinaryNode(const aiNode* node) { uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AINODE); len += Write<aiString>(node->mName); len += Write<aiMatrix4x4>(node->mTransformation); len += Write<unsigned int>(node->mNumChildren); len += Write<unsigned int>(node->mNumMeshes); for (unsigned int i = 0; i < node->mNumMeshes;++i) { len += Write<unsigned int>(node->mMeshes[i]); } for (unsigned int i = 0; i < node->mNumChildren;++i) { len += WriteBinaryNode(node->mChildren[i])+8; } ChangeInteger(old,len); return len; }
// ----------------------------------------------------------------------------------- // 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); } } }