2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
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_WINDING_H )
23 #define INCLUDED_WINDING_H
25 #include "debugging/debugging.h"
29 #include "math/vector.h"
30 #include "container/array.h"
38 const float ProjectionAxisEpsilon = static_cast<float>( 0.0001 );
40 inline bool projectionaxis_better(float axis, float other)
42 return fabs(axis) > fabs(other) + ProjectionAxisEpsilon;
45 /// \brief Texture axis precedence: Z > X > Y
46 inline ProjectionAxis projectionaxis_for_normal(const Vector3 &normal)
48 return (projectionaxis_better(normal[eProjectionAxisY], normal[eProjectionAxisX]))
49 ? (projectionaxis_better(normal[eProjectionAxisY], normal[eProjectionAxisZ]))
52 : (projectionaxis_better(normal[eProjectionAxisX], normal[eProjectionAxisZ]))
59 indexremap_t(std::size_t _x, std::size_t _y, std::size_t _z)
67 inline indexremap_t indexremap_for_projectionaxis(const ProjectionAxis axis)
70 case eProjectionAxisX:
71 return indexremap_t(1, 2, 0);
72 case eProjectionAxisY:
73 return indexremap_t(2, 0, 1);
75 return indexremap_t(0, 1, 2);
79 enum PlaneClassification {
85 #define MAX_POINTS_ON_WINDING 64
86 const std::size_t c_brush_maxFaces = 1024;
100 typedef Array<WindingVertex> container_type;
102 std::size_t numpoints;
103 container_type points;
105 typedef container_type::iterator iterator;
106 typedef container_type::const_iterator const_iterator;
108 Winding() : numpoints(0)
112 Winding(std::size_t size) : numpoints(0), points(size)
116 void resize(std::size_t size)
124 return points.begin();
127 const_iterator begin() const
129 return points.begin();
134 return points.begin() + numpoints;
137 const_iterator end() const
139 return points.begin() + numpoints;
142 WindingVertex &operator[](std::size_t index)
144 ASSERT_MESSAGE(index < points.size(), "winding: index out of bounds");
145 return points[index];
148 const WindingVertex &operator[](std::size_t index) const
150 ASSERT_MESSAGE(index < points.size(), "winding: index out of bounds");
151 return points[index];
154 void push_back(const WindingVertex &point)
156 points[numpoints] = point;
160 void erase(iterator point)
162 for (iterator i = point + 1; i != end(); point = i, ++i) {
169 typedef BasicVector3<double> DoubleVector3;
173 DoubleVector3 origin;
174 DoubleVector3 direction;
177 class FixedWindingVertex {
179 DoubleVector3 vertex;
181 std::size_t adjacent;
183 FixedWindingVertex(const DoubleVector3 &vertex_, const DoubleLine &edge_, std::size_t adjacent_)
184 : vertex(vertex_), edge(edge_), adjacent(adjacent_)
189 struct FixedWinding {
190 typedef std::vector<FixedWindingVertex> Points;
195 points.reserve(MAX_POINTS_ON_WINDING);
198 FixedWindingVertex &front()
200 return points.front();
203 const FixedWindingVertex &front() const
205 return points.front();
208 FixedWindingVertex &back()
210 return points.back();
213 const FixedWindingVertex &back() const
215 return points.back();
223 void push_back(const FixedWindingVertex &point)
225 points.push_back(point);
228 std::size_t size() const
230 return points.size();
233 FixedWindingVertex &operator[](std::size_t index)
235 //ASSERT_MESSAGE(index < MAX_POINTS_ON_WINDING, "winding: index out of bounds");
236 return points[index];
239 const FixedWindingVertex &operator[](std::size_t index) const
241 //ASSERT_MESSAGE(index < MAX_POINTS_ON_WINDING, "winding: index out of bounds");
242 return points[index];
248 inline void Winding_forFixedWinding(Winding &winding, const FixedWinding &fixed)
250 winding.resize(fixed.size());
251 winding.numpoints = fixed.size();
252 for (std::size_t i = 0; i < fixed.size(); ++i) {
253 winding[i].vertex[0] = static_cast<float>( fixed[i].vertex[0] );
254 winding[i].vertex[1] = static_cast<float>( fixed[i].vertex[1] );
255 winding[i].vertex[2] = static_cast<float>( fixed[i].vertex[2] );
256 winding[i].adjacent = fixed[i].adjacent;
260 inline std::size_t Winding_wrap(const Winding &winding, std::size_t i)
262 ASSERT_MESSAGE(winding.numpoints != 0, "Winding_wrap: empty winding");
263 return i % winding.numpoints;
266 inline std::size_t Winding_next(const Winding &winding, std::size_t i)
268 return Winding_wrap(winding, ++i);
274 void Winding_createInfinite(FixedWinding &w, const Plane3 &plane, double infinity);
276 const double ON_EPSILON = 1.0 / (1 << 8);
278 /// \brief Returns true if edge (\p x, \p y) is smaller than the epsilon used to classify winding points against a plane.
279 inline bool Edge_isDegenerate(const Vector3 &x, const Vector3 &y)
281 return vector3_length_squared(y - x) < (ON_EPSILON * ON_EPSILON);
284 void Winding_Clip(const FixedWinding &winding, const Plane3 &plane, const Plane3 &clipPlane, std::size_t adjacent,
285 FixedWinding &clipped);
287 struct brushsplit_t {
295 brushsplit_t &operator+=(const brushsplit_t &other)
297 counts[0] += other.counts[0];
298 counts[1] += other.counts[1];
299 counts[2] += other.counts[2];
303 std::size_t counts[3];
306 brushsplit_t Winding_ClassifyPlane(const Winding &w, const Plane3 &plane);
308 bool Winding_PlanesConcave(const Winding &w1, const Winding &w2, const Plane3 &plane1, const Plane3 &plane2);
310 bool Winding_TestPlane(const Winding &w, const Plane3 &plane, bool flipped);
312 std::size_t Winding_FindAdjacent(const Winding &w, std::size_t face);
314 std::size_t Winding_Opposite(const Winding &w, const std::size_t index, const std::size_t other);
316 std::size_t Winding_Opposite(const Winding &w, std::size_t index);
318 void Winding_Centroid(const Winding &w, const Plane3 &plane, Vector3 ¢roid);
321 inline void Winding_printConnectivity(Winding &winding)
323 for (Winding::iterator i = winding.begin(); i != winding.end(); ++i) {
324 std::size_t vertexIndex = std::distance(winding.begin(), i);
325 globalOutputStream() << "vertex: " << Unsigned(vertexIndex) << " adjacent: " << Unsigned((*i).adjacent) << "\n";