diff --git a/src/Converter.cpp b/src/Converter.cpp index 021d179..9c0c680 100644 --- a/src/Converter.cpp +++ b/src/Converter.cpp @@ -1,21 +1,22 @@ -#include "Converter.h" -#include +#include "Converter.h" +#include +#include #include #include +#include #include -#include -void Converter::read(std::string_view fileName) +void Converter::readZen(std::string_view fileName) { std::ifstream file(fileName.data(), std::ios::binary); - std::cout << "Read file: " << fileName << std::endl; - if (!file.is_open()) + std::cout << "Read file: " << fileName << '\n'; + if(!file.is_open()) { - std::cerr << "Couldn't open file!" << std::endl; + std::cerr << "Couldn't open file!\n"; return; } - std::cout << "Reading... " << std::endl; + std::cout << "Reading ..."; // Connections. std::vector wayl; @@ -34,21 +35,42 @@ void Converter::read(std::string_view fileName) exit(1); } - // Skip until '[WayNet' tag. - bool foundWayNet = false; - while (std::getline(file, line)) + bool foundWaynet = false; + while(std::getline(file, line)) { - if (!foundWayNet) + if(!foundWaynet) { - foundWayNet = line.find("[WayNet") != std::string::npos; + if(line.find("[% zCVobSpot:") == std::string::npos) + { + foundWaynet = (line.find("[WayNet") != std::string::npos); + } + else + { + Freepoint& fp = freepoints.emplace_back(); + + // skip pack, presetName and bbox3DWS + file.ignore(std::numeric_limits::max(), '\n'); + file.ignore(std::numeric_limits::max(), '\n'); + file.ignore(std::numeric_limits::max(), '\n'); + + // TODO: extract rotation and convert it to GMP angle + file.ignore(std::numeric_limits::max(), '\n'); + + // skip to the position + file.ignore(std::numeric_limits::max(), ':'); + file >> fp.pos.x >> fp.pos.y >> fp.pos.z; + // skip to the name + file.ignore(std::numeric_limits::max(), ':'); + file >> fp.name; + } } - else if (line.find("[way") != std::string::npos) + else if(line.find("[way") != std::string::npos) { // Get object id. auto vector = split(line); - if (vector.size() != 4) + if(vector.size() != 4) { - std::cerr << "Too many split result (" << vector.size() << ") instead of 3 from line:" << std::endl << "'" << line << "'" << std::endl; + std::cerr << "Too many split result (" << vector.size() << ") instead of 3 from line:\n'" << line << "'\n"; return; } vector[3].erase(vector[3].end() - 1); // Remove ']'. @@ -59,83 +81,39 @@ void Converter::read(std::string_view fileName) // Create a new Waypoint if this line is not a reference. if(line.find("\247") == std::string::npos) // § { - std::string attribute; - size_t location; - std::string lineWaypoint; - - // Get name. - std::getline(file, lineWaypoint); - attribute = "wpName=string:"; - location = lineWaypoint.find(attribute); - if (location == std::string::npos) - { - std::cerr << "Awaited '" << attribute << "' but instead line is:" << std::endl << "'" << lineWaypoint << "'" << std::endl; - return; - } - std::string name(lineWaypoint.substr(location + attribute.length())); - - // Skip waterDepth and underWater. - std::getline(file, lineWaypoint); - std::getline(file, lineWaypoint); - - // Get position - std::getline(file, lineWaypoint); - attribute = "position=vec3:"; - location = lineWaypoint.find(attribute); - if (location == std::string::npos) - { - std::cerr << "Awaited '" << attribute << "' but instead line is:" << std::endl << "'" << lineWaypoint << "'" << std::endl; - return; - } - std::vector positions = split(lineWaypoint.substr(location + attribute.length())); - if (positions.size() != 3) - { - std::cerr << "Too many split result (" << positions.size() << ") instead of 3 from line:" << std::endl << "'" << lineWaypoint << "'" << std::endl; - return; - } - double x = std::stod(positions[0]); - double y = std::stod(positions[1]); - double z = std::stod(positions[2]); - - // Get direction - std::getline(file, lineWaypoint); - attribute = "direction=vec3:"; - location = lineWaypoint.find(attribute); - if (location == std::string::npos) - { - std::cerr << "Awaited '" << attribute << "' but instead line is:" << std::endl << "'" << lineWaypoint << "'" << std::endl; - return; - } - std::vector directions = split(lineWaypoint.substr(location + attribute.length())); - if (directions.size() != 3) - { - std::cerr << "Too many split result (" << directions.size() << ") instead of 3 from line:" << std::endl << "'" << lineWaypoint << "'" << std::endl; - return; - } - double dX = std::stod(directions[0]); - double dZ = std::stod(directions[2]); - - waypoint = std::make_shared(name, x, y, z, dX, dZ); - waypoints[objectId] = waypoint; + waypoint = std::make_shared(); + waypoints.emplace(objectId, waypoint); + + // skip to the name + file.ignore(std::numeric_limits::max(), ':'); + file >> waypoint->name; + // jump to the next line + file.ignore(std::numeric_limits::max(), '\n'); + // skip waterDepth and underWater + file.ignore(std::numeric_limits::max(), '\n'); + file.ignore(std::numeric_limits::max(), '\n'); + // skip to the position + file.ignore(std::numeric_limits::max(), ':'); + file >> waypoint->pos.x >> waypoint->pos.y >> waypoint->pos.z; + // skip to the direction + file.ignore(std::numeric_limits::max(), ':'); + [[maybe_unused]] float dY; + file >> waypoint->dX >> dY >> waypoint->dZ; } // Don't create a Way for Waypoints. - if (line.find("[waypoint") == std::string::npos) + if(line.find("[waypoint") == std::string::npos) { Way way{ objectId, waypoint }; - if (line.find("[wayl") != std::string::npos) - { + if(line.find("[wayl") != std::string::npos) wayl.push_back(way); - } - else if (line.find("[wayr") != std::string::npos) - { + else if(line.find("[wayr") != std::string::npos) wayr.push_back(way); - } // After a left Way there must be a right Way. The difference should never be higher than 1. - if (wayr.size() > wayl.size() && wayl.size() - 1 > wayr.size()) + if(wayr.size() > wayl.size() && wayl.size() - 1 > wayr.size()) { - std::cerr << "WayNet didn't started with left Way or two right/left Way successively." << std::endl; + std::cerr << "WayNet didn't started with left Way or two right/left Way successively.\n"; } } } @@ -143,90 +121,108 @@ void Converter::read(std::string_view fileName) file.close(); // Fill out empty waypoint pointers. - for (auto& way : wayl) + for(auto& way : wayl) { - if (way.waypoint == nullptr) + if(!way.waypoint) { auto result = waypoints.find(way.objectId); - if (result != waypoints.end()) + if(result != waypoints.end()) { way.waypoint = result->second; } else { - std::cerr << "For id: " << way.objectId << " doesn't exists a Waypoint!" << std::endl; + std::cerr << "For id: " << way.objectId << " doesn't exist a Waypoint!\n"; } } } - for (auto& way : wayr) + for(auto& way : wayr) { - if (way.waypoint == nullptr) + if(!way.waypoint) { auto result = waypoints.find(way.objectId); - if (result != waypoints.end()) + if(result != waypoints.end()) { way.waypoint = result->second; } else { - std::cerr << "For id: " << way.objectId << " doesn't exists a Waypoint!" << std::endl; + std::cerr << "For id: " << way.objectId << " doesn't exist a Waypoint!\n"; } } } // Insert Waypoint connections. - for (int i = 0; i < wayl.size(); i++) + for(size_t i = 0; i < wayl.size(); i++) { auto left = waypoints.find(wayl[i].objectId); auto right = waypoints.find(wayr[i].objectId); - if (left != waypoints.end() && right != waypoints.end()) + if(left != waypoints.end() && right != waypoints.end()) { left->second->connections.push_back(right->second->name); right->second->connections.push_back(left->second->name); } else { - std::cerr << "Couldn't get Waypoint with object id: " << wayl[i].objectId << " or " << wayr[i].objectId << std::endl; + std::cerr << "Couldn't get Waypoint with object id: " << wayl[i].objectId << " or " << wayr[i].objectId << '\n'; } } - std::cout << "Done. Waypoints: " << waypoints.size() << " and Ways: " << wayl.size() << std::endl; + std::cout << " Done.\nFreepoints: " << freepoints.size() << "; Waypoints: " << waypoints.size() << "; Ways: " << wayl.size() << '\n'; } std::vector Converter::split(const std::string& line) const { - std::istringstream iss(line); - return {std::istream_iterator{ iss }, std::istream_iterator{}}; + std::istringstream iss{line.c_str()}; + return {std::istream_iterator{iss}, std::istream_iterator{}}; } -void Converter::write(std::string_view fileName) const +void Converter::writeWp(std::string_view fileName) const { - if (waypoints.size() == 0) + if(waypoints.size() == 0) { - std::cerr << "Nothing to write." << std::endl; + std::cerr << "[WP] Nothing to write.\n"; return; } - std::ofstream file(fileName.data(), std::ios::binary); // don't convert \n to \r\n on Windows - - std::cout << std::endl << "Write file: " << fileName << std::endl; - if (!file.is_open()) + std::cout << "\nWrite file: " << fileName << '\n'; + if(!file.is_open()) { - std::cerr << "Couldn't open file!" << std::endl; + std::cerr << "Couldn't open file!\n"; return; } - std::cout << "Writing... " << std::endl; + std::cout << "Writing ..."; - for (const auto& wp : waypoints) + for(const auto& wp : waypoints) { auto waypoint = wp.second; - file << waypoint->name << ";" << waypoint->x << ";" << waypoint->y << ";" << waypoint->z << ";" << waypoint->dX << ";" << waypoint->dZ; - for (const auto& connection : waypoint->connections) - { + file << waypoint->name << ";" << waypoint->pos.x << ";" << waypoint->pos.y << ";" << waypoint->pos.z << ";" << waypoint->dX << ";" << waypoint->dZ; + for(const auto& connection : waypoint->connections) file << ";" << connection; - } - file << std::endl; + file << '\n'; } - std::cout << "Done. Waypoints: " << waypoints.size() << std::endl; + std::cout << " Done.\n"; +} + +void Converter::writeFp(std::string_view fileName) const +{ + if(freepoints.size() == 0) + { + std::cerr << "[FP] Nothing to write.\n"; + return; + } + std::ofstream file(fileName.data(), std::ios::binary); // don't convert \n to \r\n on Windows + std::cout << "\nWrite file: " << fileName << '\n'; + if(!file.is_open()) + { + std::cerr << "Couldn't open file!\n"; + return; + } + std::cout << "Writing ..."; + + for(const auto& fp : freepoints) + file << fp.name << ";" << fp.pos.x << ";" << fp.pos.y << ";" << fp.pos.z << ";" << fp.dX << ";" << fp.dZ << '\n'; + + std::cout << " Done.\n"; } diff --git a/src/Converter.h b/src/Converter.h index c83b909..921f0e9 100644 --- a/src/Converter.h +++ b/src/Converter.h @@ -1,6 +1,7 @@ #pragma once #include "Waypoint.h" +#include "Freepoint.h" #include #include #include @@ -8,11 +9,13 @@ class Converter { public: - void read(std::string_view fileName); - void write(std::string_view fileName) const; + void readZen(std::string_view fileName); + void writeWp(std::string_view fileName) const; + void writeFp(std::string_view fileName) const; private: std::vector split(const std::string& line) const; std::map> waypoints; + std::vector freepoints; }; diff --git a/src/Freepoint.h b/src/Freepoint.h new file mode 100644 index 0000000..e515dcc --- /dev/null +++ b/src/Freepoint.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include +#include "Math.h" + +struct Freepoint +{ + Freepoint() = default; + Freepoint(std::string name, const vec3& pos) + : name(std::move(name)), + pos(pos) + { + } + + std::string name; + vec3 pos; + float dX = 0; + float dZ = 0; +}; diff --git a/src/Math.h b/src/Math.h new file mode 100644 index 0000000..89eee43 --- /dev/null +++ b/src/Math.h @@ -0,0 +1,8 @@ +#pragma once + +struct vec3 +{ + float x = 0; + float y = 0; + float z = 0; +}; diff --git a/src/Waypoint.h b/src/Waypoint.h index 13fca39..0af36a9 100644 --- a/src/Waypoint.h +++ b/src/Waypoint.h @@ -1,16 +1,26 @@ #pragma once + +#include #include #include #include +#include "Math.h" struct Waypoint { - Waypoint(std::string name, double x, double y, double z, double dX, double dZ) - : name(name), x(x), y(y), z(z), dX(dX), dZ(dZ) {} + Waypoint() = default; + Waypoint(std::string name, vec3 pos, float dX, float dZ) + : name(std::move(name)), + pos(pos), + dX(dX), + dZ(dZ) + { + } std::string name; - double x, y, z; - double dX, dZ; + vec3 pos; + float dX = 0; + float dZ = 0; std::vector connections; }; diff --git a/src/main.cpp b/src/main.cpp index 0c314ba..062e289 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,11 +1,11 @@ -#include +#include #include #include #include "Converter.h" int main(int argc, char *argv[]) { - std::cout << "Reveares' Waypoint Converter" << std::endl << std::endl; + std::cout << "Reveares' Waypoint Converter v1.1 (improved by Sabrosa)\n\n"; if(argc != 2) { @@ -17,8 +17,9 @@ int main(int argc, char *argv[]) auto start = std::chrono::high_resolution_clock::now(); Converter converter; - converter.read(zen.string()); - converter.write(zen.replace_extension(".wp").string()); + converter.readZen(zen.string()); + converter.writeWp(zen.replace_extension(".wp").string()); + converter.writeFp(zen.replace_extension(".fp").string()); auto end = std::chrono::high_resolution_clock::now(); std::cout << "Which took " << std::chrono::duration_cast(end - start).count() << " ms.\n";