Skip to content

Serializer #215

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 7 commits into
base: release
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 130 additions & 3 deletions tiny_obj_loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,40 @@ class ObjReader {
std::string error_;
};

class ObjWriter {
public:
ObjWriter() {}

/// Construct a writer from a reader
ObjWriter(const ObjReader &other);

///\brief Save the content of this obj asset to a pair of strings representing
/// the OBJ and MLT file contents
bool SaveToString(std::string &obj_text, std::string &mlt_text);

/// Save the content to the file path
/// \param file_path The path where to save the file WITHOUT EXTENSION
bool SaveTofile(const std::string &file_path);

///
/// Warning message(may be filled after `save`)
///
const std::string &Warning() const;

///
/// Error message(filled when `save` failed)
///
const std::string &error() const;

attrib_t attrib_;
std::vector<shape_t> shapes_;
std::vector<material_t> materials_;

private:
std::string warning_;
std::string error_;
};

/// ==>>========= Legacy v1 API =============================================

/// Loads .obj from a file.
Expand Down Expand Up @@ -616,11 +650,12 @@ bool ParseTextureNameAndOption(std::string *texname, texture_option_t *texopt,
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <limits>
#include <utility>

#include <fstream>
#include <iostream>
#include <limits>
#include <sstream>
#include <string>
#include <utility>

namespace tinyobj {

Expand Down Expand Up @@ -2060,6 +2095,98 @@ bool MaterialStreamReader::operator()(const std::string &matId,
return true;
}

ObjWriter::ObjWriter(const ObjReader &other) {
attrib_ = other.GetAttrib();
shapes_ = other.GetShapes();
materials_ = other.GetMaterials();
warning_.clear();
error_.clear();
}

bool ObjWriter::SaveToString(std::string &obj_text, std::string &mlt_text) {
// Write the Obj text
std::stringstream obj_text_stream;
obj_text_stream << "#File created by experimental tiny_obj serializer\n";
const size_t vertex_count = attrib_.vertices.size() / 3;
for (size_t v = 0; v < vertex_count; v++) {
obj_text_stream << "v ";
obj_text_stream << attrib_.vertices[3 * v + 0] << " ";
obj_text_stream << attrib_.vertices[3 * v + 1] << " ";
obj_text_stream << attrib_.vertices[3 * v + 2] << "\n";
}

for (size_t v = 0; v < vertex_count; v++) {
obj_text_stream << "vt ";
obj_text_stream << attrib_.texcoords[2 * v + 0] << " ";
obj_text_stream << attrib_.texcoords[2 * v + 1] << "\n";
// obj_text_stream << attrib_.texcoord_ws[v] << "\n";
}

for (size_t v = 0; v < vertex_count; v++) {
obj_text_stream << "vn ";
obj_text_stream << attrib_.normals[3 * v + 0] << " ";
obj_text_stream << attrib_.normals[3 * v + 1] << " ";
obj_text_stream << attrib_.normals[3 * v + 2] << "\n";
}

// faces
for (size_t s = 0; s < shapes_.size(); ++s) {
const shape_t &shape = shapes_[s];
const unsigned char face_count =
static_cast<unsigned char>(shape.mesh.num_face_vertices.size());

size_t index_offset = 0;
for (size_t f = 0; f < face_count; f++) {
obj_text_stream << "f ";
const unsigned char face_vertex_count = shape.mesh.num_face_vertices[f];
for (size_t v = 0; v < face_vertex_count; ++v) {
const index_t index = shape.mesh.indices[index_offset + v];
obj_text_stream << index.vertex_index << "/" << index.texcoord_index
<< "/" << index.normal_index << " ";
}
obj_text_stream << "\n";
index_offset += face_vertex_count;
}
}

obj_text = obj_text_stream.str();

// TODO write material
(void)mlt_text;

return true;
}

bool ObjWriter::SaveTofile(const std::string &file_path) {
std::string obj_path, mlt_path;
obj_path = mlt_path = file_path;
obj_path += ".obj";
mlt_path += ".mlt";

std::string obj_text, mlt_text;

if (!SaveToString(obj_text, mlt_text)) {
return false;
}

std::ofstream obj_output(obj_path.c_str());
std::ofstream mlt_output(mlt_path.c_str());

if (!(obj_output && mlt_output)) {
error_ = "Could not open output files " + obj_path + " and/or " + mlt_path;
return false;
}

obj_output << obj_text;
mlt_output << mlt_text;

return true;
}

const std::string &ObjWriter::Warning() const { return warning_; }

const std::string &ObjWriter::error() const { return error_; }

bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
std::vector<material_t> *materials, std::string *warn,
std::string *err, const char *filename, const char *mtl_basedir,
Expand Down