Example #1
0
void PLYDataWriter::write_header(p_ply oply)
{
    ply_add_element ( oply, "vertex", mesh->vertex_count() );
    ply_add_scalar_property(oply, "x", PLY_FLOAT );
    ply_add_scalar_property(oply, "y", PLY_FLOAT );
    ply_add_scalar_property(oply, "z", PLY_FLOAT );

    ply_add_element ( oply, "face", mesh->face_count() );
    ply_add_list_property ( oply, "vertex_index", PLY_UCHAR, PLY_INT );
    ply_write_header ( oply );
}
Example #2
0
bool WritePlyFile(const std::string &filename, int nTriangles,
                  const int *vertexIndices, int nVertices, const Point3f *P,
                  const Vector3f *S, const Normal3f *N, const Point2f *UV) {
    p_ply plyFile =
        ply_create(filename.c_str(), PLY_DEFAULT, PlyErrorCallback, 0, nullptr);
    if (plyFile != nullptr) {
        ply_add_element(plyFile, "vertex", nVertices);
        ply_add_scalar_property(plyFile, "x", PLY_FLOAT);
        ply_add_scalar_property(plyFile, "y", PLY_FLOAT);
        ply_add_scalar_property(plyFile, "z", PLY_FLOAT);
        if (N != nullptr) {
            ply_add_scalar_property(plyFile, "nx", PLY_FLOAT);
            ply_add_scalar_property(plyFile, "ny", PLY_FLOAT);
            ply_add_scalar_property(plyFile, "nz", PLY_FLOAT);
        }
        if (UV != nullptr) {
            ply_add_scalar_property(plyFile, "u", PLY_FLOAT);
            ply_add_scalar_property(plyFile, "v", PLY_FLOAT);
        }
        if (S != nullptr)
            Warning("PLY mesh in \"%s\" will be missing tangent vectors \"S\".",
                    filename.c_str());

        ply_add_element(plyFile, "face", nTriangles);
        ply_add_list_property(plyFile, "vertex_indices", PLY_UINT8, PLY_INT);
        ply_write_header(plyFile);

        for (int i = 0; i < nVertices; ++i) {
            ply_write(plyFile, P[i].x);
            ply_write(plyFile, P[i].y);
            ply_write(plyFile, P[i].z);
            if (N) {
                ply_write(plyFile, N[i].x);
                ply_write(plyFile, N[i].y);
                ply_write(plyFile, N[i].z);
            }
            if (UV) {
                ply_write(plyFile, UV[i].x);
                ply_write(plyFile, UV[i].y);
            }
        }

        for (int i = 0; i < nTriangles; ++i) {
            ply_write(plyFile, 3);
            ply_write(plyFile, vertexIndices[3 * i]);
            ply_write(plyFile, vertexIndices[3 * i + 1]);
            ply_write(plyFile, vertexIndices[3 * i + 2]);
        }
        ply_close(plyFile);
        return true;
    }
    return false;
}
Example #3
0
void PlyWriter::done(PointTableRef table)
{
    if (!ply_add_element(m_ply, "vertex", m_pointCollector->size()))
    {
        std::stringstream ss;
        ss << "Could not add vertex element";
        throw pdal_error(ss.str());
    }
    auto dimensions = table.layout()->dims();
    for (auto dim : dimensions) {
        std::string name = Dimension::name(dim);
        e_ply_type plyType = getPlyType(Dimension::defaultType(dim));
        if (!ply_add_scalar_property(m_ply, name.c_str(), plyType))
        {
            std::stringstream ss;
            ss << "Could not add scalar property '" << name << "'";
            throw pdal_error(ss.str());
        }
    }
    if (!ply_add_comment(m_ply, "Generated by PDAL"))
    {
        std::stringstream ss;
        ss << "Could not add comment";
        throw pdal_error(ss.str());
    }
    if (!ply_write_header(m_ply))
    {
        std::stringstream ss;
        ss << "Could not write ply header";
        throw pdal_error(ss.str());
    }

    for (PointId index = 0; index < m_pointCollector->size(); ++index)
    {
        for (auto dim : dimensions)
        {
            double value = m_pointCollector->getFieldAs<double>(dim, index);
            if (!ply_write(m_ply, value))
            {
                std::stringstream ss;
                ss << "Error writing dimension '" << Dimension::name(dim) <<
                    "' of point number " << index;
                throw pdal_error(ss.str());
            }
        }
    }

    if (!ply_close(m_ply))
    {
        throw pdal_error("Error closing ply file");
    }
}
Example #4
0
void write_ply(const std::string &filename, const MatrixXu &F,
               const MatrixXf &V, const MatrixXf &N, const MatrixXf &Nf, const MatrixXf &UV,
               const MatrixXf &C, const ProgressCallback &progress) {
    auto message_cb = [](p_ply ply, const char *msg) {
        cerr << "rply: " << msg << endl;
    };

    Timer<> timer;
    cout << "Writing \"" << filename << "\" (V=" << V.cols()
         << ", F=" << F.cols() << ") .. ";
    cout.flush();

    if (N.size() > 0 && Nf.size() > 0)
        throw std::runtime_error("Please specify either face or vertex normals but not both!");

    p_ply ply = ply_create(filename.c_str(), PLY_DEFAULT, message_cb, 0, nullptr);
    if (!ply)
        throw std::runtime_error("Unable to write PLY file!");

    ply_add_comment(ply, "Generated by Instant Meshes");
    ply_add_element(ply, "vertex", V.cols());
    ply_add_scalar_property(ply, "x", PLY_FLOAT);
    ply_add_scalar_property(ply, "y", PLY_FLOAT);
    ply_add_scalar_property(ply, "z", PLY_FLOAT);

    if (N.size() > 0) {
        ply_add_scalar_property(ply, "nx", PLY_FLOAT);
        ply_add_scalar_property(ply, "ny", PLY_FLOAT);
        ply_add_scalar_property(ply, "nz", PLY_FLOAT);
        if (N.cols() != V.cols() || N.rows() != 3)
            throw std::runtime_error("Vertex normal matrix has incorrect size");
    }

    if (UV.size() > 0) {
        ply_add_scalar_property(ply, "u", PLY_FLOAT);
        ply_add_scalar_property(ply, "v", PLY_FLOAT);
        if (UV.cols() != V.cols() || UV.rows() != 2)
            throw std::runtime_error("Texture coordinate matrix has incorrect size");
    }

    if (C.size() > 0) {
        ply_add_scalar_property(ply, "red", PLY_FLOAT);
        ply_add_scalar_property(ply, "green", PLY_FLOAT);
        ply_add_scalar_property(ply, "blue", PLY_FLOAT);
        if (C.cols() != V.cols() || (C.rows() != 3 && C.rows() != 4))
            throw std::runtime_error("Color matrix has incorrect size");
    }

    /* Check for irregular faces */
    std::map<uint32_t, std::pair<uint32_t, std::map<uint32_t, uint32_t>>> irregular;
    size_t nIrregular = 0;
    if (F.rows() == 4) {
        for (uint32_t f=0; f<F.cols(); ++f) {
            if (F(2, f) == F(3, f)) {
                nIrregular++;
                auto &value = irregular[F(2, f)];
                value.first = f;
                value.second[F(0, f)] = F(1, f);
            }
        }
    }

    ply_add_element(ply, "face", F.cols() - nIrregular + irregular.size());
    ply_add_list_property(ply, "vertex_indices", PLY_UINT8, PLY_INT);
    if (Nf.size() > 0) {
        ply_add_scalar_property(ply, "nx", PLY_FLOAT);
        ply_add_scalar_property(ply, "ny", PLY_FLOAT);
        ply_add_scalar_property(ply, "nz", PLY_FLOAT);
        if (Nf.cols() != F.cols() || Nf.rows() != 3)
            throw std::runtime_error("Face normal matrix has incorrect size");
    }
    ply_write_header(ply);

    for (uint32_t j=0; j<V.cols(); ++j) {
        for (uint32_t i=0; i<V.rows(); ++i)
            ply_write(ply, V(i, j));
        if (N.size() > 0) {
            for (uint32_t i=0; i<N.rows(); ++i)
                ply_write(ply, N(i, j));
        }
        if (UV.size() > 0) {
            for (uint32_t i=0; i<UV.rows(); ++i)
                ply_write(ply, UV(i, j));
        }
        if (C.size() > 0) {
            for (uint32_t i=0; i<std::min(3u, (uint32_t) C.rows()); ++i)
                ply_write(ply, C(i, j));
        }
        if (progress && j % 500000 == 0)
            progress("Writing vertex data", j / (Float) V.cols());
    }

    for (uint32_t f=0; f<F.cols(); ++f) {
        if (F.rows() == 4 && F(2, f) == F(3, f))
            continue;
        ply_write(ply, F.rows());
        for (uint32_t i=0; i<F.rows(); ++i)
            ply_write(ply, F(i, f));
        if (Nf.size() > 0) {
            for (uint32_t i=0; i<Nf.rows(); ++i)
                ply_write(ply, Nf(i, f));
        }
        if (progress && f % 500000 == 0)
            progress("Writing face data", f / (Float) F.cols());
    }

    for (auto item : irregular) {
        auto face = item.second;
        uint32_t v = face.second.begin()->first, first = v;
        ply_write(ply, face.second.size());
        while (true) {
            ply_write(ply, v);
            v = face.second[v];
            if (v == first)
                break;
        }
        if (Nf.size() > 0) {
            for (uint32_t i=0; i<Nf.rows(); ++i)
                ply_write(ply, Nf(i, face.first));
        }
    }

    ply_close(ply);
    cout << "done. (";
    if (irregular.size() > 0)
        cout << irregular.size() << " irregular faces, ";
    cout << "took " << timeString(timer.value()) << ")" << endl;
}