Skip to content

File meshobj_to_pointcloudobj.cpp

File List > apps > mesh_to_pointcloud > meshobj_to_pointcloudobj.cpp

Go to the documentation of this file

#include <fstream>
#include <iostream>

#include "argos/serializer/ObjSerializer.h"
#include "argos/mesh/Mesh.h"



using namespace Argos;



std::vector<Vector3D<double>> naiveSample(const Mesh& mesh) {
    const std::vector<Vertex>& vertices = mesh.getVertices();
    std::vector<Vector3D<double>> points;
    points.reserve(vertices.size());
    for (const Vertex& v : vertices) {
        points.push_back(v.getPosition());
    }

    return points;
}



std::vector<Vector3D<double>> sampleMeshSurface(const Mesh& mesh, std::size_t pointCount) {
    std::vector<Vector3D<double>> points;
    points.reserve(pointCount);

    const auto& faces = mesh.getFaces();
    if (faces.empty())
        return points;

    for (std::size_t i = 0; i < pointCount; ++i) {

        // 1. Choix al�atoire d�une face
        const Face& face = faces[rand() % faces.size()];
        //std::cout << "Sampling point " << i << " on face with " << face.getVertices().size() << " vertices." << std::endl; // DEBUG

        const auto& vertexIndices = face.getIndices();
        if (vertexIndices.size() < 3)
            continue;

        std::vector<Vertex> vertices;
        for (auto& idx : vertexIndices) {
            vertices.push_back(mesh.getVertices()[idx]);
        }


        // 2. Triangulation (en �ventail (fan triangulation))
        std::size_t triIndex = 1 + rand() % (vertices.size() - 2);

        const Vector3D<double>& A = vertices[0].getPosition();
        const Vector3D<double>& B = vertices[triIndex].getPosition();
        const Vector3D<double>& C = vertices[triIndex + 1].getPosition();

        // 3. Coordonn�es barycentriques al�atoires
        float u = static_cast<float>(rand()) / RAND_MAX;
        float v = static_cast<float>(rand()) / RAND_MAX;


        if (u + v > 1.0f) {
            u = 1.0f - u;
            v = 1.0f - v;
        }

        float alpha = 1.0f - u - v;
        float beta = u;
        float gamma = v;

        //std::cout << "Barycentric coords: alpha=" << alpha << ", beta=" << beta << ", gamma=" << gamma << std::endl; // DEBUG

        // 4. Construction du point
        Vector3D<double> P = A * alpha + B * beta + C * gamma;

        //std::cout << "   -> Result : " << P << std::endl; // DEBUG

        points.push_back(P);
    }

    return points;
}



std::vector<Face> convertFaces(const std::vector<int>& faces, const std::vector<int>& offsets) {
    std::vector<Face> faces_convert;

    std::vector<int> indices;

    for (int j = 0; j < offsets.size(); j++) {
        int fin;
        if (j == offsets.size()-1) {
            fin = faces.size();
        }
        else {
            fin = offsets[j + 1];
        }

        for (int i = offsets[j]; i < fin; i++) {
            indices.push_back(faces[i]);
        }

        faces_convert.emplace_back(indices);

        indices.clear();
    }

    return faces_convert;
};


std::vector<Vertex> convertVertices(std::vector<Vector3D<double>> vectors3D) {
    std::vector<Vertex> newVertices;
    for (Vector3D<double> vec : vectors3D) {
        newVertices.push_back(Vertex(vec));
    }

    return newVertices;
}







int main(int argc, char* argv[]) {
    if (argc != 3) {
        std::cout << "ERREUR : PAS ASSEZ D'ARGUMENTS (2 ou 3 attendus):" << std::endl;
        std::cout << "  -Arg1 : fichier OBJ en entree ou vont etre lu les sommets et faces" << std::endl;
        std::cout << "  -Arg2 : nombre de points genere par le surface sampling" << std::endl;
        return -1;
    }

    ObjSerializer serializer = ObjSerializer();
    std::vector<Vector3D<double>> vertices;
    std::vector<int> faces;
    std::vector<int> offsets;

    try {
        std::ifstream file(argv[0]);

        serializer.deserialize(vertices, faces, offsets, file);

        file.close();
    }
    catch (const std::runtime_error& e) {
        return 0;
    }


    std::vector<Face> newFaces = convertFaces(faces, offsets);

    std::vector<Vertex> newVertices = convertVertices(vertices);



    Mesh mesh = Mesh(newVertices, newFaces);


    std::vector<Vector3D<double>> pointCloudNaive = naiveSample(mesh);
    std::vector<Vector3D<double>> pointCloudSurface = sampleMeshSurface(mesh, std::stoi(argv[2]));

    try {
        std::ofstream fileNaive("naive.obj");
        std::ofstream fileSampling("naive.obj");

        serializer.serialize(pointCloudNaive, std::vector<int>(), std::vector<int>(), fileNaive);
        serializer.serialize(pointCloudSurface, std::vector<int>(), std::vector<int>(), fileSampling);

        fileNaive.close();
        fileSampling.close();
    }
    catch (const std::runtime_error& e) {
        return 0;
    }

    return 0;
}