dragplanes.h

Go to the documentation of this file.
00001 /*
00002  Copyright (C) 2001-2006, William Joseph.
00003  All Rights Reserved.
00004 
00005  This file is part of GtkRadiant.
00006 
00007  GtkRadiant is free software; you can redistribute it and/or modify
00008  it under the terms of the GNU General Public License as published by
00009  the Free Software Foundation; either version 2 of the License, or
00010  (at your option) any later version.
00011 
00012  GtkRadiant is distributed in the hope that it will be useful,
00013  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  GNU General Public License for more details.
00016 
00017  You should have received a copy of the GNU General Public License
00018  along with GtkRadiant; if not, write to the Free Software
00019  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020  */
00021 
00022 #if !defined(INCLUDED_DRAGPLANES_H)
00023 #define INCLUDED_DRAGPLANES_H
00024 
00025 #include "selectable.h"
00026 #include "selectionlib.h"
00027 #include "math/aabb.h"
00028 #include "math/line.h"
00029 
00030 // local must be a pure rotation
00031 inline Vector3 translation_to_local (const Vector3& translation, const Matrix4& local)
00032 {
00033     return matrix4_get_translation_vec3(matrix4_multiplied_by_matrix4(matrix4_translated_by_vec3(matrix4_transposed(
00034             local), translation), local));
00035 }
00036 
00037 // local must be a pure rotation
00038 inline Vector3 translation_from_local (const Vector3& translation, const Matrix4& local)
00039 {
00040     return matrix4_get_translation_vec3(matrix4_multiplied_by_matrix4(matrix4_translated_by_vec3(local, translation),
00041             matrix4_transposed(local)));
00042 }
00043 
00044 class DragPlanes
00045 {
00046     public:
00047         ObservedSelectable m_selectable_right; // +x
00048         ObservedSelectable m_selectable_left; // -x
00049         ObservedSelectable m_selectable_front; // +y
00050         ObservedSelectable m_selectable_back; // -y
00051         ObservedSelectable m_selectable_top; // +z
00052         ObservedSelectable m_selectable_bottom; // -z
00053         AABB m_bounds;
00054 
00055         DragPlanes (const SelectionChangeCallback& onchanged) :
00056             m_selectable_right(onchanged), m_selectable_left(onchanged), m_selectable_front(onchanged),
00057                     m_selectable_back(onchanged), m_selectable_top(onchanged), m_selectable_bottom(onchanged)
00058         {
00059         }
00060         bool isSelected () const
00061         {
00062             return m_selectable_right.isSelected() || m_selectable_left.isSelected() || m_selectable_front.isSelected()
00063                     || m_selectable_back.isSelected() || m_selectable_top.isSelected()
00064                     || m_selectable_bottom.isSelected();
00065         }
00066         void setSelected (bool selected)
00067         {
00068             m_selectable_right.setSelected(selected);
00069             m_selectable_left.setSelected(selected);
00070             m_selectable_front.setSelected(selected);
00071             m_selectable_back.setSelected(selected);
00072             m_selectable_top.setSelected(selected);
00073             m_selectable_bottom.setSelected(selected);
00074         }
00075         void selectPlanes (const AABB& aabb, Selector& selector, SelectionTest& test,
00076                 const PlaneCallback& selectedPlaneCallback, const Matrix4& rotation = g_matrix4_identity)
00077         {
00078             Line line(test.getNear(), test.getFar());
00079             Vector3 corners[8];
00080             aabb_corners_oriented(aabb, rotation, corners);
00081 
00082             Plane3 planes[6];
00083             aabb_planes_oriented(aabb, rotation, planes);
00084 
00085             for (Vector3* i = corners; i != corners + 8; ++i) {
00086                 *i = line_closest_point(line, *i) - (*i);
00087             }
00088 
00089             if (planes[0].normal().dot(corners[1]) > 0 && planes[0].normal().dot(corners[2]) > 0
00090                     && planes[0].normal().dot(corners[5]) > 0 && planes[0].normal().dot(corners[6]) > 0) {
00091                 Selector_add(selector, m_selectable_right);
00092                 selectedPlaneCallback(planes[0]);
00093             }
00094             if (planes[1].normal().dot(corners[0]) > 0 && planes[1].normal().dot(corners[3]) > 0
00095                     && planes[1].normal().dot(corners[4]) > 0 && planes[1].normal().dot(corners[7]) > 0) {
00096                 Selector_add(selector, m_selectable_left);
00097                 selectedPlaneCallback(planes[1]);
00098             }
00099             if (planes[2].normal().dot(corners[0]) > 0 && planes[2].normal().dot(corners[1]) > 0
00100                     && planes[2].normal().dot(corners[4]) > 0 && planes[2].normal().dot(corners[5]) > 0) {
00101                 Selector_add(selector, m_selectable_front);
00102                 selectedPlaneCallback(planes[2]);
00103             }
00104             if (planes[3].normal().dot(corners[2]) > 0 && planes[3].normal().dot(corners[3]) > 0
00105                     && planes[3].normal().dot(corners[6]) > 0 && planes[3].normal().dot(corners[7]) > 0) {
00106                 Selector_add(selector, m_selectable_back);
00107                 selectedPlaneCallback(planes[3]);
00108             }
00109             if (planes[4].normal().dot(corners[0]) > 0 && planes[4].normal().dot(corners[1]) > 0
00110                     && planes[4].normal().dot(corners[2]) > 0 && planes[4].normal().dot(corners[3]) > 0) {
00111                 Selector_add(selector, m_selectable_top);
00112                 selectedPlaneCallback(planes[4]);
00113             }
00114             if (planes[5].normal().dot(corners[4]) > 0 && planes[5].normal().dot(corners[5]) > 0
00115                     && planes[5].normal().dot(corners[6]) > 0 && planes[5].normal().dot(corners[7]) > 0) {
00116                 Selector_add(selector, m_selectable_bottom);
00117                 selectedPlaneCallback(planes[5]);
00118             }
00119 
00120             m_bounds = aabb;
00121         }
00122         void selectReversedPlanes (const AABB& aabb, Selector& selector, const SelectedPlanes& selectedPlanes,
00123                 const Matrix4& rotation = g_matrix4_identity)
00124         {
00125             Plane3 planes[6];
00126             aabb_planes_oriented(aabb, rotation, planes);
00127 
00128             if (selectedPlanes.contains(plane3_flipped(planes[0]))) {
00129                 Selector_add(selector, m_selectable_right);
00130             }
00131             if (selectedPlanes.contains(plane3_flipped(planes[1]))) {
00132                 Selector_add(selector, m_selectable_left);
00133             }
00134             if (selectedPlanes.contains(plane3_flipped(planes[2]))) {
00135                 Selector_add(selector, m_selectable_front);
00136             }
00137             if (selectedPlanes.contains(plane3_flipped(planes[3]))) {
00138                 Selector_add(selector, m_selectable_back);
00139             }
00140             if (selectedPlanes.contains(plane3_flipped(planes[4]))) {
00141                 Selector_add(selector, m_selectable_top);
00142             }
00143             if (selectedPlanes.contains(plane3_flipped(planes[5]))) {
00144                 Selector_add(selector, m_selectable_bottom);
00145             }
00146         }
00147         AABB evaluateResize (const Vector3& translation) const
00148         {
00149             Vector3 min = m_bounds.origin - m_bounds.extents;
00150             Vector3 max = m_bounds.origin + m_bounds.extents;
00151             if (m_bounds.extents[0] != 0) {
00152                 if (m_selectable_right.isSelected()) {
00153                     max[0] += translation[0];
00154                 }
00155                 if (m_selectable_left.isSelected()) {
00156                     min[0] += translation[0];
00157                 }
00158             }
00159             if (m_bounds.extents[1] != 0) {
00160                 if (m_selectable_front.isSelected()) {
00161                     max[1] += translation[1];
00162                 }
00163                 if (m_selectable_back.isSelected()) {
00164                     min[1] += translation[1];
00165                 }
00166             }
00167             if (m_bounds.extents[2] != 0) {
00168                 if (m_selectable_top.isSelected()) {
00169                     max[2] += translation[2];
00170                 }
00171                 if (m_selectable_bottom.isSelected()) {
00172                     min[2] += translation[2];
00173                 }
00174             }
00175 
00176             return AABB(vector3_mid(min, max), (max - min) * 0.5);
00177         }
00178         AABB evaluateResize (const Vector3& translation, const Matrix4& rotation) const
00179         {
00180             AABB aabb(evaluateResize(translation_to_local(translation, rotation)));
00181             aabb.origin = m_bounds.origin + translation_from_local(aabb.origin - m_bounds.origin, rotation);
00182             return aabb;
00183         }
00184         Matrix4 evaluateTransform (const Vector3& translation) const
00185         {
00186             AABB aabb(evaluateResize(translation));
00187             Vector3 scale(m_bounds.extents[0] != 0 ? aabb.extents[0] / m_bounds.extents[0] : 1, m_bounds.extents[1]
00188                     != 0 ? aabb.extents[1] / m_bounds.extents[1] : 1, m_bounds.extents[2] != 0 ? aabb.extents[2]
00189                     / m_bounds.extents[2] : 1);
00190 
00191             Matrix4 matrix = Matrix4::getTranslation(aabb.origin - m_bounds.origin);
00192             matrix4_pivoted_scale_by_vec3(matrix, scale, m_bounds.origin);
00193 
00194             return matrix;
00195         }
00196 };
00197 
00198 #endif

Generated by  doxygen 1.6.2