Skip to content

Commit

Permalink
#5711: Add unimplemented legacy Q3 brush def exporter
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Aug 29, 2021
1 parent 9979ea1 commit a34ace1
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 2 deletions.
5 changes: 3 additions & 2 deletions radiantcore/map/format/Quake3MapWriter.h
Expand Up @@ -2,6 +2,7 @@

#include "Doom3MapWriter.h"
#include "primitivewriters/BrushDefExporter.h"
#include "primitivewriters/LegacyBrushDefExporter.h"
#include "primitivewriters/PatchDefExporter.h"
#include "Quake3MapFormat.h"

Expand All @@ -26,8 +27,8 @@ class Quake3MapWriter :
// Primitive count comment
stream << "// brush " << _primitiveCount++ << std::endl;

// Export brushDef definition to stream
BrushDefExporter::exportBrush(stream, brush); // TODO
// Export old brush syntax to stream
LegacyBrushDefExporter::exportBrush(stream, brush);
}

virtual void beginWritePatch(const IPatchNodePtr& patch, std::ostream& stream) override
Expand Down
140 changes: 140 additions & 0 deletions radiantcore/map/format/primitivewriters/LegacyBrushDefExporter.h
@@ -0,0 +1,140 @@
#pragma once

#include "ibrush.h"
#include "math/Plane3.h"
#include "math/Matrix4.h"
#include "shaderlib.h"

#include "string/predicate.h"
#include "ExportUtil.h"

namespace map
{

class LegacyBrushDefExporter
{
public:

// Writes an old Q3-style brush definition from the given brush to the given stream
static void exportBrush(std::ostream& stream, const IBrushNodePtr& brushNode)
{
const IBrush& brush = brushNode->getIBrush();

// Brush decl header
stream << "{" << std::endl;
stream << "brushDef" << std::endl;
stream << "{" << std::endl;

// Iterate over each brush face, exporting the tokens from all faces
for (std::size_t i = 0; i < brush.getNumFaces(); ++i)
{
writeFace(stream, brush.getFace(i), brush.getDetailFlag());
}

// Close brush contents and header
stream << "}" << std::endl << "}" << std::endl;
}

/*
brushDef
{
( -64 64 64 ) ( 64 -64 64 ) ( -64 -64 64 ) ( ( 0.015625 0 -0 ) ( -0 0.015625 0 ) ) common/caulk 0 0 0
( -64 64 64 ) ( 64 64 -64 ) ( 64 64 64 ) ( ( 0.015625 0 0 ) ( 0 0.015625 0 ) ) common/caulk 0 0 0
( 64 64 64 ) ( 64 -64 -64 ) ( 64 -64 64 ) ( ( 0.015625 0 -0 ) ( -0 0.015625 0 ) ) common/caulk 0 0 0
( 64 64 -64 ) ( -64 -64 -64 ) ( 64 -64 -64 ) ( ( 0.015625 0 -0 ) ( -0 0.015625 0 ) ) common/caulk 0 0 0
( 64 -64 -64 ) ( -64 -64 64 ) ( 64 -64 64 ) ( ( 0.015625 0 -0 ) ( -0 0.015625 0 ) ) common/caulk 0 0 0
( -64 -64 64 ) ( -64 64 -64 ) ( -64 64 64 ) ( ( 0.015625 0 -0 ) ( -0 0.015625 0 ) ) common/caulk 0 0 0
}
*/

private:

static void writeFace(std::ostream& stream, const IFace& face, IBrush::DetailFlag detailFlag)
{
// greebo: Don't export faces with degenerate or empty windings (they are "non-contributing")
const IWinding& winding = face.getWinding();

if (winding.size() <= 2)
{
return;
}

// Each face plane is defined by three points

stream << "( ";
writeDoubleSafe(winding[2].vertex.x(), stream);
stream << " ";
writeDoubleSafe(winding[2].vertex.y(), stream);
stream << " ";
writeDoubleSafe(winding[2].vertex.z(), stream);
stream << " ";
stream << ") ";

stream << "( ";
writeDoubleSafe(winding[0].vertex.x(), stream);
stream << " ";
writeDoubleSafe(winding[0].vertex.y(), stream);
stream << " ";
writeDoubleSafe(winding[0].vertex.z(), stream);
stream << " ";
stream << ") ";

stream << "( ";
writeDoubleSafe(winding[1].vertex.x(), stream);
stream << " ";
writeDoubleSafe(winding[1].vertex.y(), stream);
stream << " ";
writeDoubleSafe(winding[1].vertex.z(), stream);
stream << " ";
stream << ") ";

// Write TexDef
Matrix4 texdef = face.getTexDefMatrix();
stream << "( ";

stream << "( ";
writeDoubleSafe(texdef.xx(), stream);
stream << " ";
writeDoubleSafe(texdef.yx(), stream);
stream << " ";
writeDoubleSafe(texdef.tx(), stream);
stream << " ) ";

stream << "( ";
writeDoubleSafe(texdef.xy(), stream);
stream << " ";
writeDoubleSafe(texdef.yy(), stream);
stream << " ";
writeDoubleSafe(texdef.ty(), stream);
stream << " ) ";

stream << ") ";

// Write Shader (without quotes)
const std::string& shaderName = face.getShader();

if (shaderName.empty())
{
stream << "_default ";
}
else
{
if (string::starts_with(shaderName, GlobalTexturePrefix_get()))
{
// brushDef has an implicit "textures/" not written to the map, cut it off
stream << "" << shader_get_textureName(shaderName.c_str()) << " ";
}
else
{
stream << "" << shaderName << " ";
}
}

// Export (dummy) contents/flags
stream << detailFlag << " 0 0";

stream << std::endl;
}
};

}
1 change: 1 addition & 0 deletions tools/msvc/DarkRadiantCore.vcxproj
Expand Up @@ -848,6 +848,7 @@
<ClInclude Include="..\..\radiantcore\map\format\primitivewriters\BrushDef3Exporter.h" />
<ClInclude Include="..\..\radiantcore\map\format\primitivewriters\BrushDefExporter.h" />
<ClInclude Include="..\..\radiantcore\map\format\primitivewriters\ExportUtil.h" />
<ClInclude Include="..\..\radiantcore\map\format\primitivewriters\LegacyBrushDefExporter.h" />
<ClInclude Include="..\..\radiantcore\map\format\primitivewriters\PatchDefExporter.h" />
<ClInclude Include="..\..\radiantcore\map\format\Quake3MapFormat.h" />
<ClInclude Include="..\..\radiantcore\map\format\Quake3MapReader.h" />
Expand Down
3 changes: 3 additions & 0 deletions tools/msvc/DarkRadiantCore.vcxproj.filters
Expand Up @@ -2187,5 +2187,8 @@
<ClInclude Include="..\..\radiantcore\map\format\primitivewriters\ExportUtil.h">
<Filter>src\map\format\primitivewriters</Filter>
</ClInclude>
<ClInclude Include="..\..\radiantcore\map\format\primitivewriters\LegacyBrushDefExporter.h">
<Filter>src\map\format\primitivewriters</Filter>
</ClInclude>
</ItemGroup>
</Project>

0 comments on commit a34ace1

Please sign in to comment.