/* BobToolz plugin for GtkRadiant Copyright (C) 2001 Gordon Biggans This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // DPlane.cpp: implementation of the DPlane class. // ////////////////////////////////////////////////////////////////////// #include "DPlane.h" #include #include "DPoint.h" #include "DWinding.h" #include "str.h" #include "misc.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// DPlane::DPlane( const vec3_t va, const vec3_t vb, const vec3_t vc, const _QERFaceData* texData ){ MakeNormal( va, vb, vc, normal ); if ( VectorNormalize( normal, normal ) == 0 ) { // normalizes and returns length globalErrorStream() << "DPlane::DPlane: Bad Normal.\n"; } _d = ( normal[0] * va[0] ) + ( normal[1] * va[1] ) + ( normal[2] * va[2] ); VectorCopy( va, points[0] ); VectorCopy( vb, points[1] ); VectorCopy( vc, points[2] ); m_bChkOk = true; if ( texData ) { memcpy( &texInfo, texData, sizeof( _QERFaceData ) ); } else{ FillDefaultTexture( &texInfo, points[0], points[1], points[2], "textures/common/caulk" ); } } DPlane::~DPlane(){ } ////////////////////////////////////////////////////////////////////// // Implementation ////////////////////////////////////////////////////////////////////// vec_t DPlane::DistanceToPoint( vec3_t pnt ){ vec3_t tmp; VectorSubtract( pnt, points[0], tmp ); return DotProduct( tmp, normal ); } bool DPlane::PlaneIntersection( DPlane *pl1, DPlane *pl2, vec3_t out ){ float a1, a2, a3; float b1, b2, b3; float c1, c2, c3; a1 = normal[0]; a2 = normal[1]; a3 = normal[2]; b1 = pl1->normal[0]; b2 = pl1->normal[1]; b3 = pl1->normal[2]; c1 = pl2->normal[0]; c2 = pl2->normal[1]; c3 = pl2->normal[2]; float d = Determinant3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3 ); if ( d == 0 ) { return false; } float v1 = _d; float v2 = pl1->_d; float v3 = pl2->_d; float d1 = Determinant3x3( v1, a2, a3, v2, b2, b3, v3, c2, c3 ); float d2 = Determinant3x3( a1, v1, a3, b1, v2, b3, c1, v3, c3 ); float d3 = Determinant3x3( a1, a2, v1, b1, b2, v2, c1, c2, v3 ); out[0] = d1 / d; out[1] = d2 / d; out[2] = d3 / d; return true; } bool DPlane::IsRedundant( std::list& pointList ){ int cnt = 0; //std::list::const_iterator point=pointList.begin(); for ( std::list::const_iterator point = pointList.begin(); point != pointList.end(); point++ ) { if ( fabs( DistanceToPoint( ( *point )->_pnt ) ) < MAX_ROUND_ERROR ) { cnt++; } if ( cnt == 3 ) { return false; } } return true; } bool DPlane::operator ==( DPlane& other ){ vec3_t chk; VectorSubtract( other.normal, normal, chk ); if ( fabs( VectorLength( chk ) ) > MAX_ROUND_ERROR ) { return false; } if ( fabs( other._d - _d ) > MAX_ROUND_ERROR ) { return false; } return true; } bool DPlane::operator !=( DPlane& other ){ vec3_t chk; VectorAdd( other.normal, normal, chk ); if ( fabs( VectorLength( chk ) ) > MAX_ROUND_ERROR ) { return false; } return true; } DWinding* DPlane::BaseWindingForPlane(){ int i, x; vec_t max, v; vec3_t org, vright, vup; // find the major axis max = -131072; x = -1; for ( i = 0 ; i < 3; i++ ) { v = (float)fabs( normal[i] ); if ( v > max ) { x = i; max = v; } } if ( x == -1 ) { globalOutputStream() << "BaseWindingForPlane: no axis found"; } VectorCopy( vec3_origin, vup ); switch ( x ) { case 0: case 1: vup[2] = 1; break; case 2: vup[0] = 1; break; } v = DotProduct( vup, normal ); VectorMA( vup, -v, normal, vup ); VectorNormalize( vup, vup ); VectorScale( normal, _d, org ); CrossProduct( vup, normal, vright ); VectorScale( vup, 131072, vup ); VectorScale( vright, 131072, vright ); // project a really big axis aligned box onto the plane DWinding* w = new DWinding; w->AllocWinding( 4 ); VectorSubtract( org, vright, w->p[0] ); VectorAdd( w->p[0], vup, w->p[0] ); VectorAdd( org, vright, w->p[1] ); VectorAdd( w->p[1], vup, w->p[1] ); VectorAdd( org, vright, w->p[2] ); VectorSubtract( w->p[2], vup, w->p[2] ); VectorSubtract( org, vright, w->p[3] ); VectorSubtract( w->p[3], vup, w->p[3] ); return w; } void DPlane::Rebuild(){ vec3_t v1, v2; VectorSubtract( points[0], points[1], v1 ); VectorSubtract( points[2], points[1], v2 ); CrossProduct( v1, v2, normal ); if ( VectorNormalize( normal, normal ) == 0 ) { // normalizes and returns length globalErrorStream() << "DPlane::Rebuild: Bad Normal.\n"; } _d = ( normal[0] * points[0][0] ) + ( normal[1] * points[0][1] ) + ( normal[2] * points[0][2] ); VectorCopy( points[0], texInfo.m_p0 ); VectorCopy( points[1], texInfo.m_p1 ); VectorCopy( points[2], texInfo.m_p2 ); } bool DPlane::AddToBrush( scene::Node& brush ){ bool changed = false; if ( !( m_bChkOk || !strcmp( m_shader.c_str(), "textures/common/caulk" ) ) ) { m_shader = "textures/common/caulk"; changed = true; } _QERFaceData faceData; faceData.m_p0 = vector3_from_array( points[0] ); faceData.m_p1 = vector3_from_array( points[1] ); faceData.m_p2 = vector3_from_array( points[2] ); faceData.m_texdef = texInfo.m_texdef; faceData.m_shader = m_shader.c_str(); GlobalBrushCreator().Brush_addFace( brush, faceData ); return changed; } void DPlane::ScaleTexture() { } DPlane::DPlane( const vec3_t va, const vec3_t vb, const vec3_t vc, const char* textureName, bool bDetail ){ vec3_t v1, v2; VectorSubtract( va, vb, v1 ); VectorSubtract( vc, vb, v2 ); CrossProduct( v1, v2, normal ); if ( VectorNormalize( normal, normal ) == 0 ) { // normalizes and returns length globalErrorStream() << "DPlane::DPlane: Bad Normal.\n"; } _d = ( normal[0] * va[0] ) + ( normal[1] * va[1] ) + ( normal[2] * va[2] ); VectorCopy( va, points[0] ); VectorCopy( vb, points[1] ); VectorCopy( vc, points[2] ); m_bChkOk = true; FillDefaultTexture( &texInfo, points[0], points[1], points[2], textureName ); if ( bDetail ) { texInfo.contents |= FACE_DETAIL; } }