From c520f4d9de42b65153ca60bec2a3ebddf3f348a6 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Fri, 18 Jun 2021 12:45:17 +0200 Subject: [PATCH] first draft nexus exporter --- src/external/nexus | 2 +- src/meshlabplugins/io_nxs/io_nxs.cpp | 134 +++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 1 deletion(-) diff --git a/src/external/nexus b/src/external/nexus index 8f507ed59..f15c1a0b2 160000 --- a/src/external/nexus +++ b/src/external/nexus @@ -1 +1 @@ -Subproject commit 8f507ed591c9edaeb0e31a9b8950ed64cfade507 +Subproject commit f15c1a0b24e402a61622395cf46da44e5291278c diff --git a/src/meshlabplugins/io_nxs/io_nxs.cpp b/src/meshlabplugins/io_nxs/io_nxs.cpp index be2f1cbc4..2a3f4c4db 100644 --- a/src/meshlabplugins/io_nxs/io_nxs.cpp +++ b/src/meshlabplugins/io_nxs/io_nxs.cpp @@ -24,6 +24,12 @@ #include #include "io_nxs.h" +#include +#include +#include +#include +#include + QString IONXSPlugin::pluginName() const { return "IONXS"; @@ -79,7 +85,135 @@ void IONXSPlugin::save( vcg::CallBackPos*) { if (fileFormat.toUpper() == "NXS"){ + int node_size = 1<<15; + int top_node_size = 4096; + float vertex_quantization = 0.0f; //optionally quantize vertices position. + int tex_quality(92); //default jpg texture quality + //QString decimation("quadric"); //simplification method + int ram_buffer(2000); //Mb of ram to use + int n_threads = 4; + float scaling(0.5); //simplification ratio + int skiplevels = 0; + vcg::Point3d origin(0, 0, 0); + bool center = false; + + bool point_cloud = false; + bool normals = false; + bool no_normals = false; + bool colors = false; + bool no_colors = false; + bool no_texcoords = false; + bool useOrigTex = false; + bool create_pow_two_tex = false; + bool deepzoom = false; + + QVariant adaptive(0.333f); + + Stream* stream = nullptr; + VcgLoader* loader = nullptr; + KDTree* tree = nullptr; + try { + quint64 max_memory = (1<<20)*(uint64_t)ram_buffer/4; //hack 4 is actually an estimate... + std::string input = "mesh"; + if (point_cloud) { + input = "pointcloud"; + stream = new StreamCloud("cache_stream"); + } + else + stream = new StreamSoup("cache_stream"); + stream->setVertexQuantization(vertex_quantization); + stream->setMaxMemory(max_memory); + if(center) { + stream->origin = m.cm.bbox.Center(); + } else + stream->origin = origin; + + vcg::Point3d &o = stream->origin; + if(o[0] != 0.0 || o[1] != 0.0 || o[2] != 0.0) { + int lastPoint = fileName.lastIndexOf("."); + QString ref = fileName.left(lastPoint) + ".js"; + QFile file(ref); + if(!file.open(QFile::ReadWrite)) { + throw MLException("Could not save reference file: " + ref); + } + QTextStream stream(&file); + stream.setRealNumberPrecision(12); + stream << "{ \"origin\": [" << o[0] << ", " << o[1] << ", " << o[2] << "] }\n"; + } + + loader = new VcgLoader; + //todo + bool has_colors = false, has_normals = false, has_textures = false; + loader->load(&m.cm, has_colors, has_normals, has_textures); + stream->load(loader); + + quint32 components = 0; + if(!point_cloud) components |= NexusBuilder::FACES; + + if((!no_normals && (!point_cloud || has_normals)) || normals) { + components |= NexusBuilder::NORMALS; + cout << "Normals enabled\n"; + } + if((has_colors && !no_colors ) || colors ) { + components |= NexusBuilder::COLORS; + cout << "Colors enabled\n"; + } + if(has_textures && !no_texcoords) { + components |= NexusBuilder::TEXTURES; + cout << "Textures enabled\n"; + } + + //WORKAROUND to save loading textures not needed + if(!(components & NexusBuilder::TEXTURES)) { + stream->textures.clear(); + } + + NexusBuilder builder(components); + builder.skipSimplifyLevels = skiplevels; + builder.setMaxMemory(max_memory); + builder.n_threads = n_threads; + builder.setScaling(scaling); + builder.useNodeTex = !useOrigTex; + builder.createPowTwoTex = create_pow_two_tex; + if(deepzoom) + builder.header.signature.flags |= nx::Signature::Flags::DEEPZOOM; + builder.tex_quality = tex_quality; + bool success = builder.initAtlas(stream->textures); + if(!success) { + throw MLException("Fail"); + } + if(point_cloud) + tree = new KDTreeCloud("cache_tree", adaptive.toFloat()); + else + tree = new KDTreeSoup("cache_tree", adaptive.toFloat()); + + tree->setMaxMemory((1<<20)*(uint64_t)ram_buffer/2); + KDTreeSoup *treesoup = dynamic_cast(tree); + if(treesoup) + treesoup->setTrianglesPerBlock(node_size); + + KDTreeCloud *treecloud = dynamic_cast(tree); + if(treecloud) + treecloud->setTrianglesPerBlock(node_size); + + builder.create(tree, stream, top_node_size); + builder.save(fileName); + delete tree; + delete loader; + delete stream; + } + catch(QString error) { + delete tree; + delete loader; + delete stream; + throw MLException("Fatal error: " + error); + } catch(const char *error) { + delete tree; + delete loader; + delete stream; + throw MLException("Fatal error: " + QString(error)); + } } else { wrongSaveFormat(fileFormat);