2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #if !defined(INCLUDED_DRAGPLANES_H)
23 #define INCLUDED_DRAGPLANES_H
25 #include "selectable.h"
26 #include "selectionlib.h"
27 #include "math/aabb.h"
28 #include "math/line.h"
33 ObservedSelectable m_selectable_right; // +x
34 ObservedSelectable m_selectable_left; // -x
35 ObservedSelectable m_selectable_front; // +y
36 ObservedSelectable m_selectable_back; // -y
37 ObservedSelectable m_selectable_top; // +z
38 ObservedSelectable m_selectable_bottom; // -z
41 DragPlanes(const SelectionChangeCallback& onchanged) :
42 m_selectable_right(onchanged),
43 m_selectable_left(onchanged),
44 m_selectable_front(onchanged),
45 m_selectable_back(onchanged),
46 m_selectable_top(onchanged),
47 m_selectable_bottom(onchanged)
50 bool isSelected() const
52 return m_selectable_right.isSelected()
53 || m_selectable_left.isSelected()
54 || m_selectable_front.isSelected()
55 || m_selectable_back.isSelected()
56 || m_selectable_top.isSelected()
57 || m_selectable_bottom.isSelected();
59 void setSelected(bool selected)
61 m_selectable_right.setSelected(selected);
62 m_selectable_left.setSelected(selected);
63 m_selectable_front.setSelected(selected);
64 m_selectable_back.setSelected(selected);
65 m_selectable_top.setSelected(selected);
66 m_selectable_bottom.setSelected(selected);
68 void selectPlanes(const AABB& aabb, Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback)
70 Line line(test.getNear(), test.getFar());
72 aabb_corners(aabb, corners);
74 aabb_planes(aabb, planes);
76 for(Vector3* i = corners; i != corners + 8; ++i)
78 *i = vector3_subtracted(line_closest_point(line, *i), *i);
81 if(vector3_dot(planes[0].normal(), corners[1]) > 0
82 && vector3_dot(planes[0].normal(), corners[2]) > 0
83 && vector3_dot(planes[0].normal(), corners[5]) > 0
84 && vector3_dot(planes[0].normal(), corners[6]) > 0)
86 Selector_add(selector, m_selectable_right);
87 selectedPlaneCallback(planes[0]);
88 //globalOutputStream() << "right\n";
90 if(vector3_dot(planes[1].normal(), corners[0]) > 0
91 && vector3_dot(planes[1].normal(), corners[3]) > 0
92 && vector3_dot(planes[1].normal(), corners[4]) > 0
93 && vector3_dot(planes[1].normal(), corners[7]) > 0)
95 Selector_add(selector, m_selectable_left);
96 selectedPlaneCallback(planes[1]);
97 //globalOutputStream() << "left\n";
99 if(vector3_dot(planes[2].normal(), corners[0]) > 0
100 && vector3_dot(planes[2].normal(), corners[1]) > 0
101 && vector3_dot(planes[2].normal(), corners[4]) > 0
102 && vector3_dot(planes[2].normal(), corners[5]) > 0)
104 Selector_add(selector, m_selectable_front);
105 selectedPlaneCallback(planes[2]);
106 //globalOutputStream() << "front\n";
108 if(vector3_dot(planes[3].normal(), corners[2]) > 0
109 && vector3_dot(planes[3].normal(), corners[3]) > 0
110 && vector3_dot(planes[3].normal(), corners[6]) > 0
111 && vector3_dot(planes[3].normal(), corners[7]) > 0)
113 Selector_add(selector, m_selectable_back);
114 selectedPlaneCallback(planes[3]);
115 //globalOutputStream() << "back\n";
117 if(vector3_dot(planes[4].normal(), corners[0]) > 0
118 && vector3_dot(planes[4].normal(), corners[1]) > 0
119 && vector3_dot(planes[4].normal(), corners[2]) > 0
120 && vector3_dot(planes[4].normal(), corners[3]) > 0)
122 Selector_add(selector, m_selectable_top);
123 selectedPlaneCallback(planes[4]);
124 //globalOutputStream() << "top\n";
126 if(vector3_dot(planes[5].normal(), corners[4]) > 0
127 && vector3_dot(planes[5].normal(), corners[5]) > 0
128 && vector3_dot(planes[5].normal(), corners[6]) > 0
129 && vector3_dot(planes[5].normal(), corners[7]) > 0)
131 Selector_add(selector, m_selectable_bottom);
132 //globalOutputStream() << "bottom\n";
133 selectedPlaneCallback(planes[5]);
138 void selectReversedPlanes(const AABB& aabb, Selector& selector, const SelectedPlanes& selectedPlanes)
141 aabb_planes(aabb, planes);
143 if(selectedPlanes.contains(plane3_flipped(planes[0])))
145 Selector_add(selector, m_selectable_right);
147 if(selectedPlanes.contains(plane3_flipped(planes[1])))
149 Selector_add(selector, m_selectable_left);
151 if(selectedPlanes.contains(plane3_flipped(planes[2])))
153 Selector_add(selector, m_selectable_front);
155 if(selectedPlanes.contains(plane3_flipped(planes[3])))
157 Selector_add(selector, m_selectable_back);
159 if(selectedPlanes.contains(plane3_flipped(planes[4])))
161 Selector_add(selector, m_selectable_top);
163 if(selectedPlanes.contains(plane3_flipped(planes[5])))
165 Selector_add(selector, m_selectable_bottom);
168 Matrix4 evaluateTransform(const Vector3& translation) const
170 Vector3 min = m_bounds.origin - m_bounds.extents;
171 Vector3 max = m_bounds.origin + m_bounds.extents;
172 Vector3 origin = m_bounds.origin;
173 Vector3 extents = m_bounds.extents;
176 if(m_selectable_right.isSelected())
178 max[0] += translation[0];
179 //globalOutputStream() << "moving right\n";
181 if(m_selectable_left.isSelected())
183 min[0] += translation[0];
184 //globalOutputStream() << "moving left\n";
189 if(m_selectable_front.isSelected())
191 max[1] += translation[1];
192 //globalOutputStream() << "moving front\n";
194 if(m_selectable_back.isSelected())
196 min[1] += translation[1];
197 //globalOutputStream() << "moving back\n";
202 if(m_selectable_top.isSelected())
204 max[2] += translation[2];
205 //globalOutputStream() << "moving top\n";
207 if(m_selectable_bottom.isSelected())
209 min[2] += translation[2];
210 //globalOutputStream() << "moving bottom\n";
214 Vector3 originTransformed(vector3_mid(min, max));
215 Vector3 scale(vector3_scaled(vector3_subtracted(max, min), 0.5));
219 scale[0] /= extents[0];
227 scale[1] /= extents[1];
235 scale[2] /= extents[2];
242 Matrix4 matrix(matrix4_translation_for_vec3(originTransformed - origin));
243 matrix4_pivoted_scale_by_vec3(matrix, scale, origin);