Skip to content

Commit

Permalink
[mesh] use assimp for save also
Browse files Browse the repository at this point in the history
  • Loading branch information
servantftechnicolor committed Jul 5, 2021
1 parent 4c5450f commit 8329e3b
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 65 deletions.
16 changes: 8 additions & 8 deletions src/aliceVision/mesh/Mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2270,6 +2270,10 @@ bool Mesh::loadFromObjAscii(const std::string& objAsciiFileName)
trisUvIds.clear();
_trisMtlIds.clear();
_colors.clear();
nmtls = 0;
uvCoords.clear();
normals.clear();
pointsVisibilities.clear();

std::ifstream in(objAsciiFileName.c_str());
if (!in.fail())
Expand Down Expand Up @@ -2357,6 +2361,8 @@ bool Mesh::loadFromObjAscii(const std::string& objAsciiFileName)
Voxel nid;
Voxel uvids;

triangle.alive = true;

if (face.mNumIndices != 3)
{
continue;
Expand All @@ -2382,11 +2388,8 @@ bool Mesh::loadFromObjAscii(const std::string& objAsciiFileName)

tris.push_back(triangle);
_trisMtlIds.push_back(mesh->mMaterialIndex);

if (mesh->HasTextureCoords(0))
{
trisUvIds.push_back(uvids);
}
trisUvIds.push_back(uvids);


if (mesh->HasNormals())
{
Expand All @@ -2403,9 +2406,6 @@ bool Mesh::loadFromObjAscii(const std::string& objAsciiFileName)
if (node == nullptr) continue;
}

std::cout << tris.size() << std::endl;
std::cout << pts.size() << std::endl;

return true;
}

Expand Down
152 changes: 95 additions & 57 deletions src/aliceVision/mesh/Texturing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@

#include <boost/algorithm/string/case_conv.hpp>

#include <assimp/Exporter.hpp>
#include <assimp/scene.h>

#include <map>
#include <set>

