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