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)
38 VectorSubtract (p0, p1, t1);
39 VectorSubtract (p2, p1, t2);
40 plane->normal[0] = t1[1]*t2[2] - t1[2]*t2[1];
41 plane->normal[1] = t1[2]*t2[0] - t1[0]*t2[2];
42 plane->normal[2] = t1[0]*t2[1] - t1[1]*t2[0];
44 length = (vec)(sqrt(plane->normal[0]*plane->normal[0] +
45 plane->normal[1]*plane->normal[1] +
46 plane->normal[2]*plane->normal[2] ));
49 VectorClear(plane->normal);
53 plane->normal[0] /= length;
54 plane->normal[1] /= length;
55 plane->normal[2] /= length;
57 plane->dist = DotProduct (p0, plane->normal);
60 void VectorMA (vec3 va, vec scale, vec3 vb, vec3 vc)
62 vc[0] = va[0] + scale*vb[0];
63 vc[1] = va[1] + scale*vb[1];
64 vc[2] = va[2] + scale*vb[2];
67 void CrossProduct (vec3 v1, vec3 v2, vec3 cross)
69 cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
70 cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
71 cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
79 MY_WINDING *AllocWinding (int points)
84 s = sizeof(vec)*3*points + sizeof(int);
85 w = (MY_WINDING*)malloc (s);
90 vec VectorNormalize (vec3 in, vec3 out)
94 length = (vec)(sqrt (in[0]*in[0] + in[1]*in[1] + in[2]*in[2]));
101 ilength = (vec)1.0/length;
102 out[0] = in[0]*ilength;
103 out[1] = in[1]*ilength;
104 out[2] = in[2]*ilength;
115 MY_WINDING *BaseWindingForPlane (vec3 normal, vec dist)
119 vec3 org, vright, vup;
122 // find the major axis
128 v = (vec)(fabs(normal[i]));
137 VectorCopy(vec3_origin,vup);
149 v = DotProduct (vup, normal);
150 VectorMA (vup, -v, normal, vup);
151 VectorNormalize (vup, vup);
153 VectorScale (normal, dist, org);
155 CrossProduct (vup, normal, vright);
157 VectorScale (vup, 65536, vup);
158 VectorScale (vright, 65536, vright);
160 // project a really big axis aligned box onto the plane
161 w = AllocWinding (4);
163 VectorSubtract (org, vright, w->p[0]);
164 VectorAdd (w->p[0], vup, w->p[0]);
166 VectorAdd (org, vright, w->p[1]);
167 VectorAdd (w->p[1], vup, w->p[1]);
169 VectorAdd (org, vright, w->p[2]);
170 VectorSubtract (w->p[2], vup, w->p[2]);
172 VectorSubtract (org, vright, w->p[3]);
173 VectorSubtract (w->p[3], vup, w->p[3]);
180 void FreeWinding (MY_WINDING *w)
182 if (*(unsigned *)w == 0xdeaddead)
183 // Error ("FreeWinding: freed a freed winding");
185 *(unsigned *)w = 0xdeaddead;
195 void ChopWindingInPlace (MY_WINDING **inout, vec3 normal, vec dist, vec epsilon)
198 vec dists[MAX_POINTS_ON_WINDING+4];
199 int sides[MAX_POINTS_ON_WINDING+4];
201 static vec dot; // VC 4.2 optimizer bug if not static
209 counts[0] = counts[1] = counts[2] = 0;
211 // determine sides for each point
212 for (i=0 ; i<in->numpoints ; i++)
214 dot = DotProduct (in->p[i], normal);
218 sides[i] = SIDE_FRONT;
219 else if (dot < -epsilon)
220 sides[i] = SIDE_BACK;
237 return; // inout stays the same
239 maxpts = in->numpoints+4; // cant use counts[0]+2 because
240 // of fp grouping errors
242 f = AllocWinding (maxpts);
244 for (i=0 ; i<in->numpoints ; i++)
248 if (sides[i] == SIDE_ON)
250 VectorCopy (p1, f->p[f->numpoints]);
255 if (sides[i] == SIDE_FRONT)
257 VectorCopy (p1, f->p[f->numpoints]);
261 if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
264 // generate a split point
265 p2 = in->p[(i+1)%in->numpoints];
267 dot = dists[i] / (dists[i]-dists[i+1]);
268 for (j=0 ; j<3 ; j++)
269 { // avoid round off error when possible
272 else if (normal[j] == -1)
275 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");
295 float planepts[3][3];
301 PLANE plane[MAX_FACES*2];
339 i = g_FuncTable.m_pfnAllocateSelectedBrushHandles();
340 vp = g_FuncTable.m_pfnGetSelectedBrushHandle(0);
341 NumFaces = g_FuncTable.m_pfnGetFaceCount(vp);
346 for(i=0; i<NumFaces; i++)
348 _QERFaceData* QERFaceData = g_FuncTable.m_pfnGetFaceData(vp,i);
349 planepts[0][0] = QERFaceData->m_v1[0];
350 planepts[0][1] = QERFaceData->m_v1[1];
351 planepts[0][2] = QERFaceData->m_v1[2];
352 planepts[1][0] = QERFaceData->m_v2[0];
353 planepts[1][1] = QERFaceData->m_v2[1];
354 planepts[1][2] = QERFaceData->m_v2[2];
355 planepts[2][0] = QERFaceData->m_v3[0];
356 planepts[2][1] = QERFaceData->m_v3[1];
357 planepts[2][2] = QERFaceData->m_v3[2];
359 PlaneFromPoints (planepts[0], planepts[1], planepts[2], &plane[2*i]);
360 VectorSubtract (vec3_origin, plane[2*i].normal, plane[2*i+1].normal);
361 plane[2*i+1].dist = -plane[2*i].dist;
363 Dot = DotProduct(plane[2*i].normal,SurfNormal);
368 if(strlen(QERFaceData->m_TextureName))
369 strcpy(Texture[Game][0],QERFaceData->m_TextureName);
372 for(i=0; i<NumFaces; i++)
374 if(i==BestFace) continue;
375 _QERFaceData* QERFaceData = g_FuncTable.m_pfnGetFaceData(vp,i);
376 if(strlen(QERFaceData->m_TextureName))
378 if(strcmp(Texture[Game][0],QERFaceData->m_TextureName))
379 strcpy(Texture[Game][1],QERFaceData->m_TextureName);
384 g_FuncTable.m_pfnReleaseSelectedBrushHandles();
386 w = BaseWindingForPlane (plane[BestFace*2].normal, plane[BestFace*2].dist);
388 for (i=0 ; i<NumFaces && w; i++)
392 ChopWindingInPlace (&w, plane[i*2+1].normal, plane[i*2+1].dist, 0);
396 // Get bounding box for this face
397 vmin[0] = vmax[0] = w->p[0][0];
398 vmin[1] = vmax[1] = w->p[0][1];
399 vmin[2] = vmax[2] = w->p[0][2];
400 for(j=1; j<w->numpoints; j++)
402 vmin[0] = min(vmin[0],w->p[j][0]);
403 vmin[1] = min(vmin[1],w->p[j][1]);
404 vmin[2] = min(vmin[2],w->p[j][2]);
405 vmax[0] = max(vmax[0],w->p[j][0]);
406 vmax[1] = max(vmax[1],w->p[j][1]);
407 vmax[2] = max(vmax[2],w->p[j][2]);
412 VectorCopy(plane[BestFace*2].normal,pface.normal);
413 pface.dist = plane[BestFace*2].dist;
418 if(pface.normal[1] == 0.) return;
423 Z00 = (pface.dist - pface.normal[0]*Hll - pface.normal[2]*Vll)/pface.normal[1];
424 Z01 = (pface.dist - pface.normal[0]*Hll - pface.normal[2]*Vur)/pface.normal[1];
425 Z10 = (pface.dist - pface.normal[0]*Hur - pface.normal[2]*Vll)/pface.normal[1];
426 Z11 = (pface.dist - pface.normal[0]*Hur - pface.normal[2]*Vur)/pface.normal[1];
430 if(pface.normal[0] == 0.) return;
435 Z00 = (pface.dist - pface.normal[1]*Hll - pface.normal[2]*Vll)/pface.normal[0];
436 Z01 = (pface.dist - pface.normal[1]*Hll - pface.normal[2]*Vur)/pface.normal[0];
437 Z10 = (pface.dist - pface.normal[1]*Hur - pface.normal[2]*Vll)/pface.normal[0];
438 Z11 = (pface.dist - pface.normal[1]*Hur - pface.normal[2]*Vur)/pface.normal[0];
441 if(pface.normal[2] == 0.) return;
446 Z00 = (pface.dist - pface.normal[0]*Hll - pface.normal[1]*Vll)/pface.normal[2];
447 Z01 = (pface.dist - pface.normal[0]*Hll - pface.normal[1]*Vur)/pface.normal[2];
448 Z10 = (pface.dist - pface.normal[0]*Hur - pface.normal[1]*Vll)/pface.normal[2];
449 Z11 = (pface.dist - pface.normal[0]*Hur - pface.normal[1]*Vur)/pface.normal[2];