Expand Down Expand Up @@ -948,77 +951,112 @@ void Texturing::saveAsOBJ(const bfs::path& dir, const std::string& basename, ima
std::string mtlName = (basename + ".mtl");
std::string mtlFilename = (dir / mtlName).string();

// create .OBJ file
FILE* fobj = fopen(objFilename.c_str(), "w");

// header
fprintf(fobj, "# \n");
fprintf(fobj, "# Wavefront OBJ file\n");
fprintf(fobj, "# Created with AliceVision\n");
fprintf(fobj, "# \n");
fprintf(fobj, "mtllib %s\n\n", mtlName.c_str());
fprintf(fobj, "g TexturedMesh\n");
if (_atlases.size() == 0)
{
return;
}

// write vertices
auto vertices = mesh->pts;
for(int i = 0; i < vertices.size(); ++i)
fprintf(fobj, "v %f %f %f\n", vertices[i].x, vertices[i].y, vertices[i].z);
aiScene scene;

scene.mRootNode = new aiNode;

// write UV coordinates
for(int i=0; i < mesh->uvCoords.size(); ++i)
fprintf(fobj, "vt %f %f\n", mesh->uvCoords[i].x, mesh->uvCoords[i].y);
scene.mMeshes = new aiMesh*[_atlases.size()];
scene.mNumMeshes = _atlases.size();
scene.mRootNode->mMeshes = new unsigned int[_atlases.size()];
scene.mRootNode->mNumMeshes = _atlases.size();
scene.mMaterials = new aiMaterial*[_atlases.size()];
scene.mNumMaterials = _atlases.size();

// write faces per texture atlas
for(std::size_t atlasId=0; atlasId < _atlases.size(); ++atlasId)
{
const std::size_t textureId = 1001 + atlasId; // starts at '1001' for UDIM compatibility
fprintf(fobj, "usemtl TextureAtlas_%i\n", textureId);
for(std::size_t atlasId = 0; atlasId < _atlases.size(); ++atlasId)
{
// starts at '1001' for UDIM compatibility
const std::size_t textureId = 1001 + atlasId;
const std::string texturePath = "texture_" + std::to_string(textureId) + "." + imageIO::EImageFileType_enumToString(textureFileType);

//Set material for this atlas
aiVector3D valcolor(0.6, 0.6, 0.6);
aiVector3D valspecular(0.0, 0.0, 0.0);
double shininess = 0.0;
aiString texFile(texturePath);
aiString texName(std::to_string(textureId));

scene.mMaterials[atlasId] = new aiMaterial;
scene.mMaterials[atlasId]->AddProperty(&valcolor, 1, AI_MATKEY_COLOR_AMBIENT);
scene.mMaterials[atlasId]->AddProperty(&valcolor, 1, AI_MATKEY_COLOR_DIFFUSE);
scene.mMaterials[atlasId]->AddProperty(&valspecular, 1, AI_MATKEY_COLOR_SPECULAR);
scene.mMaterials[atlasId]->AddProperty(&shininess, 1, AI_MATKEY_SHININESS);
scene.mMaterials[atlasId]->AddProperty(&texFile, AI_MATKEY_TEXTURE_DIFFUSE(0));
scene.mMaterials[atlasId]->AddProperty(&texName, AI_MATKEY_NAME);

scene.mRootNode->mMeshes[atlasId] = atlasId;
scene.mMeshes[atlasId] = new aiMesh;
aiMesh * aimesh = scene.mMeshes[atlasId];
aimesh->mMaterialIndex = atlasId;
aimesh->mNumUVComponents[0] = 2;


//Assimp does not allow vertex indices different from uv indices
//So we need to group and duplicate
std::map<std::pair<int, int>, int> unique_pairs;
for(const auto triangleID : _atlases[atlasId])
{
// vertex IDs
int vertexID1 = mesh->tris[triangleID].v[0];
int vertexID2 = mesh->tris[triangleID].v[1];
int vertexID3 = mesh->tris[triangleID].v[2];
for (int k = 0; k < 3; k++)
{
int vertexId = mesh->tris[triangleID].v[k];
int uvId = mesh->trisUvIds[triangleID].m[k];

int uvID1 = mesh->trisUvIds[triangleID].m[0];
int uvID2 = mesh->trisUvIds[triangleID].m[1];
int uvID3 = mesh->trisUvIds[triangleID].m[2];
std::pair<int, int> p = std::make_pair(vertexId, uvId);
unique_pairs[p] = -1;
}
}

aimesh->mNumVertices = unique_pairs.size();
aimesh->mVertices = new aiVector3D[unique_pairs.size()];
aimesh->mTextureCoords[0] = new aiVector3D[unique_pairs.size()];

fprintf(fobj, "f %i/%i %i/%i %i/%i\n", vertexID1 + 1, uvID1 + 1, vertexID2 + 1, uvID2 + 1, vertexID3 + 1, uvID3 + 1); // indexed from 1
int index = 0;
for (auto & p : unique_pairs)
{
int vertexId = p.first.first;
int uvId = p.first.second;

aimesh->mVertices[index].x = mesh->pts[vertexId].x;
aimesh->mVertices[index].y = mesh->pts[vertexId].y;
aimesh->mVertices[index].z = mesh->pts[vertexId].z;

aimesh->mTextureCoords[0][index].x = mesh->uvCoords[uvId].x;
aimesh->mTextureCoords[0][index].y = mesh->uvCoords[uvId].y;
aimesh->mTextureCoords[0][index].z = 0.0;

p.second = index;

index++;
}
}
fclose(fobj);

// create .MTL material file
FILE* fmtl = fopen(mtlFilename.c_str(), "w");
aimesh->mNumFaces = _atlases[atlasId].size();
aimesh->mFaces = new aiFace[aimesh->mNumFaces];

// header
fprintf(fmtl, "# \n");
fprintf(fmtl, "# Wavefront material file\n");
fprintf(fmtl, "# Created with AliceVision\n");
fprintf(fmtl, "# \n\n");
for(int i = 0; i < _atlases[atlasId].size(); i++)
{
int triangleId = _atlases[atlasId][i];

// for each atlas, create a new material with associated texture
for(size_t atlasId=0; atlasId < _atlases.size(); ++atlasId)
{
const std::size_t textureId = 1001 + atlasId; // starts at '1001' for UDIM compatibility
const std::string textureName = "texture_" + std::to_string(textureId) + "." + imageIO::EImageFileType_enumToString(textureFileType);

fprintf(fmtl, "newmtl TextureAtlas_%i\n", textureId);
fprintf(fmtl, "Ka 0.6 0.6 0.6\n");
fprintf(fmtl, "Kd 0.6 0.6 0.6\n");
fprintf(fmtl, "Ks 0.0 0.0 0.0\n");
fprintf(fmtl, "d 1.0\n");
fprintf(fmtl, "Ns 0.0\n");
fprintf(fmtl, "illum 2\n");
fprintf(fmtl, "map_Kd %s\n", textureName.c_str());
aimesh->mFaces[i].mNumIndices = 3;
aimesh->mFaces[i].mIndices = new unsigned int[3];

for (int k = 0; k < 3; k++)
{
int vertexId = mesh->tris[triangleId].v[k];
int uvId = mesh->trisUvIds[triangleId].m[k];

std::pair<int, int> p = std::make_pair(vertexId, uvId);
aimesh->mFaces[i].mIndices[k] = unique_pairs[p];
}
}
}
fclose(fmtl);

ALICEVISION_LOG_INFO("Writing done: " << std::endl
<< "\t- obj file: " << objFilename << std::endl
<< "\t- mtl file: " << mtlFilename);
}
Assimp::Exporter exporter;
exporter.Export(&scene, "obj", objFilename);

} // namespace mesh
} // namespace aliceVision

0 comments on commit 8329e3b

Please sign in to comment.