1
0

wavefront/parse: processing v, vn, vt, o, g

This commit is contained in:
2025-10-08 00:44:02 +03:00
parent 753c21ef11
commit aadd9d8661
9 changed files with 621 additions and 312 deletions

View File

@@ -1,129 +1,124 @@
#include <algorithm>
#include <array>
#include <filesystem>
#include <fstream>
#include <initializer_list>
#include <iostream>
#include <istream>
#include <limits>
#include <optional>
#include <set>
#include <tuple>
#include <variant>
#include <string>
#include <vector>
#include "wavefront.hpp"
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <memory>
#include <stdexcept>
#include <variant>
namespace fs = std::filesystem;
#include "file.hpp"
#include "settings.hpp"
void printUsage() {
std::cout
<< "Usage: parse-wavefront [options] <input.obj>" << std::endl
<< "Options:" << std::endl
<< " --filter-object / -O <name> Filter objects by name (can be used multiple times)" << std::endl
<< " --filter-group / -G <name> Filter groups by name (can be used multiple times)" << std::endl
<< " --output-float-set / -f <file> Output float set to file" << std::endl
<< " --output-position / -p <file> Output positions to file" << std::endl
<< " --output-vertex / -v <file> Output vertices to file" << std::endl
<< " --output-mesh / -m <file> Output mesh to file" << std::endl
<< " --output-normal-file / -n <file> Output normals to file" << std::endl
<< " --output-texcoord-file / -t <file> Output texture coordinates to file" << std::endl
<< " -- Stop processing flags" << std::endl
;
std::cout
<< " <input.obj> Input Wavefront OBJ file" << std::endl
<< "Examples:" << std::endl
<< " parse-wavefront --float64 --output-float-set output.fset --output-position output.pos --filter-object Car,Wheel --filter-group Metal -- model.obj" << std::endl
;
static void usage(const char* prog) {
std::cerr << "Usage: " << prog
<< " [options] <input_file|- for stdin> <output_file|- for stdout>\n"
"Options:\n"
" --float64 output double instead of float\n"
" --object <name> select an object (can be given multiple times)\n"
" --group <name> select a group (can be given multiple times)\n"
" --with-normals extract normal vectors\n"
" --with-texcoords extract texture coordinates\n"
" -- end of options\n";
}
[[noreturn]]
void exitWithError(const std::string& message) {
std::cerr << "Error: " << message << std::endl;
std::exit(1);
}
int main(int argc, char** argv) {
using namespace wavefront::parser;
int main(int argc, char *argv[]) {
std::vector<std::string> selected_objects, selected_groups;
bool process_flags = true;
bool has_input_file = false;
bool has_output_float_set_file = false;
bool has_output_position_file = false;
bool has_output_mesh_file = false;
bool has_output_vertex_file = false;
std::string input_file_path;
for (decltype(argc) i = 1; i < argc; ++i) {
std::string arg = argv[i];
if (!process_flags) {
if (has_input_file) {
std::cerr << "Unexpected argument after the input file: " << arg << std::endl;
printUsage();
return 1;
}
has_input_file = true;
input_file_path = arg;
continue;
}
if (arg == "--filter-object" || arg == "-O") {
if (i + 1 < argc) {
selected_groups.push_back(argv[++i]);
}
} else if (arg == "--filter-group" || arg == "-G") {
if (i + 1 < argc) {
selected_groups.push_back(argv[++i]);
}
} else if (arg == "--") {
process_flags = false;
} else if (arg.starts_with("-")) {
std::cerr << "Unknown option: " << arg << std::endl;
printUsage();
return 1;
} else {
input_file_path = arg;
has_input_file = true;
}
}
if (!has_input_file) {
std::cerr << "No input file specified." << std::endl;
printUsage();
if (argc < 3) {
usage(argv[0]);
return 1;
}
// if (!has_output_float_set_file) {
// std::cerr << "No output float set file specified." << std::endl;
// printUsage();
// return 1;
// }
// if (!has_output_vertex_file) {
// std::cerr << "No output vertex file specified." << std::endl;
// printUsage();
// return 1;
// }
// if (!has_output_mesh_file) {
// std::cerr << "No output mesh file specified." << std::endl;
// printUsage();
// return 1;
// }
// if (!has_output_position_file) {
// std::cerr << "No output position file specified." << std::endl;
// printUsage();
// return 1;
// }
// WaveFrontFilter wavefront_filter(
// selected_objects.empty() ? std::nullopt : std::make_optional(selected_objects),
// selected_groups.empty() ? std::nullopt : std::make_optional(selected_groups)
// );
std::ifstream input_file;
std::istream &input_stream = (input_file_path == "")
? std::cin
: (input_file.open(input_file_path), input_file);
SettingsBuilder settings_builder;
int arg_index = 1;
bool end_of_options = false;
std::vector<std::string> positional;
if (!input_stream) {
std::cerr << "Failed to open file: " << input_file_path << std::endl;
std::exit(1);
while (arg_index < argc) {
std::string arg = argv[arg_index];
if (!end_of_options && arg == "--") {
end_of_options = true;
++arg_index;
continue;
}
if (!end_of_options && arg.size() > 0 && arg[0] == '-' && arg != "-") {
if (arg == "--float64") {
settings_builder.use_float64(true);
++arg_index;
continue;
} else if (arg == "--with-normals") {
settings_builder.with_normals(true);
++arg_index;
continue;
} else if (arg == "--with-texcoords") {
settings_builder.with_texcoords(true);
++arg_index;
continue;
} else if (arg == "--object") {
if (arg_index + 1 >= argc) {
std::cerr << "--object requires an argument\n";
return 2;
}
settings_builder.selected_objects().emplace_back(argv[arg_index + 1]);
arg_index += 2;
continue;
} else if (arg == "--group") {
if (arg_index + 1 >= argc) {
std::cerr << "--group requires an argument\n";
return 2;
}
settings_builder.selected_groups().emplace_back(argv[arg_index + 1]);
arg_index += 2;
continue;
} else {
std::cerr << "Unknown option: " << arg << "\n";
usage(argv[0]);
return 2;
}
} else {
positional.emplace_back(arg);
++arg_index;
}
}
auto wavefront_lines = parse_wavefront(input_stream);
if (positional.size() != 2) {
std::cerr << "Expected exactly two positional arguments: input_file output_file\n";
usage(argv[0]);
return 3;
}
const std::string& input_file = positional[0];
if (input_file != "-") {
settings_builder.input(input_file);
}
// Open output
const std::string& output_file = positional[1];
if (output_file != "-") {
settings_builder.output(output_file);
}
Settings settings = settings_builder.build();
std::variant<File<float, uint32_t>, File<double, uint32_t>> file = [&]() -> decltype(file) {
if (settings.use_float64()) {
return File<double, uint32_t>();
} else {
return File<float, uint32_t>();
}
}();
std::visit([&](auto& file) {
file.parse(settings);
}, file);
return 0;
}