Skip to content

Commit

Permalink
Add experimental OBJ exporter code.
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Aug 25, 2017
1 parent 7cdeabb commit 1abec27
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 0 deletions.
1 change: 1 addition & 0 deletions plugins/model/Makefile.am
Expand Up @@ -11,6 +11,7 @@ model_la_LIBADD = $(top_builddir)/libs/picomodel/libpicomodel.la \
model_la_SOURCES = AseExporter.cpp \
Lwo2Chunk.cpp \
Lwo2Exporter.cpp \
WavefrontExporter.cpp \
PicoModelNode.cpp \
RenderablePicoModel.cpp \
PicoModelLoader.cpp \
Expand Down
2 changes: 2 additions & 0 deletions plugins/model/PicoModelModule.h
Expand Up @@ -12,6 +12,7 @@
#include "PicoModelLoader.h"
#include "AseExporter.h"
#include "Lwo2Exporter.h"
#include "WavefrontExporter.h"

typedef unsigned char byte;

Expand Down Expand Up @@ -113,6 +114,7 @@ class PicoModelModule :

GlobalModelFormatManager().registerExporter(std::make_shared<AseExporter>());
GlobalModelFormatManager().registerExporter(std::make_shared<Lwo2Exporter>());
GlobalModelFormatManager().registerExporter(std::make_shared<WavefrontExporter>());
}
};

Expand Down
88 changes: 88 additions & 0 deletions plugins/model/WavefrontExporter.cpp
@@ -0,0 +1,88 @@
#include "WavefrontExporter.h"

#include "itextstream.h"
#include "imodelsurface.h"
#include "imap.h"

#include <boost/algorithm/string/replace.hpp>
#include <boost/format.hpp>

namespace model
{

WavefrontExporter::WavefrontExporter()
{}

IModelExporterPtr WavefrontExporter::clone()
{
return std::make_shared<WavefrontExporter>();
}

const std::string& WavefrontExporter::getDisplayName() const
{
static std::string _extension("Wavefront OBJ");
return _extension;
}

const std::string& WavefrontExporter::getExtension() const
{
static std::string _extension("OBJ");
return _extension;
}

void WavefrontExporter::exportToStream(std::ostream& stream)
{
// Count exported vertices. Exported indices are 1-based though.
std::size_t vertexCount = 0;

// Each surface is exported as group.
for (const Surfaces::value_type& pair : _surfaces)
{
const Surface& surface = pair.second;

// Base index for vertices, added to the surface indices
std::size_t vertBaseIndex = vertexCount;

// Since we don't write .mtl files store at least the material into the group name
stream << "g " << surface.materialName << std::endl;
stream << std::endl;

// Temporary buffers for vertices, texcoords and polys
std::stringstream vertexBuf;
std::stringstream texCoordBuf;
std::stringstream polyBuf;

for (const ArbitraryMeshVertex& meshVertex : surface.vertices)
{
// Write coordinates into the export buffers
const Vector3& vert = meshVertex.vertex;
const Vector2& uv = meshVertex.texcoord;

vertexBuf << "v " << vert.x() << " " << vert.y() << " " << vert.z() << "\n";
texCoordBuf << "vt " << uv.x() << " " << uv.y() << "\n";

vertexCount++;
}

// Every three indices form a triangle. Indices are 1-based so add +1 to each index
for (std::size_t i = 0; i + 2 < surface.indices.size(); i += 3)
{
std::size_t index1 = vertBaseIndex + static_cast<std::size_t>(surface.indices[i+0]) + 1;
std::size_t index2 = vertBaseIndex + static_cast<std::size_t>(surface.indices[i+1]) + 1;
std::size_t index3 = vertBaseIndex + static_cast<std::size_t>(surface.indices[i+2]) + 1;

// f 1/1 3/3 2/2
polyBuf << "f";
polyBuf << " " << index1 << "/" << index1;
polyBuf << " " << index2 << "/" << index2;
polyBuf << " " << index3 << "/" << index3;
polyBuf << "\n";
}

stream << vertexBuf.str() << std::endl;
stream << texCoordBuf.str() << std::endl;
stream << polyBuf.str() << std::endl;
}
}

}
31 changes: 31 additions & 0 deletions plugins/model/WavefrontExporter.h
@@ -0,0 +1,31 @@
#pragma once

#include "imodel.h"
#include "ModelExporterBase.h"

namespace model
{

class WavefrontExporter :
public ModelExporterBase
{
public:
WavefrontExporter();

IModelExporterPtr clone() override;

Format getFileFormat() const override
{
return Format::Text;
}

const std::string& getDisplayName() const override;

// Returns the uppercase file extension this exporter is suitable for
const std::string& getExtension() const override;

// Export the model file to the given stream
void exportToStream(std::ostream& stream) override;
};

}
2 changes: 2 additions & 0 deletions tools/msvc/model.vcxproj
Expand Up @@ -323,6 +323,7 @@
<ClCompile Include="..\..\plugins\model\plugin.cpp" />
<ClCompile Include="..\..\plugins\model\RenderablePicoModel.cpp" />
<ClCompile Include="..\..\plugins\model\RenderablePicoSurface.cpp" />
<ClCompile Include="..\..\plugins\model\WavefrontExporter.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\plugins\model\AseExporter.h" />
Expand All @@ -335,6 +336,7 @@
<ClInclude Include="..\..\plugins\model\plugin.h" />
<ClInclude Include="..\..\plugins\model\RenderablePicoModel.h" />
<ClInclude Include="..\..\plugins\model\RenderablePicoSurface.h" />
<ClInclude Include="..\..\plugins\model\WavefrontExporter.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="picomodellib.vcxproj">
Expand Down
6 changes: 6 additions & 0 deletions tools/msvc/model.vcxproj.filters
Expand Up @@ -31,6 +31,9 @@
<ClCompile Include="..\..\plugins\model\Lwo2Chunk.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\plugins\model\WavefrontExporter.cpp">
<Filter>src</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\plugins\model\PicoModelLoader.h">
Expand Down Expand Up @@ -63,5 +66,8 @@
<ClInclude Include="..\..\plugins\model\ModelExporterBase.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\plugins\model\WavefrontExporter.h">
<Filter>src</Filter>
</ClInclude>
</ItemGroup>
</Project>

0 comments on commit 1abec27

Please sign in to comment.