]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/bobtoolz/DPlane.cpp
Merge remote-tracking branch 'ttimo/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         MakeNormal( va, vb, vc, normal );
40         if ( VectorNormalize( normal, normal ) == 0 ) {  // normalizes and returns length
41                 globalErrorStream() << "DPlane::DPlane: Bad Normal.\n";
42         }
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         }
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 // Implementation
66 //////////////////////////////////////////////////////////////////////
67
68 vec_t DPlane::DistanceToPoint( vec3_t pnt ){
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         float a1, a2, a3;
76         float b1, b2, b3;
77         float c1, c2, c3;
78
79         a1 = normal[0];         a2 = normal[1];         a3 = normal[2];
80         b1 = pl1->normal[0];    b2 = pl1->normal[1];    b3 = pl1->normal[2];
81         c1 = pl2->normal[0];    c2 = pl2->normal[1];    c3 = pl2->normal[2];
82
83         float d = Determinant3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3 );
84
85         if ( d == 0 ) {
86                 return false;
87         }
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         int cnt = 0;
106
107         //std::list<DPoint *>::const_iterator point=pointList.begin();
108         for ( std::list<DPoint *>::const_iterator point = pointList.begin(); point != pointList.end(); point++ )
109         {
110                 if ( fabs( DistanceToPoint( ( *point )->_pnt ) ) < MAX_ROUND_ERROR ) {
111                         cnt++;
112                 }
113
114                 if ( cnt == 3 ) {
115                         return false;
116                 }
117         }
118         return true;
119 }
120
121 bool DPlane::operator ==( DPlane& other ){
122         vec3_t chk;
123         VectorSubtract( other.normal, normal, chk );
124         if ( fabs( VectorLength( chk ) ) > MAX_ROUND_ERROR ) {
125                 return false;
126         }
127
128         if ( fabs( other._d - _d ) > MAX_ROUND_ERROR ) {
129                 return false;
130         }
131
132         return true;
133 }
134
135 bool DPlane::operator !=( DPlane& other ){
136         vec3_t chk;
137         VectorAdd( other.normal, normal, chk );
138         if ( fabs( VectorLength( chk ) ) > MAX_ROUND_ERROR ) {
139                 return false;
140         }
141
142         return true;
143 }
144
145 DWinding* DPlane::BaseWindingForPlane(){
146         int i, x;
147         vec_t max, v;
148         vec3_t org, vright, vup;
149
150 // find the major axis
151
152         max = -131072;
153         x = -1;
154         for ( i = 0 ; i < 3; i++ )
155         {
156                 v = (float)fabs( normal[i] );
157                 if ( v > max ) {
158                         x = i;
159                         max = v;
160                 }
161         }
162         if ( x == -1 ) {
163                 globalOutputStream() << "BaseWindingForPlane: no axis found";
164         }
165
166         VectorCopy( vec3_origin, vup );
167         switch ( x )
168         {
169         case 0:
170         case 1:
171                 vup[2] = 1;
172                 break;
173         case 2:
174                 vup[0] = 1;
175                 break;
176         }
177
178         v = DotProduct( vup, normal );
179         VectorMA( vup, -v, normal, vup );
180         VectorNormalize( vup, vup );
181
182         VectorScale( normal, _d, org );
183
184         CrossProduct( vup, normal, vright );
185
186         VectorScale( vup, 131072, vup );
187         VectorScale( vright, 131072, vright );
188
189 // project a really big axis aligned box onto the plane
190         DWinding* w = new DWinding;
191         w->AllocWinding( 4 );
192
193         VectorSubtract( org, vright, w->p[0] );
194         VectorAdd( w->p[0], vup, w->p[0] );
195
196         VectorAdd( org, vright, w->p[1] );
197         VectorAdd( w->p[1], vup, w->p[1] );
198
199         VectorAdd( org, vright, w->p[2] );
200         VectorSubtract( w->p[2], vup, w->p[2] );
201
202         VectorSubtract( org, vright, w->p[3] );
203         VectorSubtract( w->p[3], vup, w->p[3] );
204
205         return w;
206 }
207
208 void DPlane::Rebuild(){
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
218         _d = ( normal[0] * points[0][0] ) + ( normal[1] * points[0][1] ) + ( normal[2] * points[0][2] );
219
220         VectorCopy( points[0], texInfo.m_p0 );
221         VectorCopy( points[1], texInfo.m_p1 );
222         VectorCopy( points[2], texInfo.m_p2 );
223 }
224
225 bool DPlane::AddToBrush( scene::Node& brush ){
226         bool changed = false;
227         if ( !( m_bChkOk || !strcmp( m_shader.c_str(), "textures/common/caulk" ) ) ) {
228                 m_shader = "textures/common/caulk";
229                 changed = true;
230         }
231
232         _QERFaceData faceData;
233         faceData.m_p0 = vector3_from_array( points[0] );
234         faceData.m_p1 = vector3_from_array( points[1] );
235         faceData.m_p2 = vector3_from_array( points[2] );
236         faceData.m_texdef = texInfo.m_texdef;
237         faceData.m_shader = m_shader.c_str();
238         GlobalBrushCreator().Brush_addFace( brush, faceData );
239
240         return changed;
241 }
242
243 void DPlane::ScaleTexture()
244 { }
245
246 DPlane::DPlane( const vec3_t va, const vec3_t vb, const vec3_t vc, const char* textureName, bool bDetail ){
247         vec3_t v1, v2;
248         VectorSubtract( va, vb, v1 );
249         VectorSubtract( vc, vb, v2 );
250         CrossProduct( v1, v2, normal );
251
252         if ( VectorNormalize( normal, normal ) == 0 ) {  // normalizes and returns length
253                 globalErrorStream() << "DPlane::DPlane: Bad Normal.\n";
254         }
255
256         _d = ( normal[0] * va[0] ) + ( normal[1] * va[1] ) + ( normal[2] * va[2] );
257
258         VectorCopy( va, points[0] );
259         VectorCopy( vb, points[1] );
260         VectorCopy( vc, points[2] );
261
262         m_bChkOk = true;
263
264         FillDefaultTexture( &texInfo, points[0], points[1], points[2], textureName );
265         if ( bDetail ) {
266                 texInfo.contents |= FACE_DETAIL;
267         }
268 }