1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
#pragma once
#include "iscenegraph.h"
#include "../Rectangle.h"
#include "math/Matrix4.h"
#include "math/Vector3.h"
#include "iselectiontest.h"
#include "render/View.h"
#include "BestPoint.h"
inline SelectionIntersection select_point_from_clipped(Vector4& clipped)
{
return SelectionIntersection(static_cast<float>(clipped[2] / clipped[3]),
static_cast<float>(Vector3(clipped[0] / clipped[3], clipped[1] / clipped[3], 0).getLengthSquared()));
}
class SelectionVolume :
public SelectionTest
{
Matrix4 _local2view;
render::View _view;
clipcull_t _cull;
Vector3 _near;
Vector3 _far;
public:
SelectionVolume(const render::View& view) :
_view(view)
{}
const VolumeTest& getVolume() const override
{
return _view;
}
const Vector3& getNear() const override
{
return _near;
}
const Vector3& getFar() const override
{
return _far;
}
void BeginMesh(const Matrix4& localToWorld, bool twoSided) override
{
_local2view = _view.GetViewProjection().getMultipliedBy(localToWorld);
// Cull back-facing polygons based on winding being clockwise or counter-clockwise.
// Don't cull if the material is twosided or the view is wireframe
_cull = twoSided || !_view.fill() ? eClipCullNone :
(localToWorld.getHandedness() == Matrix4::RIGHTHANDED) ? eClipCullCW : eClipCullCCW;
Matrix4 screen2world(_local2view.getFullInverse());
_near = screen2world.transformPoint(Vector3(0, 0, -1));
_far = screen2world.transformPoint(Vector3(0, 0, 1));
}
void TestPoint(const Vector3& point, SelectionIntersection& best) override
{
Vector4 clipped;
if (clipPoint(_local2view, point, clipped) == c_CLIP_PASS)
{
best = select_point_from_clipped(clipped);
}
}
void TestPolygon(const VertexPointer& vertices, std::size_t count, SelectionIntersection& best) override
{
Vector4 clipped[9];
for (std::size_t i = 0; i + 2 < count; ++i)
{
BestPoint(clipTriangle(_local2view, vertices[0], vertices[i + 1],
vertices[i + 2], clipped),
clipped, best, _cull);
}
}
void TestLineStrip(const VertexPointer& vertices, std::size_t count, SelectionIntersection& best) override
{
if (count == 0)
return;
Vector4 clipped[9];
for (VertexPointer::iterator i = vertices.begin(), end = i + count, next = i + 1; next != end; i = next, ++next)
{
BestPoint(clipLine(_local2view, *i, *next, clipped), clipped, best,
_cull);
}
}
void TestTriangles(const VertexPointer& vertices, const IndexPointer& indices, SelectionIntersection& best) override
{
Vector4 clipped[9];
for (IndexPointer::iterator i(indices.begin()); i != indices.end(); i += 3)
{
BestPoint(clipTriangle(_local2view, vertices[*i],
vertices[*(i + 1)], vertices[*(i + 2)],
clipped),
clipped, best, _cull);
}
}
void TestQuads(const VertexPointer& vertices, const IndexPointer& indices, SelectionIntersection& best) override
{
Vector4 clipped[9];
for (IndexPointer::iterator i(indices.begin()); i != indices.end(); i += 4)
{
BestPoint(clipTriangle(_local2view, vertices[*i],
vertices[*(i + 1)], vertices[*(i + 3)],
clipped),
clipped, best, _cull);
BestPoint(clipTriangle(_local2view, vertices[*(i + 1)],
vertices[*(i + 2)], vertices[*(i + 3)],
clipped),
clipped, best, _cull);
}
}
void TestQuadStrip(const VertexPointer& vertices, const IndexPointer& indices, SelectionIntersection& best) override
{
Vector4 clipped[9];
for (IndexPointer::iterator i(indices.begin()); i + 2 != indices.end(); i += 2)
{
BestPoint(clipTriangle(_local2view, vertices[*i],
vertices[*(i + 1)], vertices[*(i + 2)],
clipped),
clipped, best, _cull);
BestPoint(clipTriangle(_local2view, vertices[*(i + 2)],
vertices[*(i + 1)], vertices[*(i + 3)],
clipped),
clipped, best, _cull);
}
}
};
// --------------------------------------------------------------------------------
inline void ConstructSelectionTest(render::View& view, const selection::Rectangle& selection_box)
{
view.EnableScissor(selection_box.min[0], selection_box.max[0],
selection_box.min[1], selection_box.max[1]);
}
|