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