refactored plugin api; refactored callback library; added signals library
[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         _d = (normal[0]*va[0]) + (normal[1]*va[1]) + (normal[2]*va[2]);
45
46         VectorCopy(va, points[0]);
47         VectorCopy(vb, points[1]);
48         VectorCopy(vc, points[2]);
49
50         m_bChkOk = true;
51
52         if(texData)
53                 memcpy(&texInfo, texData, sizeof(_QERFaceData));
54         else
55                 FillDefaultTexture(&texInfo, points[0], points[1], points[2], "textures/common/caulk");
56 }
57
58 DPlane::~DPlane()
59 {
60
61 }
62
63 //////////////////////////////////////////////////////////////////////
64 // Implementation
65 //////////////////////////////////////////////////////////////////////
66
67 vec_t DPlane::DistanceToPoint(vec3_t pnt)
68 {
69         vec3_t tmp;
70         VectorSubtract(pnt, points[0], tmp);
71         return DotProduct(tmp, normal);
72 }
73
74 bool DPlane::PlaneIntersection(DPlane *pl1, DPlane *pl2, vec3_t out)
75 {
76         float a1, a2, a3;
77         float b1, b2, b3;
78         float c1, c2, c3;
79         
80         a1 = normal[0];                 a2 = normal[1];                 a3 = normal[2];
81         b1 = pl1->normal[0];    b2 = pl1->normal[1];    b3 = pl1->normal[2];
82         c1 = pl2->normal[0];    c2 = pl2->normal[1];    c3 = pl2->normal[2];
83
84         float d = Determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3);
85
86         if(d == 0)
87                 return false;
88         
89         float v1 = _d;
90         float v2 = pl1->_d;
91         float v3 = pl2->_d;
92
93         float d1 = Determinant3x3(v1, a2, a3, v2, b2, b3, v3, c2, c3);
94         float d2 = Determinant3x3(a1, v1, a3, b1, v2, b3, c1, v3, c3);
95         float d3 = Determinant3x3(a1, a2, v1, b1, b2, v2, c1, c2, v3);
96
97         out[0] = d1/d;  
98         out[1] = d2/d;  
99         out[2] = d3/d;  
100
101         return true;
102 }
103
104 bool DPlane::IsRedundant(std::list<DPoint*>& pointList)
105 {
106         int cnt = 0;
107
108         //std::list<DPoint *>::const_iterator point=pointList.begin();
109         for(std::list<DPoint *>::const_iterator point=pointList.begin(); point!=pointList.end(); point++)
110         {
111                  if(fabs(DistanceToPoint((*point)->_pnt)) < MAX_ROUND_ERROR)
112                          cnt++;
113
114                  if(cnt == 3)
115                          return false;
116         }
117         return true;
118 }
119
120 bool DPlane::operator == (DPlane& other)
121 {
122         vec3_t chk;
123         VectorSubtract(other.normal, normal, chk);
124         if(fabs(VectorLength(chk)) > MAX_ROUND_ERROR)
125                 return false;
126
127         if(fabs(other._d - _d) > MAX_ROUND_ERROR)
128                 return false;
129
130         return true;
131 }
132
133 bool DPlane::operator != (DPlane& other)
134 {
135         vec3_t chk;
136         VectorAdd(other.normal, normal, chk);
137         if(fabs(VectorLength(chk)) > MAX_ROUND_ERROR)
138                 return false;
139
140         return true;
141 }
142
143 DWinding* DPlane::BaseWindingForPlane()
144 {
145         int             i, x;
146         vec_t   max, v;
147         vec3_t  org, vright, vup;
148         
149 // find the major axis
150
151         max = -131072;
152         x = -1;
153         for (i=0 ; i<3; i++)
154         {
155                 v = (float)fabs(normal[i]);
156                 if (v > max)
157                 {
158                         x = i;
159                         max = v;
160                 }
161         }
162         if (x==-1)
163                 globalOutputStream() << "BaseWindingForPlane: no axis found";
164                 
165         VectorCopy (vec3_origin, vup);  
166         switch (x)
167         {
168         case 0:
169         case 1:
170                 vup[2] = 1;
171                 break;          
172         case 2:
173                 vup[0] = 1;
174                 break;          
175         }
176
177         v = DotProduct (vup, normal);
178         VectorMA (vup, -v, normal, vup);
179         VectorNormalize (vup, vup);
180                 
181         VectorScale (normal, _d, org);
182         
183         CrossProduct (vup, normal, vright);
184         
185         VectorScale (vup, 131072, vup);
186         VectorScale (vright, 131072, vright);
187
188 // project a really big axis aligned box onto the plane
189         DWinding* w = new DWinding;
190         w->AllocWinding(4);
191         
192         VectorSubtract (org, vright, w->p[0]);
193         VectorAdd (w->p[0], vup, w->p[0]);
194         
195         VectorAdd (org, vright, w->p[1]);
196         VectorAdd (w->p[1], vup, w->p[1]);
197         
198         VectorAdd (org, vright, w->p[2]);
199         VectorSubtract (w->p[2], vup, w->p[2]);
200         
201         VectorSubtract (org, vright, w->p[3]);
202         VectorSubtract (w->p[3], vup, w->p[3]);
203                 
204         return w;       
205 }
206
207 void DPlane::Rebuild()
208 {
209         vec3_t v1, v2;
210         VectorSubtract(points[0], points[1], v1);
211         VectorSubtract(points[2], points[1], v2);
212         CrossProduct(v1, v2, normal);
213
214         if(VectorNormalize(normal, normal) == 0)        // normalizes and returns length
215                 globalErrorStream() << "DPlane::Rebuild: Bad Normal.\n";
216
217         _d = (normal[0]*points[0][0]) + (normal[1]*points[0][1]) + (normal[2]*points[0][2]);
218
219         VectorCopy(points[0], texInfo.m_p0);
220         VectorCopy(points[1], texInfo.m_p1);
221         VectorCopy(points[2], texInfo.m_p2);
222 }
223
224 bool DPlane::AddToBrush(scene::Node& brush)
225 {
226   bool changed = false;
227   if(!(m_bChkOk || !strcmp(m_shader.c_str(), "textures/common/caulk")))
228   {
229           m_shader = "textures/common/caulk";
230     changed = true;
231   }
232
233   _QERFaceData faceData;
234   faceData.m_p0 = vector3_from_array(points[0]);
235   faceData.m_p1 = vector3_from_array(points[1]);
236   faceData.m_p2 = vector3_from_array(points[2]);
237   faceData.m_texdef = texInfo.m_texdef;
238   faceData.m_shader = m_shader.c_str();
239   GlobalBrushCreator().addBrushFace(brush, faceData);
240
241         return changed;
242 }
243
244 void DPlane::ScaleTexture()
245 { }
246
247 DPlane::DPlane(const vec3_t va, const vec3_t vb, const vec3_t vc, const char* textureName, bool bDetail)
248 {
249         vec3_t v1, v2;
250         VectorSubtract(va, vb, v1);
251         VectorSubtract(vc, vb, v2);
252         CrossProduct(v1, v2, normal);
253
254         if(VectorNormalize(normal, normal) == 0)        // normalizes and returns length
255                 globalErrorStream() << "DPlane::DPlane: Bad Normal.\n";
256
257         _d = (normal[0]*va[0]) + (normal[1]*va[1]) + (normal[2]*va[2]);
258
259         VectorCopy(va, points[0]);
260         VectorCopy(vb, points[1]);
261         VectorCopy(vc, points[2]);
262
263         m_bChkOk = true;
264
265         FillDefaultTexture(&texInfo, points[0], points[1], points[2], textureName);
266         if(bDetail)
267                 texInfo.contents |= FACE_DETAIL;
268 }