I want to improve the serialization time of my 3D application. I use the following scene for testing: https://www.dropbox.com/scl/fi/j8ays9phm2xs45icla4bo/TestScene.zip?rlkey=qy8jpwgz3s8b95mz62l8axcug&dl=0
I did a performance comparison with Blender and 3DS Max.
Blender: 1 second
3DS max: 2 seconds
My application: 15 seconds !!
To serialize meshes I use the OBJ file format and Assimp.
The Assimp serialization time is too high.
Should I write my own format? Is there any tricks I should know about?
Thank you. For convenience here my serialization code:
aiScene* scene = new aiScene();
// Allocate materials memory
scene->mNumMaterials = 1;
scene->mMaterials = new aiMaterial*[scene->mNumMaterials];
// Allocate mesh memory
scene->mNumMeshes = (unsigned)m_flatMeshContainer.size();
scene->mMeshes = new aiMesh*[m_flatMeshContainer.size()];
scene->mRootNode = new aiNode();
scene->mRootNode->mNumMeshes = 0;
// Create materials
for (Uint32 i = 0u; i < scene->mNumMaterials; ++i)
{
scene->mMaterials[i] = new aiMaterial();
}
// Create meshes
std::mutex mtx;
tbb::parallel_for(size_t(0), m_meshGroupIdentifiers.size(), [&](size_t idx) {
const auto& groupId = m_meshGroupIdentifiers[idx];
const auto group = getMeshGroupPtr_FromEntity(groupId);
// Create meshes
const auto nbMeshes = (unsigned)group->m_meshes.size();
aiNode* node = new aiNode();
node->mMeshes = new unsigned int[nbMeshes];
node->mNumMeshes = nbMeshes;
for (Uint32 i = 0u; i < nbMeshes; ++i)
{
// Init mesh
const Mesh* nativeMesh = group->m_meshes[i];
const auto flatMeshIdx = nativeMesh->getFlatId();
scene->mMeshes[flatMeshIdx] = new aiMesh();
node->mMeshes[i] = flatMeshIdx;
aiMesh* mesh = scene->mMeshes[flatMeshIdx];
mesh->mName = group->getName();
mesh->mMaterialIndex = 0;
// Build vertices
const auto& vertices = nativeMesh->getRealVertices();
const auto nbVertex = (unsigned)vertices.size();
mesh->mVertices = new aiVector3D[nbVertex];
mesh->mNormals = new aiVector3D[nbVertex];
mesh->mNumVertices = nbVertex;
mesh->mTextureCoords[0] = new aiVector3D[nbVertex];
mesh->mNumUVComponents[0] = nbVertex;
for (Uint32 j = 0u; j < nbVertex; ++j)
{
const auto& vtx = vertices[j];
mesh->mVertices[j] = aiVector3D(vtx.position.x, vtx.position.y, vtx.position.z);
mesh->mNormals[j] = aiVector3D(vtx.normal.x, vtx.normal.y, vtx.normal.z);
mesh->mTextureCoords[0][j] = aiVector3D(vtx.texCoord.x, vtx.texCoord.y, 0);
}
// Build faces
const auto& indices = nativeMesh->getRealIndices();
mesh->mNumFaces = (unsigned)indices.size() / PRIMITIVE_NB_VTX;
mesh->mFaces = new aiFace[mesh->mNumFaces];
for (Uint32 j = 0u; j < indices.size(); j += PRIMITIVE_NB_VTX)
{
aiFace &face = mesh->mFaces[j / PRIMITIVE_NB_VTX];
face.mIndices = new unsigned int[PRIMITIVE_NB_VTX];
face.mNumIndices = PRIMITIVE_NB_VTX;
for (Uint32 k = 0; k < PRIMITIVE_NB_VTX; ++k)
{
face.mIndices[k] = indices[k + j];
}
}
}
std::lock_guard<std::mutex> lock(mtx);
scene->mRootNode->addChildren(1, &node);
});
const auto objPath = m_serializationFullPath.string();
Assimp::Exporter exporter;
// HERE : SLOW --------------------------------------------------------------------------------------------
exporter.Export(scene, "obj", objPath);
// ---------------------------------------------------------------------------------------------------------
delete scene;
I solved it by implementing my own binary file format.
For writing to the file i use:
std::ofstream fileStream(filePath, std::ios::out | std::ios::binary)
for reading:
std::ifstream fileStream(filePath, std::ios::out | std::ios::binary);
Here good examples: https://www.tutorialspoint.com/reading-and-writing-binary-file-in-c-cplusplus#:~:text=To%20write%20a%20binary%20file,the%20end%20of%20the%20file.