Skip to content

Commit

Permalink
#5231: Move clip algorithm closer to the Clipper Module. Extend IBrus…
Browse files Browse the repository at this point in the history
…h interface by the classifyPlane() method.

Fix compilation errors in LayerControlDialog.
  • Loading branch information
codereader committed May 21, 2020
1 parent 5c1d80f commit a051f66
Show file tree
Hide file tree
Showing 16 changed files with 150 additions and 128 deletions.
24 changes: 24 additions & 0 deletions include/ibrush.h
Expand Up @@ -90,6 +90,27 @@ class IFace
virtual Matrix4 getTexDefMatrix() const = 0;
};

// Plane classification info used by splitting and CSG algorithms
struct BrushSplitType
{
std::size_t counts[3];

BrushSplitType()
{
counts[0] = 0;
counts[1] = 0;
counts[2] = 0;
}

BrushSplitType& operator+=(const BrushSplitType& other)
{
counts[0] += other.counts[0];
counts[1] += other.counts[1];
counts[2] += other.counts[2];
return *this;
}
};

// Brush Interface
class IBrush
{
Expand Down Expand Up @@ -158,6 +179,9 @@ class IBrush
* Q3-compatibility feature, set the detail/structural flag
*/
virtual void setDetailFlag(DetailFlag newValue) = 0;

// Classify this brush against the given plane, used by clipper and CSG algorithms
virtual BrushSplitType classifyPlane(const Plane3& plane) const = 0;
};

// Forward-declare the Brush object, only accessible from main binary
Expand Down
16 changes: 0 additions & 16 deletions include/iclipper.h
Expand Up @@ -17,22 +17,6 @@ enum PlaneClassification {
ePlaneOn = 2,
};

struct BrushSplitType {
std::size_t counts[3];

BrushSplitType() {
counts[0] = 0;
counts[1] = 0;
counts[2] = 0;
}
BrushSplitType& operator+=(const BrushSplitType& other) {
counts[0] += other.counts[0];
counts[1] += other.counts[1];
counts[2] += other.counts[2];
return *this;
}
};

class ClipPoint;

const char* const MODULE_CLIPPER("Clipper");
Expand Down
3 changes: 2 additions & 1 deletion radiant/Makefile.am
Expand Up @@ -53,7 +53,6 @@ darkradiant_SOURCES = main.cpp \
brush/Face.cpp \
brush/TexDef.cpp \
brush/TextureMatrix.cpp \
brush/csg/BrushByPlaneClipper.cpp \
brush/csg/CSG.cpp \
brush/FacePlane.cpp \
camera/Camera.cpp \
Expand Down Expand Up @@ -341,6 +340,8 @@ darkradiant_SOURCES = main.cpp \
map/RenderableAasFile.cpp \
clipper/ClipPoint.cpp \
clipper/Clipper.cpp \
clipper/SplitAlgorithm.cpp \
clipper/BrushByPlaneClipper.cpp \
log/Console.cpp \
model/ModelScalePreserver.cpp \
model/ModelExporter.cpp \
Expand Down
17 changes: 17 additions & 0 deletions radiant/brush/Brush.cpp
Expand Up @@ -216,6 +216,23 @@ void Brush::setDetailFlag(DetailFlag newValue)
_detailFlag = newValue;
}

BrushSplitType Brush::classifyPlane(const Plane3& plane) const
{
evaluateBRep();

BrushSplitType split;

for (auto face : *this)
{
if (face->contributes())
{
split += face->getWinding().classifyPlane(plane);
}
}

return split;
}

