File: SelectionVolume.h

package info (click to toggle)
darkradiant 3.9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 41,080 kB
  • sloc: cpp: 264,743; ansic: 10,659; python: 1,852; xml: 1,650; sh: 92; makefile: 21
file content (144 lines) | stat: -rw-r--r-- 4,986 bytes parent folder | download | duplicates (3)
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]);
}