]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/bobtoolz/DPlane.cpp
Merge branch 'fix-fast' into 'master'
[xonotic/netradiant.git] / contrib / bobtoolz / DPlane.cpp
1 /*
2    BobToolz plugin for GtkRadiant
3    Copyright (C) 2001 Gordon Biggans
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 // DPlane.cpp: implementation of the DPlane class.
21 //
22 //////////////////////////////////////////////////////////////////////
23
24 #include "DPlane.h"
25
26 #include <list>
27
28 #include "DPoint.h"
29 #include "DWinding.h"
30
31 #include "str.h"
32 #include "misc.h"
33
34 //////////////////////////////////////////////////////////////////////
35 // Construction/Destruction
36 //////////////////////////////////////////////////////////////////////
37
38 DPlane::DPlane(const vec3_t va, const vec3_t vb, const vec3_t vc, const _QERFaceData *texData)
39 {
40     MakeNormal(va, vb, vc, normal);
41     if (VectorNormalize(normal, normal) == 0) {  // normalizes and returns length
42         globalErrorStream() << "DPlane::DPlane: Bad Normal.\n";
43     }
44
45     _d = (normal[0] * va[0]) + (normal[1] * va[1]) + (normal[2] * va[2]);
46
47     VectorCopy(va, points[0]);
48     VectorCopy(vb, points[1]);
49     VectorCopy(vc, points[2]);
50
51     m_bChkOk = true;
52
53     if (texData) {
54         memcpy(&texInfo, texData, sizeof(_QERFaceData));
55     } else {
56         FillDefaultTexture(&texInfo, points[0], points[1], points[2], "textures/common/caulk");
57     }
58 }
59
60 DPlane::~DPlane()
61 {
62
63 }
64
65 //////////////////////////////////////////////////////////////////////
66 // Implementation
67 //////////////////////////////////////////////////////////////////////
68
69 vec_t DPlane::DistanceToPoint(vec3_t pnt)
70 {
71     vec3_t tmp;
72     VectorSubtract(pnt, points[0], tmp);
73     return DotProduct(tmp, normal);
74 }
75
76 bool DPlane::PlaneIntersection(DPlane *pl1, DPlane *pl2, vec3_t out)
77 {
78     float a1, a2, a3;
79     float b1, b2, b3;
80     float c1, c2, c3;
81
82     a1 = normal[0];
83     a2 = normal[1];
84     a3 = normal[2];
85     b1 = pl1->normal[0];
86     b2 = pl1->normal[1];
87     b3 = pl1->normal[2];
88     c1 = pl2->normal[0];
89     c2 = pl2->normal[1];
90     c3 = pl2->normal[2];
91
92     float d = Determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3);
93
94     if (d == 0) {
95         return false;
96     }
97
98     float v1 = _d;
99     float v2 = pl1->_d;
100     float v3 = pl2->_d;
101
102     float d1 = Determinant3x3(v1, a2, a3, v2, b2, b3, v3, c2, c3);
103     float d2 = Determinant3x3(a1, v1, a3, b1, v2, b3, c1, v3, c3);
104     float d3 = Determinant3x3(a1, a2, v1, b1, b2, v2, c1, c2, v3);
105
106     out[0] = d1 / d;
107     out[1] = d2 / d;
108     out[2] = d3 / d;
109
110     return true;
111 }
112
113 bool DPlane::IsRedundant(std::list<DPoint *> &pointList)
114 {
115     int cnt = 0;
116
117     //std::list<DPoint *>::const_iterator point=pointList.begin();
118     for (std::list<DPoint *>::const_iterator point = pointList.begin(); point != pointList.end(); point++) {
119         if (fabs(DistanceToPoint((*point)->_pnt)) < MAX_ROUND_ERROR) {
120             cnt++;
121         }
122
123         if (cnt == 3) {
124             return false;
125         }
126     }
127     return true;
128 }
129
130 bool DPlane::operator==(DPlane &other)
131 {
132     vec3_t chk;
133     VectorSubtract(other.normal, normal, chk);
134     if (fabs(VectorLength(chk)) > MAX_ROUND_ERROR) {
135         return false;
136     }
137
138     if (fabs(other._d - _d) > MAX_ROUND_ERROR) {
139         return false;
140     }
141
142     return true;
143 }
144
145 bool DPlane::operator!=(DPlane &other)
146 {
147     vec3_t chk;
148     VectorAdd(other.normal, normal, chk);
149     if (fabs(VectorLength(chk)) > MAX_ROUND_ERROR) {
150         return false;
151     }
152
153     return true;
154 }
155
156 DWinding *DPlane::BaseWindingForPlane()
157 {
158     int i, x;
159     vec_t max, v;
160     vec3_t org, vright, vup;
161
162 // find the major axis
163
164     max = -131072;
165     x = -1;
166     for (i = 0; i < 3; i++) {
167         v = (float) fabs(normal[i]);
168         if (v > max) {
169             x = i;
170             max = v;
171         }
172     }
173     if (x == -1) {
174         globalOutputStream() << "BaseWindingForPlane: no axis found";
175     }
176
177     VectorCopy(vec3_origin, vup);
178     switch (x) {
179         case 0:
180         case 1:
181             vup[2] = 1;
182             break;
183         case 2:
184             vup[0] = 1;
185             break;
186     }
187
188     v = DotProduct(vup, normal);
189     VectorMA(vup, -v, normal, vup);
190     VectorNormalize(vup, vup);
191
192     VectorScale(normal, _d, org);
193
194     CrossProduct(vup, normal, vright);
195
196     VectorScale(vup, 131072, vup);
197     VectorScale(vright, 131072, vright);
198
199 // project a really big axis aligned box onto the plane
200     DWinding *w = new DWinding;
201     w->AllocWinding(4);
202
203     VectorSubtract(org, vright, w->p[0]);
204     VectorAdd(w->p[0], vup, w->p[0]);
205
206     VectorAdd(org, vright, w->p[1]);
207     VectorAdd(w->p[1], vup, w->p[1]);
208
209     VectorAdd(org, vright, w->p[2]);
210     VectorSubtract(w->p[2], vup, w->p[2]);
211
212     VectorSubtract(org, vright, w->p[3]);
213     VectorSubtract(w->p[3], vup, w->p[3]);
214
215     return w;
216 }
217
218 void DPlane::Rebuild()
219 {
220     vec3_t v1, v2;
221     VectorSubtract(points[0], points[1], v1);
222     VectorSubtract(points[2], points[1], v2);
223     CrossProduct(v1, v2, normal);
224
225     if (VectorNormalize(normal, normal) == 0) {  // normalizes and returns length
226         globalErrorStream() << "DPlane::Rebuild: Bad Normal.\n";
227     }
228
229     _d = (normal[0] * points[0][0]) + (normal[1] * points[0][1]) + (normal[2] * points[0][2]);
230
231     VectorCopy(points[0], texInfo.m_p0);
232     VectorCopy(points[1], texInfo.m_p1);
233     VectorCopy(points[2], texInfo.m_p2);
234 }
235
236 bool DPlane::AddToBrush(scene::Node &brush)
237 {
238     bool changed = false;
239     if (!(m_bChkOk || !strcmp(m_shader.c_str(), "textures/common/caulk"))) {
240         m_shader = "textures/common/caulk";
241         changed = true;
242     }
243
244     _QERFaceData faceData;
245     faceData.m_p0 = vector3_from_array(points[0]);
246     faceData.m_p1 = vector3_from_array(points[1]);
247     faceData.m_p2 = vector3_from_array(points[2]);
248     faceData.m_texdef = texInfo.m_texdef;
249     faceData.m_shader = m_shader.c_str();
250     GlobalBrushCreator().Brush_addFace(brush, faceData);
251
252     return changed;
253 }
254
255 void DPlane::ScaleTexture()
256 {}
257
258 DPlane::DPlane(const vec3_t va, const vec3_t vb, const vec3_t vc, const char *textureName, bool bDetail)
259 {
260     vec3_t v1, v2;
261     VectorSubtract(va, vb, v1);
262     VectorSubtract(vc, vb, v2);
263     CrossProduct(v1, v2, normal);
264
265     if (VectorNormalize(normal, normal) == 0) {  // normalizes and returns length
266         globalErrorStream() << "DPlane::DPlane: Bad Normal.\n";
267     }
268
269     _d = (normal[0] * va[0]) + (normal[1] * va[1]) + (normal[2] * va[2]);
270
271     VectorCopy(va, points[0]);
272     VectorCopy(vb, points[1]);
273     VectorCopy(vc, points[2]);
274
275     m_bChkOk = true;
276
277     FillDefaultTexture(&texInfo, points[0], points[1], points[2], textureName);
278     if (bDetail) {
279         texInfo.contents |= FACE_DETAIL;
280     }
281 }