void Brush::evaluateBRep() const {
if(m_planeChanged) {
m_planeChanged = false;
Expand Down
2 changes: 2 additions & 0 deletions radiant/brush/Brush.h
Expand Up @@ -209,6 +209,8 @@ class Brush :
DetailFlag getDetailFlag() const;
void setDetailFlag(DetailFlag newValue);

BrushSplitType classifyPlane(const Plane3& plane) const override;

void evaluateBRep() const;

void transformChanged();
Expand Down
66 changes: 1 addition & 65 deletions radiant/brush/csg/CSG.cpp
Expand Up @@ -24,8 +24,6 @@
#include "wxutil/dialog/MessageBox.h"
#include "wxutil/dialog/MessageBox.h"

#include "BrushByPlaneClipper.h"

namespace brush {
namespace algorithm {

Expand Down Expand Up @@ -123,19 +121,6 @@ void makeRoomForSelectedBrushes(const cmd::ArgumentList& args) {
SceneChangeNotify();
}

BrushSplitType Brush_classifyPlane(const Brush& brush, const Plane3& plane) {
brush.evaluateBRep();

BrushSplitType split;
for (Brush::const_iterator i(brush.begin()); i != brush.end(); ++i) {
if ((*i)->contributes()) {
split += (*i)->getWinding().classifyPlane(plane);
}
}

return split;
}

// Returns true if fragments have been inserted into the given ret_fragments list
bool Brush_subtract(const BrushNodePtr& brush, const Brush& other, BrushPtrVector& ret_fragments)
{
Expand All @@ -152,7 +137,7 @@ bool Brush_subtract(const BrushNodePtr& brush, const Brush& other, BrushPtrVecto

if (!face.contributes()) continue;

BrushSplitType split = Brush_classifyPlane(back->getBrush(), face.plane3());
BrushSplitType split = back->getBrush().classifyPlane(face.plane3());

if (split.counts[ePlaneFront] != 0 && split.counts[ePlaneBack] != 0)
{
Expand Down Expand Up @@ -468,55 +453,6 @@ void mergeSelectedBrushes(const cmd::ArgumentList& args)
SceneChangeNotify();
}

class BrushSetClipPlane :
public SelectionSystem::Visitor
{
Plane3 _plane;
public:
BrushSetClipPlane(const Plane3& plane) :
_plane(plane)
{}

virtual ~BrushSetClipPlane() {}

void visit(const scene::INodePtr& node) const {
BrushNodePtr brush = std::dynamic_pointer_cast<BrushNode>(node);

if (brush != NULL && node->visible()) {
brush->setClipPlane(_plane);
}
}
};

/**
* greebo: Sets the "clip plane" of the selected brushes in the scene.
*/
void setBrushClipPlane(const Plane3& plane) {
BrushSetClipPlane walker(plane);
GlobalSelectionSystem().foreachSelected(walker);
}

/**
* greebo: Splits the selected brushes by the given plane.
*/
void splitBrushesByPlane(const Vector3 planePoints[3], EBrushSplit split)
{
// Collect all selected brushes
BrushPtrVector brushes = selection::algorithm::getSelectedBrushes();

// Instantiate a scoped walker
BrushByPlaneClipper splitter(
planePoints[0],
planePoints[1],
planePoints[2],
split
);

splitter.split(brushes);

SceneChangeNotify();
}

void registerCommands()
{
GlobalCommandSystem().addCommand("CSGSubtract", subtractBrushesFromUnselected);
Expand Down
17 changes: 1 addition & 16 deletions radiant/brush/csg/CSG.h
@@ -1,5 +1,4 @@
#ifndef BRUSH_CSG_H_
#define BRUSH_CSG_H_
#pragma once

#include "iclipper.h"
#include "icommandsystem.h"
Expand Down Expand Up @@ -45,19 +44,6 @@ void subtractBrushesFromUnselected(const cmd::ArgumentList& args);
*/
void mergeSelectedBrushes(const cmd::ArgumentList& args);

/**
* greebo: Sets the "clip plane" of the selected brushes in the scene.
*/
void setBrushClipPlane(const Plane3& plane);

// Classifies the given brush (needed for clipping/csg)
BrushSplitType Brush_classifyPlane(const Brush& brush, const Plane3& plane);

/**
* greebo: Splits the selected brushes by the given plane.
*/
void splitBrushesByPlane(const Vector3 planePoints[3], EBrushSplit split);

/**
* Connect the various events to the functions in this namespace
*/
Expand All @@ -66,4 +52,3 @@ void registerCommands();
} // namespace algorihtm
} // namespace brush

#endif /* BRUSH_CSG_H_ */
@@ -1,18 +1,14 @@
#include "BrushByPlaneClipper.h"

#include "CSG.h"
#include "scenelib.h"
#include "brush/BrushNode.h"
#include "ui/texturebrowser/TextureBrowser.h"

namespace brush
{

namespace algorithm
{

BrushByPlaneClipper::BrushByPlaneClipper(
const Vector3& p0, const Vector3& p1, const Vector3& p2, EBrushSplit split) :
BrushByPlaneClipper::BrushByPlaneClipper(const Vector3& p0, const Vector3& p1,
const Vector3& p2, EBrushSplit split) :
_p0(p0),
_p1(p1),
_p2(p2),
Expand All @@ -30,10 +26,8 @@ void BrushByPlaneClipper::split(const BrushPtrVector& brushes)
return;
}

for (BrushPtrVector::const_iterator i = brushes.begin(); i != brushes.end(); ++i)
for (const BrushNodePtr& node : brushes)
{
const BrushNodePtr& node = *i;

// Don't clip invisible nodes
if (!node->visible())
{
Expand All @@ -52,9 +46,9 @@ void BrushByPlaneClipper::split(const BrushPtrVector& brushes)
// greebo: Analyse the brush to find out which shader is the most used one
getMostUsedTexturing(brush);

BrushSplitType split = Brush_classifyPlane(brush, _split == eFront ? -plane : plane);
BrushSplitType split = brush.classifyPlane(_split == eFront ? -plane : plane);

if (split.counts[ePlaneBack] && split.counts[ePlaneFront])
if (split.counts[ePlaneBack] > 0 && split.counts[ePlaneFront] > 0)
{
// the plane intersects this brush
if (_split == eFrontAndBack)
Expand Down Expand Up @@ -171,4 +165,3 @@ void BrushByPlaneClipper::getMostUsedTexturing(const Brush& brush) const
}

} // namespace algorithm
} // namespace brush
Expand Up @@ -10,7 +10,6 @@

#include "selection/algorithm/Primitives.h"

namespace brush {
namespace algorithm {

class BrushByPlaneClipper
Expand Down Expand Up @@ -45,4 +44,3 @@ class BrushByPlaneClipper
};

} // namespace algorithm
} // namespace brush
11 changes: 6 additions & 5 deletions radiant/clipper/Clipper.cpp
Expand Up @@ -11,6 +11,7 @@
#include "registry/registry.h"
#include "module/StaticModule.h"
#include "ClipPoint.h"
#include "SplitAlgorithm.h"
#include "brush/csg/CSG.h"
#include "debugging/debugging.h"

Expand Down Expand Up @@ -138,7 +139,7 @@ void Clipper::getPlanePoints(Vector3 planepts[3], const AABB& bounds) const {

void Clipper::setClipPlane(const Plane3& plane)
{
brush::algorithm::setBrushClipPlane(plane);
algorithm::setBrushClipPlane(plane);
}

void Clipper::update() {
Expand Down Expand Up @@ -178,7 +179,7 @@ void Clipper::clip() {
AABB bounds(Vector3(0, 0, 0), Vector3(64, 64, 64));
getPlanePoints(planepts, bounds);

brush::algorithm::splitBrushesByPlane(planepts, !_switch ? eFront : eBack);
algorithm::splitBrushesByPlane(planepts, !_switch ? eFront : eBack);

reset();
update();
Expand All @@ -191,7 +192,7 @@ void Clipper::splitClip() {
AABB bounds(Vector3(0, 0, 0), Vector3(64, 64, 64));
getPlanePoints(planepts, bounds);

brush::algorithm::splitBrushesByPlane(planepts, eFrontAndBack);
algorithm::splitBrushesByPlane(planepts, eFrontAndBack);

reset();
update();
Expand Down Expand Up @@ -246,11 +247,11 @@ const std::string& Clipper::getName() const {
const StringSet& Clipper::getDependencies() const {
static StringSet _dependencies;

if (_dependencies.empty()) {
if (_dependencies.empty())
{
_dependencies.insert(MODULE_XMLREGISTRY);
_dependencies.insert(MODULE_COMMANDSYSTEM);
_dependencies.insert(MODULE_PREFERENCESYSTEM);
_dependencies.insert(MODULE_MAINFRAME);
}

return _dependencies;
Expand Down

0 comments on commit a051f66

Please sign in to comment.