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)
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;
114 MY_WINDING *BaseWindingForPlane (vec3 normal, vec dist)
118 vec3 org, vright, vup;
121 // find the major axis
127 v = (vec)(fabs(normal[i]));
136 VectorCopy(gensurf_vec3_origin,vup);
148 v = DotProduct (vup, normal);
149 VectorMA (vup, -v, normal, vup);
150 VectorNormalize (vup, vup);
152 VectorScale (normal, dist, org);
154 CrossProduct (vup, normal, vright);
156 VectorScale (vup, 65536, vup);
157 VectorScale (vright, 65536, vright);
159 // project a really big axis aligned box onto the plane
160 w = AllocWinding (4);
162 VectorSubtract (org, vright, w->p[0]);
163 VectorAdd (w->p[0], vup, w->p[0]);
165 VectorAdd (org, vright, w->p[1]);
166 VectorAdd (w->p[1], vup, w->p[1]);
168 VectorAdd (org, vright, w->p[2]);
169 VectorSubtract (w->p[2], vup, w->p[2]);
171 VectorSubtract (org, vright, w->p[3]);
172 VectorSubtract (w->p[3], vup, w->p[3]);
179 void FreeWinding (MY_WINDING *w)
181 if (*(unsigned *)w == 0xdeaddead)
182 // Error ("FreeWinding: freed a freed winding");
184 *(unsigned *)w = 0xdeaddead;
194 void ChopWindingInPlace (MY_WINDING **inout, vec3 normal, vec dist, vec epsilon)
197 vec dists[MAX_POINTS_ON_WINDING+4];
198 int sides[MAX_POINTS_ON_WINDING+4];
200 static vec dot; // VC 4.2 optimizer bug if not static
208 counts[0] = counts[1] = counts[2] = 0;
210 // determine sides for each point
211 for (i=0 ; i<in->numpoints ; i++)
213 dot = DotProduct (in->p[i], normal);
217 sides[i] = SIDE_FRONT;
218 else if (dot < -epsilon)
219 sides[i] = SIDE_BACK;
236 return; // inout stays the same
238 maxpts = in->numpoints+4; // cant use counts[0]+2 because
239 // of fp grouping errors
241 f = AllocWinding (maxpts);
243 for (i=0 ; i<in->numpoints ; i++)
247 if (sides[i] == SIDE_ON)
249 VectorCopy (p1, f->p[f->numpoints]);
254 if (sides[i] == SIDE_FRONT)
256 VectorCopy (p1, f->p[f->numpoints]);
260 if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
263 // generate a split point
264 p2 = in->p[(i+1)%in->numpoints];
266 dot = dists[i] / (dists[i]-dists[i+1]);
267 for (j=0 ; j<3 ; j++)
268 { // avoid round off error when possible
271 else if (normal[j] == -1)
274 mid[j] = p1[j] + dot*(p2[j]-p1[j]);
277 VectorCopy (mid, f->p[f->numpoints]);
281 // if (f->numpoints > maxpts)
282 // Error ("ClipWinding: points exceeded estimate");
283 // if (f->numpoints > MAX_POINTS_ON_WINDING)
284 // Error ("ClipWinding: MAX_POINTS_ON_WINDING");
294 float planepts[3][3];
300 _QERFaceData *QERFaceData;
301 PLANE plane[MAX_FACES*2];
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 = 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 (gensurf_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);
367 if(strlen(QERFaceData->m_TextureName))
368 strcpy(Texture[Game][0],QERFaceData->m_TextureName);
371 for(i=0; i<NumFaces; i++)
373 if(i==BestFace) continue;
374 QERFaceData = g_FuncTable.m_pfnGetFaceData(vp,i);
375 if(strlen(QERFaceData->m_TextureName))
377 if(strcmp(Texture[Game][0],QERFaceData->m_TextureName))
378 strcpy(Texture[Game][1],QERFaceData->m_TextureName);
383 g_FuncTable.m_pfnReleaseSelectedBrushHandles();
385 w = BaseWindingForPlane (plane[BestFace*2].normal, plane[BestFace*2].dist);
387 for (i=0 ; i<NumFaces && w; i++)
391 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.) return;
422 Z00 = (pface.dist - pface.normal[0]*Hll - pface.normal[2]*Vll)/pface.normal[1];
423 Z01 = (pface.dist - pface.normal[0]*Hll - pface.normal[2]*Vur)/pface.normal[1];
424 Z10 = (pface.dist - pface.normal[0]*Hur - pface.normal[2]*Vll)/pface.normal[1];
425 Z11 = (pface.dist - pface.normal[0]*Hur - pface.normal[2]*Vur)/pface.normal[1];
429 if(pface.normal[0] == 0.) return;
434 Z00 = (pface.dist - pface.normal[1]*Hll - pface.normal[2]*Vll)/pface.normal[0];
435 Z01 = (pface.dist - pface.normal[1]*Hll - pface.normal[2]*Vur)/pface.normal[0];
436 Z10 = (pface.dist - pface.normal[1]*Hur - pface.normal[2]*Vll)/pface.normal[0];
437 Z11 = (pface.dist - pface.normal[1]*Hur - pface.normal[2]*Vur)/pface.normal[0];
440 if(pface.normal[2] == 0.) return;
445 Z00 = (pface.dist - pface.normal[0]*Hll - pface.normal[1]*Vll)/pface.normal[2];
446 Z01 = (pface.dist - pface.normal[0]*Hll - pface.normal[1]*Vur)/pface.normal[2];
447 Z10 = (pface.dist - pface.normal[0]*Hur - pface.normal[1]*Vll)/pface.normal[2];
448 Z11 = (pface.dist - pface.normal[0]*Hur - pface.normal[1]*Vur)/pface.normal[2];