2 GenSurf plugin for GtkRadiant
3 Copyright (C) 2001 David Hyde, Loki software and qeradiant.com
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.
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.
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
24 #define MAX_FACES 128 // Maximum number of faces on a brush
25 #define MAX_POINTS_ON_WINDING 64
31 //vec3 vec3_origin = {0,0,0};
33 void PlaneFromPoints( float *p0, float *p1, float *p2, PLANE *plane ){
37 VectorSubtract( p0, p1, t1 );
38 VectorSubtract( p2, p1, t2 );
39 plane->normal[0] = t1[1] * t2[2] - t1[2] * t2[1];
40 plane->normal[1] = t1[2] * t2[0] - t1[0] * t2[2];
41 plane->normal[2] = t1[0] * t2[1] - t1[1] * t2[0];
43 length = (vec)( sqrt( plane->normal[0] * plane->normal[0] +
44 plane->normal[1] * plane->normal[1] +
45 plane->normal[2] * plane->normal[2] ) );
47 VectorClear( plane->normal );
51 plane->normal[0] /= length;
52 plane->normal[1] /= length;
53 plane->normal[2] /= length;
55 plane->dist = DotProduct( p0, plane->normal );
58 void VectorMA (vec3 va, vec scale, vec3 vb, vec3 vc)
60 vc[0] = va[0] + scale*vb[0];
61 vc[1] = va[1] + scale*vb[1];
62 vc[2] = va[2] + scale*vb[2];
65 void CrossProduct (vec3 v1, vec3 v2, vec3 cross)
67 cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
68 cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
69 cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
77 MY_WINDING *AllocWinding( int points ){
81 s = sizeof( vec ) * 3 * points + sizeof( int );
82 w = (MY_WINDING*)malloc( s );
87 vec VectorNormalize (vec3 in, vec3 out)
91 length = (vec)(sqrt (in[0]*in[0] + in[1]*in[1] + in[2]*in[2]));
98 ilength = (vec)1.0/length;
99 out[0] = in[0]*ilength;
100 out[1] = in[1]*ilength;
101 out[2] = in[2]*ilength;
112 MY_WINDING *BaseWindingForPlane( vec3 normal, vec dist ){
115 vec3 org, vright, vup;
118 // find the major axis
122 for ( i = 0 ; i < 3; i++ )
124 v = (vec)( fabs( normal[i] ) );
134 VectorCopy( vec3_origin,vup );
146 v = DotProduct( vup, normal );
147 VectorMA( vup, -v, normal, vup );
148 VectorNormalize( vup, vup );
150 VectorScale( normal, dist, org );
152 CrossProduct( vup, normal, vright );
154 VectorScale( vup, 65536, vup );
155 VectorScale( vright, 65536, vright );
157 // project a really big axis aligned box onto the plane
158 w = AllocWinding( 4 );
160 VectorSubtract( org, vright, w->p[0] );
161 VectorAdd( w->p[0], vup, w->p[0] );
163 VectorAdd( org, vright, w->p[1] );
164 VectorAdd( w->p[1], vup, w->p[1] );
166 VectorAdd( org, vright, w->p[2] );
167 VectorSubtract( w->p[2], vup, w->p[2] );
169 VectorSubtract( org, vright, w->p[3] );
170 VectorSubtract( w->p[3], vup, w->p[3] );
177 void FreeWinding( MY_WINDING *w ){
178 if ( *(unsigned *)w == 0xdeaddead ) {
179 // Error ("FreeWinding: freed a freed winding");
182 *(unsigned *)w = 0xdeaddead;
192 void ChopWindingInPlace( MY_WINDING **inout, vec3 normal, vec dist, vec epsilon ){
194 vec dists[MAX_POINTS_ON_WINDING + 4];
195 int sides[MAX_POINTS_ON_WINDING + 4];
197 static vec dot; // VC 4.2 optimizer bug if not static
205 counts[0] = counts[1] = counts[2] = 0;
207 // determine sides for each point
208 for ( i = 0 ; i < in->numpoints ; i++ )
210 dot = DotProduct( in->p[i], normal );
213 if ( dot > epsilon ) {
214 sides[i] = SIDE_FRONT;
216 else if ( dot < -epsilon ) {
217 sides[i] = SIDE_BACK;
234 return; // inout stays the same
237 maxpts = in->numpoints + 4; // cant use counts[0]+2 because
238 // of fp grouping errors
240 f = AllocWinding( maxpts );
242 for ( i = 0 ; i < in->numpoints ; i++ )
246 if ( sides[i] == SIDE_ON ) {
247 VectorCopy( p1, f->p[f->numpoints] );
252 if ( sides[i] == SIDE_FRONT ) {
253 VectorCopy( p1, f->p[f->numpoints] );
257 if ( sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i] ) {
261 // generate a split point
262 p2 = in->p[( i + 1 ) % in->numpoints];
264 dot = dists[i] / ( dists[i] - dists[i + 1] );
265 for ( j = 0 ; j < 3 ; j++ )
266 { // avoid round off error when possible
267 if ( normal[j] == 1 ) {
270 else if ( normal[j] == -1 ) {
274 mid[j] = p1[j] + dot * ( p2[j] - p1[j] );
278 VectorCopy( mid, f->p[f->numpoints] );
282 // if (f->numpoints > maxpts)
283 // Error ("ClipWinding: points exceeded estimate");
284 // if (f->numpoints > MAX_POINTS_ON_WINDING)
285 // Error ("ClipWinding: MAX_POINTS_ON_WINDING");
291 void UseFaceBounds(){
294 float planepts[3][3];
300 PLANE plane[MAX_FACES * 2];
309 SurfNormal[2] = -1.0;
318 SurfNormal[1] = -1.0;
327 SurfNormal[0] = -1.0;
338 i = g_FuncTable.m_pfnAllocateSelectedBrushHandles();
339 vp = g_FuncTable.m_pfnGetSelectedBrushHandle( 0 );
340 NumFaces = g_FuncTable.m_pfnGetFaceCount( vp );
345 for ( i = 0; i < NumFaces; i++ )
347 _QERFaceData* QERFaceData = g_FuncTable.m_pfnGetFaceData( vp,i );
348 planepts[0][0] = QERFaceData->m_v1[0];
349 planepts[0][1] = QERFaceData->m_v1[1];
350 planepts[0][2] = QERFaceData->m_v1[2];
351 planepts[1][0] = QERFaceData->m_v2[0];
352 planepts[1][1] = QERFaceData->m_v2[1];
353 planepts[1][2] = QERFaceData->m_v2[2];
354 planepts[2][0] = QERFaceData->m_v3[0];
355 planepts[2][1] = QERFaceData->m_v3[1];
356 planepts[2][2] = QERFaceData->m_v3[2];
358 PlaneFromPoints( planepts[0], planepts[1], planepts[2], &plane[2 * i] );
359 VectorSubtract( vec3_origin, plane[2 * i].normal, plane[2 * i + 1].normal );
360 plane[2 * i + 1].dist = -plane[2 * i].dist;
362 Dot = DotProduct( plane[2 * i].normal,SurfNormal );
363 if ( Dot > BestDot ) {
366 if ( strlen( QERFaceData->m_TextureName ) ) {
367 strcpy( Texture[Game][0],QERFaceData->m_TextureName );
371 for ( i = 0; i < NumFaces; i++ )
373 if ( i == BestFace ) {
376 _QERFaceData* QERFaceData = g_FuncTable.m_pfnGetFaceData( vp,i );
377 if ( strlen( QERFaceData->m_TextureName ) ) {
378 if ( strcmp( Texture[Game][0],QERFaceData->m_TextureName ) ) {
379 strcpy( Texture[Game][1],QERFaceData->m_TextureName );
385 g_FuncTable.m_pfnReleaseSelectedBrushHandles();
387 w = BaseWindingForPlane( plane[BestFace * 2].normal, plane[BestFace * 2].dist );
389 for ( i = 0 ; i < NumFaces && w; i++ )
391 if ( BestFace == i ) {
394 ChopWindingInPlace( &w, plane[i * 2 + 1].normal, plane[i * 2 + 1].dist, 0 );
400 // Get bounding box for this face
401 vmin[0] = vmax[0] = w->p[0][0];
402 vmin[1] = vmax[1] = w->p[0][1];
403 vmin[2] = vmax[2] = w->p[0][2];
404 for ( j = 1; j < w->numpoints; j++ )
406 vmin[0] = min( vmin[0],w->p[j][0] );
407 vmin[1] = min( vmin[1],w->p[j][1] );
408 vmin[2] = min( vmin[2],w->p[j][2] );
409 vmax[0] = max( vmax[0],w->p[j][0] );
410 vmax[1] = max( vmax[1],w->p[j][1] );
411 vmax[2] = max( vmax[2],w->p[j][2] );
416 VectorCopy( plane[BestFace * 2].normal,pface.normal );
417 pface.dist = plane[BestFace * 2].dist;
422 if ( pface.normal[1] == 0. ) {
429 Z00 = ( pface.dist - pface.normal[0] * Hll - pface.normal[2] * Vll ) / pface.normal[1];
430 Z01 = ( pface.dist - pface.normal[0] * Hll - pface.normal[2] * Vur ) / pface.normal[1];
431 Z10 = ( pface.dist - pface.normal[0] * Hur - pface.normal[2] * Vll ) / pface.normal[1];
432 Z11 = ( pface.dist - pface.normal[0] * Hur - pface.normal[2] * Vur ) / pface.normal[1];
436 if ( pface.normal[0] == 0. ) {
443 Z00 = ( pface.dist - pface.normal[1] * Hll - pface.normal[2] * Vll ) / pface.normal[0];
444 Z01 = ( pface.dist - pface.normal[1] * Hll - pface.normal[2] * Vur ) / pface.normal[0];
445 Z10 = ( pface.dist - pface.normal[1] * Hur - pface.normal[2] * Vll ) / pface.normal[0];
446 Z11 = ( pface.dist - pface.normal[1] * Hur - pface.normal[2] * Vur ) / pface.normal[0];
449 if ( pface.normal[2] == 0. ) {
456 Z00 = ( pface.dist - pface.normal[0] * Hll - pface.normal[1] * Vll ) / pface.normal[2];
457 Z01 = ( pface.dist - pface.normal[0] * Hll - pface.normal[1] * Vur ) / pface.normal[2];
458 Z10 = ( pface.dist - pface.normal[0] * Hur - pface.normal[1] * Vll ) / pface.normal[2];
459 Z11 = ( pface.dist - pface.normal[0] * Hur - pface.normal[1] * Vur ) / pface.normal[2];