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;