Skip to content

Commit

Permalink
#5115: Convert patch surface to indexed model surface before passing …
Browse files Browse the repository at this point in the history
…them to the exporter.

This way the polygons are not separated and the normals can be smoothed.
  • Loading branch information
codereader committed Nov 8, 2020
1 parent 49d1e84 commit 54fde58
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 2 deletions.
11 changes: 9 additions & 2 deletions radiantcore/model/export/ModelExporter.cpp
Expand Up @@ -13,6 +13,8 @@
#include <stdexcept>
#include <fstream>

#include "PatchSurface.h"

namespace model
{

Expand Down Expand Up @@ -196,7 +198,9 @@ void ModelExporter::processPatch(const scene::INodePtr& node)
if (!isExportableMaterial(materialName)) return;

PatchMesh mesh = patch->getTesselatedPatchMesh();
Matrix4 exportTransform = node->localToWorld().getPremultipliedBy(_centerTransform);

#if 0
std::vector<model::ModelPolygon> polys;

for (std::size_t h = 0; h < mesh.height - 1; ++h)
Expand All @@ -219,9 +223,12 @@ void ModelExporter::processPatch(const scene::INodePtr& node)
}
}

Matrix4 exportTransform = node->localToWorld().getPremultipliedBy(_centerTransform);

_exporter->addPolygons(materialName, polys, exportTransform);
#else
// Convert the patch mesh to an indexed surface
PatchSurface surface(materialName, mesh);
_exporter->addSurface(surface, exportTransform);
#endif
}

void ModelExporter::processBrush(const scene::INodePtr& node)
Expand Down
111 changes: 111 additions & 0 deletions radiantcore/model/export/PatchSurface.h
@@ -0,0 +1,111 @@
#pragma once

#include "ipatch.h"
#include "imodelsurface.h"

namespace model
{

// Adapter methods to convert patch vertices to ArbitraryMeshVertex type
inline ArbitraryMeshVertex convertPatchVertex(const VertexNT& in)
{
// Colour will be set to 1,1,1 by the constructor
return ArbitraryMeshVertex(in.vertex, in.normal, in.texcoord);
}

/**
* Adapter class converting a PatchTesselation object into
* a surface suitable for exporting it to a model file.
* The PatchSurface class will generate the triangle indices
* (clockwise) as expeced by the IModelExporter interface.
*/
class PatchSurface :
public IIndexedModelSurface
{
private:
std::vector<ArbitraryMeshVertex> _vertices;
std::vector<unsigned int> _indices;
std::string _materialName;

public:
PatchSurface(const std::string& materialName, PatchMesh& mesh) :
_materialName(materialName)
{
assert(mesh.width >= 2 && mesh.height >= 2);

_vertices.reserve(mesh.vertices.size());
_indices.reserve((mesh.height - 1) * (mesh.width- 1) * 6); // 6 => 2 triangles per quad

// Load all the vertices into the target vector
std::transform(mesh.vertices.begin(), mesh.vertices.end(),
std::back_inserter(_vertices), convertPatchVertex);

// Generate the indices to define the triangles in clockwise order
for (std::size_t h = 0; h < mesh.height - 1; ++h)
{
auto rowOffset = h * mesh.width;

for (std::size_t w = 0; w < mesh.width - 1; ++w)
{
_indices.push_back(rowOffset + w + mesh.width);
_indices.push_back(rowOffset + w + 1);
_indices.push_back(rowOffset + w);

_indices.push_back(rowOffset + w + mesh.width);
_indices.push_back(rowOffset + w + mesh.width + 1);
_indices.push_back(rowOffset + w + 1);
}
}
}

// Inherited via IIndexedModelSurface
int getNumVertices() const override
{
return static_cast<int>(_vertices.size());
}

int getNumTriangles() const override
{
return static_cast<int>(_indices.size() / 3); // 3 indices per triangle
}

const ArbitraryMeshVertex& getVertex(int vertexNum) const override
{
return _vertices[vertexNum];
}

ModelPolygon getPolygon(int polygonIndex) const override
{
assert(polygonIndex >= 0 && polygonIndex * 3 < static_cast<int>(_indices.size()));

ModelPolygon poly;

poly.a = _vertices[_indices[polygonIndex * 3]];
poly.b = _vertices[_indices[polygonIndex * 3 + 1]];
poly.c = _vertices[_indices[polygonIndex * 3 + 2]];

return poly;
}

const std::string& getDefaultMaterial() const override
{
return _materialName;
}

const std::string& getActiveMaterial() const override
{
return _materialName;
}

const std::vector<ArbitraryMeshVertex>& getVertexArray() const override
{
return _vertices;
}

const std::vector<unsigned int>& getIndexArray() const override
{
return _indices;
}
};

}
1 change: 1 addition & 0 deletions tools/msvc/DarkRadiantCore.vcxproj
Expand Up @@ -857,6 +857,7 @@
<ClInclude Include="..\..\radiantcore\model\export\ModelExporter.h" />
<ClInclude Include="..\..\radiantcore\model\export\ModelExporterBase.h" />
<ClInclude Include="..\..\radiantcore\model\export\ModelScalePreserver.h" />
<ClInclude Include="..\..\radiantcore\model\export\PatchSurface.h" />
<ClInclude Include="..\..\radiantcore\model\export\ScaledModelExporter.h" />
<ClInclude Include="..\..\radiantcore\model\export\WavefrontExporter.h" />
<ClInclude Include="..\..\radiantcore\model\md5\MD5Anim.h" />
Expand Down
3 changes: 3 additions & 0 deletions tools/msvc/DarkRadiantCore.vcxproj.filters
Expand Up @@ -2034,5 +2034,8 @@
<ClInclude Include="..\..\radiantcore\camera\CameraManager.h">
<Filter>src\camera</Filter>
</ClInclude>
<ClInclude Include="..\..\radiantcore\model\export\PatchSurface.h">
<Filter>src\model\export</Filter>
</ClInclude>
</ItemGroup>
</Project>

0 comments on commit 54fde58

Please sign in to comment.