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
DPlane(const vec3_t va,const vec3_t vb,const vec3_t vc,const _QERFaceData * texData)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
~DPlane()60 DPlane::~DPlane(){
61
62 }
63
64 //////////////////////////////////////////////////////////////////////
65 // Implementation
66 //////////////////////////////////////////////////////////////////////
67
DistanceToPoint(vec3_t pnt)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
PlaneIntersection(DPlane * pl1,DPlane * pl2,vec3_t out)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
IsRedundant(std::list<DPoint * > & pointList)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
operator ==(DPlane & other)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
operator !=(DPlane & other)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
BaseWindingForPlane()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
Rebuild()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
AddToBrush(scene::Node & brush)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
ScaleTexture()243 void DPlane::ScaleTexture()
244 { }
245
DPlane(const vec3_t va,const vec3_t vb,const vec3_t vc,const char * textureName,bool bDetail)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 }
269