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 gensurf_vec3_origin;
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 ){
59 vc[0] = va[0] + scale * vb[0];
60 vc[1] = va[1] + scale * vb[1];
61 vc[2] = va[2] + scale * vb[2];
64 void CrossProduct( vec3 v1, vec3 v2, vec3 cross ){
65 cross[0] = v1[1] * v2[2] - v1[2] * v2[1];
66 cross[1] = v1[2] * v2[0] - v1[0] * v2[2];
67 cross[2] = v1[0] * v2[1] - v1[1] * v2[0];
75 MY_WINDING *AllocWinding( int points ){
79 s = sizeof( vec ) * 3 * points + sizeof( int );
80 w = (MY_WINDING*)malloc( s );
85 vec VectorNormalize( vec3 in, vec3 out ){
88 length = (vec)( sqrt( in[0] * in[0] + in[1] * in[1] + in[2] * in[2] ) );
94 ilength = (vec)1.0 / length;
95 out[0] = in[0] * ilength;
96 out[1] = in[1] * ilength;
97 out[2] = in[2] * ilength;
107 MY_WINDING *BaseWindingForPlane( vec3 normal, vec dist ){
110 vec3 org, vright, vup;
113 // find the major axis
117 for ( i = 0 ; i < 3; i++ )
119 v = (vec)( fabs( normal[i] ) );
129 VectorCopy( gensurf_vec3_origin,vup );
141 v = DotProduct( vup, normal );
142 VectorMA( vup, -v, normal, vup );
143 VectorNormalize( vup, vup );
145 VectorScale( normal, dist, org );
147 CrossProduct( vup, normal, vright );
149 VectorScale( vup, 65536, vup );
150 VectorScale( vright, 65536, vright );
152 // project a really big axis aligned box onto the plane
153 w = AllocWinding( 4 );
155 VectorSubtract( org, vright, w->p[0] );
156 VectorAdd( w->p[0], vup, w->p[0] );
158 VectorAdd( org, vright, w->p[1] );
159 VectorAdd( w->p[1], vup, w->p[1] );
161 VectorAdd( org, vright, w->p[2] );
162 VectorSubtract( w->p[2], vup, w->p[2] );
164 VectorSubtract( org, vright, w->p[3] );
165 VectorSubtract( w->p[3], vup, w->p[3] );
172 void FreeWinding( MY_WINDING *w ){
173 if ( *(unsigned *)w == 0xdeaddead ) {
174 // Error ("FreeWinding: freed a freed winding");
177 *(unsigned *)w = 0xdeaddead;
187 void ChopWindingInPlace( MY_WINDING **inout, vec3 normal, vec dist, vec epsilon ){
189 vec dists[MAX_POINTS_ON_WINDING + 4];
190 int sides[MAX_POINTS_ON_WINDING + 4];
192 static vec dot; // VC 4.2 optimizer bug if not static
200 counts[0] = counts[1] = counts[2] = 0;
202 // determine sides for each point
203 for ( i = 0 ; i < in->numpoints ; i++ )
205 dot = DotProduct( in->p[i], normal );
208 if ( dot > epsilon ) {
209 sides[i] = SIDE_FRONT;
211 else if ( dot < -epsilon ) {
212 sides[i] = SIDE_BACK;
229 return; // inout stays the same
232 maxpts = in->numpoints + 4; // cant use counts[0]+2 because
233 // of fp grouping errors
235 f = AllocWinding( maxpts );
237 for ( i = 0 ; i < in->numpoints ; i++ )
241 if ( sides[i] == SIDE_ON ) {
242 VectorCopy( p1, f->p[f->numpoints] );
247 if ( sides[i] == SIDE_FRONT ) {
248 VectorCopy( p1, f->p[f->numpoints] );
252 if ( sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i] ) {
256 // generate a split point
257 p2 = in->p[( i + 1 ) % in->numpoints];
259 dot = dists[i] / ( dists[i] - dists[i + 1] );
260 for ( j = 0 ; j < 3 ; j++ )
261 { // avoid round off error when possible
262 if ( normal[j] == 1 ) {
265 else if ( normal[j] == -1 ) {
269 mid[j] = p1[j] + dot * ( p2[j] - p1[j] );
273 VectorCopy( mid, f->p[f->numpoints] );
277 // if (f->numpoints > maxpts)
278 // Error ("ClipWinding: points exceeded estimate");
279 // if (f->numpoints > MAX_POINTS_ON_WINDING)
280 // Error ("ClipWinding: MAX_POINTS_ON_WINDING");
286 void UseFaceBounds(){
289 float planepts[3][3];
295 _QERFaceData *QERFaceData;
296 PLANE plane[MAX_FACES * 2];
305 SurfNormal[2] = -1.0;
314 SurfNormal[1] = -1.0;
323 SurfNormal[0] = -1.0;
333 i = g_FuncTable.m_pfnAllocateSelectedBrushHandles();
334 vp = g_FuncTable.m_pfnGetSelectedBrushHandle( 0 );
335 NumFaces = g_FuncTable.m_pfnGetFaceCount( vp );
340 for ( i = 0; i < NumFaces; i++ )
342 QERFaceData = g_FuncTable.m_pfnGetFaceData( vp,i );
343 planepts[0][0] = QERFaceData->m_v1[0];
344 planepts[0][1] = QERFaceData->m_v1[1];
345 planepts[0][2] = QERFaceData->m_v1[2];
346 planepts[1][0] = QERFaceData->m_v2[0];
347 planepts[1][1] = QERFaceData->m_v2[1];
348 planepts[1][2] = QERFaceData->m_v2[2];
349 planepts[2][0] = QERFaceData->m_v3[0];
350 planepts[2][1] = QERFaceData->m_v3[1];
351 planepts[2][2] = QERFaceData->m_v3[2];
353 PlaneFromPoints( planepts[0], planepts[1], planepts[2], &plane[2 * i] );
354 VectorSubtract( gensurf_vec3_origin, plane[2 * i].normal, plane[2 * i + 1].normal );
355 plane[2 * i + 1].dist = -plane[2 * i].dist;
357 Dot = DotProduct( plane[2 * i].normal,SurfNormal );
358 if ( Dot > BestDot ) {
361 if ( strlen( QERFaceData->m_TextureName ) ) {
362 strcpy( Texture[Game][0],QERFaceData->m_TextureName );
366 for ( i = 0; i < NumFaces; i++ )
368 if ( i == BestFace ) {
371 QERFaceData = g_FuncTable.m_pfnGetFaceData( vp,i );
372 if ( strlen( QERFaceData->m_TextureName ) ) {
373 if ( strcmp( Texture[Game][0],QERFaceData->m_TextureName ) ) {
374 strcpy( Texture[Game][1],QERFaceData->m_TextureName );
380 g_FuncTable.m_pfnReleaseSelectedBrushHandles();
382 w = BaseWindingForPlane( plane[BestFace * 2].normal, plane[BestFace * 2].dist );
384 for ( i = 0 ; i < NumFaces && w; i++ )
386 if ( BestFace == i ) {
389 ChopWindingInPlace( &w, plane[i * 2 + 1].normal, plane[i * 2 + 1].dist, 0 );
395 // Get bounding box for this face
396 vmin[0] = vmax[0] = w->p[0][0];
397 vmin[1] = vmax[1] = w->p[0][1];
398 vmin[2] = vmax[2] = w->p[0][2];
399 for ( j = 1; j < w->numpoints; j++ )
401 vmin[0] = min( vmin[0],w->p[j][0] );
402 vmin[1] = min( vmin[1],w->p[j][1] );
403 vmin[2] = min( vmin[2],w->p[j][2] );
404 vmax[0] = max( vmax[0],w->p[j][0] );
405 vmax[1] = max( vmax[1],w->p[j][1] );
406 vmax[2] = max( vmax[2],w->p[j][2] );
411 VectorCopy( plane[BestFace * 2].normal,pface.normal );
412 pface.dist = plane[BestFace * 2].dist;
417 if ( pface.normal[1] == 0. ) {
424 Z00 = ( pface.dist - pface.normal[0] * Hll - pface.normal[2] * Vll ) / pface.normal[1];
425 Z01 = ( pface.dist - pface.normal[0] * Hll - pface.normal[2] * Vur ) / pface.normal[1];
426 Z10 = ( pface.dist - pface.normal[0] * Hur - pface.normal[2] * Vll ) / pface.normal[1];
427 Z11 = ( pface.dist - pface.normal[0] * Hur - pface.normal[2] * Vur ) / pface.normal[1];
431 if ( pface.normal[0] == 0. ) {
438 Z00 = ( pface.dist - pface.normal[1] * Hll - pface.normal[2] * Vll ) / pface.normal[0];
439 Z01 = ( pface.dist - pface.normal[1] * Hll - pface.normal[2] * Vur ) / pface.normal[0];
440 Z10 = ( pface.dist - pface.normal[1] * Hur - pface.normal[2] * Vll ) / pface.normal[0];
441 Z11 = ( pface.dist - pface.normal[1] * Hur - pface.normal[2] * Vur ) / pface.normal[0];
444 if ( pface.normal[2] == 0. ) {
451 Z00 = ( pface.dist - pface.normal[0] * Hll - pface.normal[1] * Vll ) / pface.normal[2];
452 Z01 = ( pface.dist - pface.normal[0] * Hll - pface.normal[1] * Vur ) / pface.normal[2];
453 Z10 = ( pface.dist - pface.normal[0] * Hur - pface.normal[1] * Vll ) / pface.normal[2];
454 Z11 = ( pface.dist - pface.normal[0] * Hur - pface.normal[1] * Vur ) / pface.normal[2];