Skip to content

Commit

Permalink
Merge pull request TrenchBroom#3912 from TrenchBroom/3911-obj-mtl-paths
Browse files Browse the repository at this point in the history
3883: Make exported .obj material paths relative to export path
  • Loading branch information
kduske authored Nov 13, 2021
2 parents accf594 + 30c5c98 commit 6ec26c0
Show file tree
Hide file tree
Showing 26 changed files with 649 additions and 100 deletions.
7 changes: 6 additions & 1 deletion common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ set(COMMON_SOURCE
${COMMON_SOURCE_DIR}/IO/EntityModelLoader.cpp
${COMMON_SOURCE_DIR}/IO/EntityModelParser.cpp
${COMMON_SOURCE_DIR}/IO/EntParser.cpp
${COMMON_SOURCE_DIR}/IO/ExportOptions.cpp
${COMMON_SOURCE_DIR}/IO/FgdParser.cpp
${COMMON_SOURCE_DIR}/IO/File.cpp
${COMMON_SOURCE_DIR}/IO/FileMatcher.cpp
Expand Down Expand Up @@ -304,6 +305,7 @@ set(COMMON_SOURCE
${COMMON_SOURCE_DIR}/View/CurrentGameIndicator.cpp
${COMMON_SOURCE_DIR}/View/CurrentGroupCommand.cpp
${COMMON_SOURCE_DIR}/View/CyclingMapView.cpp
${COMMON_SOURCE_DIR}/View/DialogHeader.cpp
${COMMON_SOURCE_DIR}/View/DirectoryTextureCollectionEditor.cpp
${COMMON_SOURCE_DIR}/View/DragTracker.cpp
${COMMON_SOURCE_DIR}/View/DropTracker.cpp
Expand Down Expand Up @@ -381,6 +383,7 @@ set(COMMON_SOURCE
${COMMON_SOURCE_DIR}/View/MoveObjectsToolPage.cpp
${COMMON_SOURCE_DIR}/View/MultiCompletionLineEdit.cpp
${COMMON_SOURCE_DIR}/View/MultiMapView.cpp
${COMMON_SOURCE_DIR}/View/ObjExportDialog.cpp
${COMMON_SOURCE_DIR}/View/OnePaneMapView.cpp
${COMMON_SOURCE_DIR}/View/PickRequest.cpp
${COMMON_SOURCE_DIR}/View/PopupButton.cpp
Expand Down Expand Up @@ -524,6 +527,7 @@ set(COMMON_HEADER
${COMMON_SOURCE_DIR}/IO/EntityModelLoader.h
${COMMON_SOURCE_DIR}/IO/EntityModelParser.h
${COMMON_SOURCE_DIR}/IO/EntParser.h
${COMMON_SOURCE_DIR}/IO/ExportOptions.h
${COMMON_SOURCE_DIR}/IO/FgdParser.h
${COMMON_SOURCE_DIR}/IO/File.h
${COMMON_SOURCE_DIR}/IO/FileMatcher.h
Expand Down Expand Up @@ -608,7 +612,6 @@ set(COMMON_HEADER
${COMMON_SOURCE_DIR}/Model/EntityProperties.h
${COMMON_SOURCE_DIR}/Model/EntityPropertiesVariableStore.h
${COMMON_SOURCE_DIR}/Model/EntityRotationPolicy.h
${COMMON_SOURCE_DIR}/Model/ExportFormat.h
${COMMON_SOURCE_DIR}/Model/Game.h
${COMMON_SOURCE_DIR}/Model/GameConfig.h
${COMMON_SOURCE_DIR}/Model/GameEngineConfig.h
Expand Down Expand Up @@ -821,6 +824,7 @@ set(COMMON_HEADER
${COMMON_SOURCE_DIR}/View/CurrentGameIndicator.h
${COMMON_SOURCE_DIR}/View/CurrentGroupCommand.h
${COMMON_SOURCE_DIR}/View/CyclingMapView.h
${COMMON_SOURCE_DIR}/View/DialogHeader.h
${COMMON_SOURCE_DIR}/View/DirectoryTextureCollectionEditor.h
${COMMON_SOURCE_DIR}/View/DragTracker.h
${COMMON_SOURCE_DIR}/View/DropTracker.h
Expand Down Expand Up @@ -899,6 +903,7 @@ set(COMMON_HEADER
${COMMON_SOURCE_DIR}/View/MoveObjectsToolPage.h
${COMMON_SOURCE_DIR}/View/MultiCompletionLineEdit.h
${COMMON_SOURCE_DIR}/View/MultiMapView.h
${COMMON_SOURCE_DIR}/View/ObjExportDialog.h
${COMMON_SOURCE_DIR}/View/OnePaneMapView.h
${COMMON_SOURCE_DIR}/View/PasteType.h
${COMMON_SOURCE_DIR}/View/PickRequest.h
Expand Down
80 changes: 80 additions & 0 deletions common/src/IO/ExportOptions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
Copyright (C) 2021 Amara M. Kilic
Copyright (C) 2021 Kristian Duske
This file is part of TrenchBroom.
TrenchBroom is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
TrenchBroom is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>.
*/

#include "Macros.h"
#include "IO/ExportOptions.h"

#include <kdl/overload.h>

#include <ostream>

namespace TrenchBroom {
namespace IO {
bool operator==(const MapExportOptions& lhs, const MapExportOptions& rhs) {
return lhs.exportPath == rhs.exportPath;
}

bool operator!=(const MapExportOptions& lhs, const MapExportOptions& rhs) {
return !(lhs == rhs);
}

std::ostream& operator<<(std::ostream& lhs, const MapExportOptions& rhs) {
lhs << "MapExportOptions{";
lhs << "exportPath: " << rhs.exportPath;
lhs << "}";
return lhs;
}

std::ostream& operator<<(std::ostream& lhs, const ObjMtlPathMode rhs) {
switch (rhs) {
case ObjMtlPathMode::RelativeToGamePath:
lhs << "RelativeToGamePath";
break;
case ObjMtlPathMode::RelativeToExportPath:
lhs << "RelativeToExportPath";
break;
switchDefault();
}
return lhs;
}

bool operator==(const ObjExportOptions& lhs, const ObjExportOptions& rhs) {
return lhs.exportPath == rhs.exportPath && lhs.mtlPathMode == rhs.mtlPathMode;
}

bool operator!=(const ObjExportOptions& lhs, const ObjExportOptions& rhs) {
return !(lhs == rhs);
}

std::ostream& operator<<(std::ostream& lhs, const ObjExportOptions& rhs) {
lhs << "ObjExportOptions{";
lhs << "exportPath: " << rhs.exportPath << ", ";
lhs << "mtlPathMode: " << rhs.mtlPathMode;
lhs << "}";
return lhs;
}

std::ostream& operator<<(std::ostream& lhs, const ExportOptions& rhs) {
std::visit([&](const auto& o) { lhs << o; }, rhs);
return lhs;
}
}
}

59 changes: 59 additions & 0 deletions common/src/IO/ExportOptions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
Copyright (C) 2021 Amara M. Kilic
Copyright (C) 2021 Kristian Duske
This file is part of TrenchBroom.
TrenchBroom is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
TrenchBroom is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include "IO/Path.h"

#include <iosfwd>
#include <variant>

namespace TrenchBroom {
namespace IO {
struct MapExportOptions {
Path exportPath;
};

bool operator==(const MapExportOptions& lhs, const MapExportOptions& rhs);
bool operator!=(const MapExportOptions& lhs, const MapExportOptions& rhs);
std::ostream& operator<<(std::ostream& lhs, const MapExportOptions& rhs);

enum class ObjMtlPathMode {
RelativeToGamePath,
RelativeToExportPath
};

std::ostream& operator<<(std::ostream& lhs, ObjMtlPathMode rhs);

struct ObjExportOptions {
Path exportPath;
ObjMtlPathMode mtlPathMode;
};

bool operator==(const ObjExportOptions& lhs, const ObjExportOptions& rhs);
bool operator!=(const ObjExportOptions& lhs, const ObjExportOptions& rhs);
std::ostream& operator<<(std::ostream& lhs, const ObjExportOptions& rhs);

using ExportOptions = std::variant<MapExportOptions, ObjExportOptions>;

std::ostream& operator<<(std::ostream& lhs, const ExportOptions& rhs);
}
}

28 changes: 22 additions & 6 deletions common/src/IO/ObjSerializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include "Ensure.h"
#include "Assets/Texture.h"
#include "IO/ExportOptions.h"
#include "Model/BrushNode.h"
#include "Model/BrushFace.h"
#include "Model/BrushGeometry.h"
Expand All @@ -32,6 +33,7 @@
#include <fmt/format.h>

#include <iostream>
#include <utility>

namespace TrenchBroom {
namespace IO {
Expand Down Expand Up @@ -78,17 +80,18 @@ namespace TrenchBroom {
return str;
}

ObjSerializer::ObjSerializer(std::ostream& objStream, std::ostream& mtlStream, std::string mtlFilename) :
ObjSerializer::ObjSerializer(std::ostream& objStream, std::ostream& mtlStream, std::string mtlFilename, IO::ObjExportOptions options) :
m_objStream{objStream},
m_mtlStream{mtlStream},
m_mtlFilename{std::move(mtlFilename)} {
m_mtlFilename{std::move(mtlFilename)},
m_options{std::move(options)} {
ensure(m_objStream.good(), "obj stream is good");
ensure(m_mtlStream.good(), "mtl stream is good");
}

void ObjSerializer::doBeginFile(const std::vector<const Model::Node*>& /* rootNodes */) {}

static void writeMtlFile(std::ostream& str, const std::vector<ObjSerializer::Object>& objects) {
static void writeMtlFile(std::ostream& str, const std::vector<ObjSerializer::Object>& objects, const IO::ObjExportOptions& options) {
auto usedTextures = std::map<std::string, const Assets::Texture*>{};

for (const auto& object : objects) {
Expand All @@ -104,11 +107,24 @@ namespace TrenchBroom {
), object);
}

const auto basePath = options.exportPath.deleteLastComponent();
for (const auto& [textureName, texture] : usedTextures) {
str << "newmtl " << textureName << "\n";
if (texture != nullptr && !texture->relativePath().isEmpty()) {
str << "map_Kd " << texture->relativePath().asString() << "\n\n";
if (texture) {
switch (options.mtlPathMode) {
case ObjMtlPathMode::RelativeToGamePath:
str << "map_Kd " << texture->relativePath() << "\n";
break;
case ObjMtlPathMode::RelativeToExportPath:
// textures loaded from image files (pak files) don't have absolute paths
if (!texture->absolutePath().isEmpty()) {
const auto mtlPath = basePath.makeRelative(texture->absolutePath());
str << "map_Kd " << mtlPath << "\n";
}
break;
}
}
str << "\n";
}
}

Expand Down Expand Up @@ -157,7 +173,7 @@ namespace TrenchBroom {
}

void ObjSerializer::doEndFile() {
writeMtlFile(m_mtlStream, m_objects);
writeMtlFile(m_mtlStream, m_objects, m_options);
writeObjFile(m_objStream, m_mtlFilename, m_vertices.list(), m_texCoords.list(), m_normals.list(), m_objects);
}

Expand Down
4 changes: 3 additions & 1 deletion common/src/IO/ObjSerializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#pragma once

#include "FloatType.h"
#include "IO/ExportOptions.h"
#include "IO/NodeSerializer.h"

#include <vecmath/forward.h>
Expand Down Expand Up @@ -117,6 +118,7 @@ namespace TrenchBroom {
std::ostream& m_objStream;
std::ostream& m_mtlStream;
std::string m_mtlFilename;
ObjExportOptions m_options;

IndexMap<vm::vec3> m_vertices;
IndexMap<vm::vec2f> m_texCoords;
Expand All @@ -125,7 +127,7 @@ namespace TrenchBroom {
std::optional<BrushObject> m_currentBrush;
std::vector<Object> m_objects;
public:
explicit ObjSerializer(std::ostream& objStream, std::ostream& mtlStream, std::string mtlFilename);
ObjSerializer(std::ostream& objStream, std::ostream& mtlStream, std::string mtlFilename, ObjExportOptions options);
private:
void doBeginFile(const std::vector<const Model::Node*>& rootNodes) override;
void doEndFile() override;
Expand Down
5 changes: 3 additions & 2 deletions common/src/Model/Game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "Game.h"

#include "Assets/EntityDefinitionFileSpec.h"
#include "IO/ExportOptions.h"
#include "Model/BrushFace.h"
#include "Model/GameFactory.h"
#include "Model/WorldNode.h"
Expand Down Expand Up @@ -86,8 +87,8 @@ namespace TrenchBroom {
doWriteMap(world, path);
}

void Game::exportMap(WorldNode& world, const Model::ExportFormat format, const IO::Path& path) const {
doExportMap(world, format, path);
void Game::exportMap(WorldNode& world, const IO::ExportOptions& options) const {
doExportMap(world, options);
}

std::vector<Node*> Game::parseNodes(const std::string& str, const MapFormat mapFormat, const vm::bbox3& worldBounds, Logger& logger) const {
Expand Down
6 changes: 3 additions & 3 deletions common/src/Model/Game.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "FloatType.h"
#include "IO/EntityDefinitionLoader.h"
#include "IO/EntityModelLoader.h"
#include "IO/ExportOptions.h"
#include "Model/GameConfig.h"
#include "Model/MapFormat.h"

Expand Down Expand Up @@ -49,7 +50,6 @@ namespace TrenchBroom {
class BrushFaceAttributes;
class CompilationConfig;
class Entity;
enum class ExportFormat;
struct FlagsConfig;
class Node;
class SmartTag;
Expand Down Expand Up @@ -98,7 +98,7 @@ namespace TrenchBroom {
std::unique_ptr<WorldNode> newMap(MapFormat format, const vm::bbox3& worldBounds, Logger& logger) const;
std::unique_ptr<WorldNode> loadMap(MapFormat format, const vm::bbox3& worldBounds, const IO::Path& path, Logger& logger) const;
void writeMap(WorldNode& world, const IO::Path& path) const;
void exportMap(WorldNode& world, Model::ExportFormat format, const IO::Path& path) const;
void exportMap(WorldNode& world, const IO::ExportOptions& options) const;
public: // parsing and serializing objects
std::vector<Node*> parseNodes(const std::string& str, MapFormat mapFormat, const vm::bbox3& worldBounds, Logger& logger) const;
std::vector<BrushFace> parseBrushFaces(const std::string& str, MapFormat mapFormat, const vm::bbox3& worldBounds, Logger& logger) const;
Expand Down Expand Up @@ -147,7 +147,7 @@ namespace TrenchBroom {
virtual std::unique_ptr<WorldNode> doNewMap(MapFormat format, const vm::bbox3& worldBounds, Logger& logger) const = 0;
virtual std::unique_ptr<WorldNode> doLoadMap(MapFormat format, const vm::bbox3& worldBounds, const IO::Path& path, Logger& logger) const = 0;
virtual void doWriteMap(WorldNode& world, const IO::Path& path) const = 0;
virtual void doExportMap(WorldNode& world, Model::ExportFormat format, const IO::Path& path) const = 0;
virtual void doExportMap(WorldNode& world, const IO::ExportOptions& options) const = 0;

virtual std::vector<Node*> doParseNodes(const std::string& str, MapFormat mapFormat, const vm::bbox3& worldBounds, Logger& logger) const = 0;
virtual std::vector<BrushFace> doParseBrushFaces(const std::string& str, MapFormat mapFormat, const vm::bbox3& worldBounds, Logger& logger) const = 0;
Expand Down
Loading

0 comments on commit 6ec26c0

Please sign in to comment.