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
23 #else /* not SINGLE */
25 #endif /* not SINGLE */
42 #define Absolute(a) ((a) >= 0.0 ? (a) : -(a))
44 void MakeDecimatedMap(int *NumNodes, int *NumTris, NODE **pNode, TRI **pTri)
46 int compare(TRITABLE *, TRITABLE *);
47 int Bisect(NODE *, int, int, int);
48 void CalcAngles(NODE *, int *, float *);
49 void EdgeOnSide(int *, int *, int *);
50 int tricall(int, NODE *, int *, TRI **, TRI **, char *);
51 int CheckBorders(int *,int,NODE *,int *,TRI **);
62 if(Decimate <= 0) return;
64 ghCursorCurrent = LoadCursor(NULL,IDC_WAIT);
65 SetCursor(ghCursorCurrent);
71 NumNodes[0] = (NH+1)*(NVP1);
72 *pNode = (NODE *) malloc(NumNodes[0] * sizeof(NODE));
74 memset(Node,0,NumNodes[0]*sizeof(NODE));
76 // Copy [NH][NV] vertex array to our working node array
77 for(i=0,N=0; i<=NH; i++)
79 for(j=0; j<=NV; j++, N++)
81 Node[N].p[0] = (float)xyz[i][j].p[0];
82 Node[N].p[1] = (float)xyz[i][j].p[1];
83 Node[N].p[2] = (float)xyz[i][j].p[2];
84 Node[N].fixed = xyz[i][j].fixed;
87 // Start things off with the corner values
90 Node[NH*NVP1].used = 1;
91 Node[NH*NVP1+NV].used = 1;
93 tricall(NumNodes[0], Node, NumTris, NULL, pTri, "cnzBNPY");
96 // Which coordinates are we triangulating on?
117 // TriTable stores the largest error in a triangle and the node where that
119 TriTable = (TRITABLE *) malloc(NH*NV*2 * sizeof(TRITABLE));
120 NumNodesToSave = min(NumNodes[0], (int)(0.01*(100-Decimate)*(NumNodes[0]-NumNodesUsed)+NumNodesUsed));
122 while(NumNodesUsed < NumNodesToSave)
124 for(i=0; i<NumTris[0]; i++)
127 // For every node that's not currently used, find what triangle it
128 // lies on, and the error at this node
129 for(i=0, biggesterror=0; i<NumNodes[0]; i++)
131 if(Node[i].used) continue;
132 for(j=0, Node[i].tri=-1; (j<NumTris[0]) && (Node[i].tri==-1); j++)
134 if( side(Node[i].p[j1], Node[i].p[j2],
135 Node[Tri[j].v[0]].p[j1],Node[Tri[j].v[0]].p[j2],
136 Node[Tri[j].v[1]].p[j1],Node[Tri[j].v[1]].p[j2]) < 0. ) continue;
137 if( side(Node[i].p[j1], Node[i].p[j2],
138 Node[Tri[j].v[1]].p[j1],Node[Tri[j].v[1]].p[j2],
139 Node[Tri[j].v[2]].p[j1],Node[Tri[j].v[2]].p[j2]) < 0. ) continue;
140 if( side(Node[i].p[j1], Node[i].p[j2],
141 Node[Tri[j].v[2]].p[j1],Node[Tri[j].v[2]].p[j2],
142 Node[Tri[j].v[0]].p[j1],Node[Tri[j].v[0]].p[j2]) < 0. ) continue;
148 ghCursorCurrent = ghCursorDefault;
149 SetCursor(ghCursorCurrent);
151 g_FuncTable.m_pfnMessageBox(g_pRadiantWnd,
152 "Error: Couldn't find the triangle bounding a point.",
153 "Decimation Error", eMB_OK, eMB_ICONWARNING);
156 if(!Tri[Node[i].tri].flag)
158 PlaneFromPoints(Node[Tri[Node[i].tri].v[0]].p,
159 Node[Tri[Node[i].tri].v[1]].p,
160 Node[Tri[Node[i].tri].v[2]].p,
161 &Tri[Node[i].tri].plane);
162 Tri[Node[i].tri].flag = 1;
165 Node[i].p[j0] - (Tri[Node[i].tri].plane.dist -
166 Tri[Node[i].tri].plane.normal[j1]*Node[i].p[j1] -
167 Tri[Node[i].tri].plane.normal[j2]*Node[i].p[j2] )/
168 Tri[Node[i].tri].plane.normal[j0];
169 biggesterror = max(biggesterror,Absolute(Node[i].error));
171 if(biggesterror == 0)
172 NumNodesToSave = NumNodesUsed;
175 // For all current triangles, build a list of worst-case nodes
176 memset(TriTable,0,NH*NV*2*sizeof(TRITABLE));
177 for(i=0; i<NumNodes[0]; i++)
179 if(Node[i].used) continue;
180 if(Absolute(Node[i].error) > TriTable[Node[i].tri].error)
182 TriTable[Node[i].tri].error = (float)(Absolute(Node[i].error));
183 TriTable[Node[i].tri].node = i;
186 qsort( (void *)TriTable, (size_t)(NumTris[0]), sizeof(TRITABLE), (int (*)(const void *, const void *))compare );
187 for(i=0; i<NumTris[0] && NumNodesUsed < NumNodesToSave && TriTable[i].error > 0.5*biggesterror; i++)
189 if(Node[TriTable[i].node].used) continue; // shouldn't happen
191 Node[TriTable[i].node].used++;
194 tricall(NumNodes[0], Node, NumTris, NULL, pTri, "cnzBNPY");
196 // Sliver-check along borders. Since borders are often linear, the errors
197 // along borders will often be zero, so no new points will be added. This
198 // tends to produce long, thin brushes. For all border triangles, check
199 // that minimum angle isn't less than SLIVER_ANGLE. If it is, add another
201 while(CheckBorders(&NumNodesUsed,NumNodes[0],Node,NumTris,pTri) > 0)
208 // One last time (because we're pessimistic), check border triangles
209 // CheckBorders(&NumNodesUsed,NumNodes[0],Node,NumTris,pTri);
212 // Check that all fixed points are exact. If not, add them to the mix.
213 // First check to see if we have any fixed points that aren't already used.
214 for(i=0, N=0; i<NumNodes[0] && !N; i++)
216 if(Node[i].used) continue;
217 if(Node[i].fixed) N++;
221 // Zero out the flag member of all triangles, indicating that
222 // the plane equation has not been found.
223 for(i=0; i<NumTris[0]; i++)
226 for(i=0; i<NumNodes[0]; i++)
228 if(Node[i].used) continue;
229 if(!Node[i].fixed) continue;
231 for(j=0; j<NumTris[0] && Node[i].tri==-1; j++)
233 if( side(Node[i].p[j1], Node[i].p[j2],
234 Node[Tri[j].v[0]].p[j1],Node[Tri[j].v[0]].p[j2],
235 Node[Tri[j].v[1]].p[j1],Node[Tri[j].v[1]].p[j2]) < 0. ) continue;
236 if( side(Node[i].p[j1], Node[i].p[j2],
237 Node[Tri[j].v[1]].p[j1],Node[Tri[j].v[1]].p[j2],
238 Node[Tri[j].v[2]].p[j1],Node[Tri[j].v[2]].p[j2]) < 0. ) continue;
239 if( side(Node[i].p[j1], Node[i].p[j2],
240 Node[Tri[j].v[2]].p[j1],Node[Tri[j].v[2]].p[j2],
241 Node[Tri[j].v[0]].p[j1],Node[Tri[j].v[0]].p[j2]) < 0. ) continue;
247 ghCursorCurrent = ghCursorDefault;
248 SetCursor(ghCursorCurrent);
250 g_FuncTable.m_pfnMessageBox(g_pRadiantWnd,
251 "Error: Couldn't find the triangle bounding a point.",
252 "Decimation Error", eMB_OK, eMB_ICONWARNING);
255 if(!Tri[Node[i].tri].flag)
257 PlaneFromPoints(Node[Tri[Node[i].tri].v[0]].p,
258 Node[Tri[Node[i].tri].v[1]].p,
259 Node[Tri[Node[i].tri].v[2]].p,
260 &Tri[Node[i].tri].plane);
261 Tri[Node[i].tri].flag = 1;
264 Node[i].p[j0] - (Tri[Node[i].tri].plane.dist -
265 Tri[Node[i].tri].plane.normal[j1]*Node[i].p[j1] -
266 Tri[Node[i].tri].plane.normal[j2]*Node[i].p[j2] )/
267 Tri[Node[i].tri].plane.normal[j0];
268 if(Absolute(Node[i].error) > 0.5)
273 tricall(NumNodes[0], Node, NumTris, NULL, pTri, "cnzBNPY");
279 // Swap node orders for surfaces facing down, north or west so that
280 // they are counterclockwise when facing the surface
282 if((Plane == PLANE_XY1) || (Plane == PLANE_XZ0) || (Plane == PLANE_YZ1) )
284 for(i=0; i<NumTris[0]; i++)
287 Tri[i].v[1] = Tri[i].v[2];
292 // Store bounding box coords
293 for(i=0; i<NumTris[0]; i++)
295 Tri[i].min[0] = Node[Tri[i].v[0]].p[0];
296 Tri[i].min[0] = min(Tri[i].min[0],Node[Tri[i].v[1]].p[0]);
297 Tri[i].min[0] = min(Tri[i].min[0],Node[Tri[i].v[2]].p[0]);
298 Tri[i].min[1] = Node[Tri[i].v[0]].p[1];
299 Tri[i].min[1] = min(Tri[i].min[1],Node[Tri[i].v[1]].p[1]);
300 Tri[i].min[1] = min(Tri[i].min[1],Node[Tri[i].v[2]].p[1]);
301 Tri[i].min[2] = Node[Tri[i].v[0]].p[2];
302 Tri[i].min[2] = min(Tri[i].min[2],Node[Tri[i].v[1]].p[2]);
303 Tri[i].min[2] = min(Tri[i].min[2],Node[Tri[i].v[2]].p[2]);
304 Tri[i].max[0] = Node[Tri[i].v[0]].p[0];
305 Tri[i].max[0] = max(Tri[i].max[0],Node[Tri[i].v[1]].p[0]);
306 Tri[i].max[0] = max(Tri[i].max[0],Node[Tri[i].v[2]].p[0]);
307 Tri[i].max[1] = Node[Tri[i].v[0]].p[1];
308 Tri[i].max[1] = max(Tri[i].max[1],Node[Tri[i].v[1]].p[1]);
309 Tri[i].max[1] = max(Tri[i].max[1],Node[Tri[i].v[2]].p[1]);
310 Tri[i].max[2] = Node[Tri[i].v[0]].p[2];
311 Tri[i].max[2] = max(Tri[i].max[2],Node[Tri[i].v[1]].p[2]);
312 Tri[i].max[2] = max(Tri[i].max[2],Node[Tri[i].v[2]].p[2]);
315 ghCursorCurrent = ghCursorDefault;
316 SetCursor(ghCursorCurrent);
319 /* end MakeDecimatedMap */
321 /*****************************************************************************/
323 /* tricall Takes an array of nodes, spits out an array of triangles */
325 /*****************************************************************************/
326 int tricall(int NumNodes, NODE *Node, int *NumTris, TRI **inTri, TRI **Tri, LPSTR Options)
329 struct triangulateio in, out;
335 /* Define input points. */
337 for(i=0,NumUsedNodes=0; i<NumNodes; i++)
338 if(Node[i].used) NumUsedNodes++;
340 memset(&in, 0,sizeof(in));
341 memset(&out,0,sizeof(out));
343 NodeTable = (int *) malloc(NumUsedNodes * sizeof(int));
345 in.numberofpoints = NumUsedNodes;
346 in.numberofpointattributes = 0;
347 in.pointlist = (REAL *) malloc(in.numberofpoints * 2 * sizeof(REAL));
348 for(i=0,N=0; i<NumNodes; i++)
356 in.pointlist[N*2 ] = Node[i].p[0];
357 in.pointlist[N*2+1] = Node[i].p[2];
361 in.pointlist[N*2 ] = Node[i].p[1];
362 in.pointlist[N*2+1] = Node[i].p[2];
365 in.pointlist[N*2 ] = Node[i].p[0];
366 in.pointlist[N*2+1] = Node[i].p[1];
372 in.pointattributelist = (REAL *) NULL;
373 in.pointmarkerlist = (int *) NULL;
375 if(strstr(Options,"r"))
378 TriTable = (int *) malloc(NumNodes * sizeof(int));
379 for(i=0,N=0; i<NumNodes; i++)
387 in.numberoftriangles = NumTris[0];
388 in.numberofcorners = 3;
389 in.numberoftriangleattributes = 0;
390 in.trianglelist = (int *) malloc(in.numberofcorners * in.numberoftriangles * sizeof(int));
391 in.triangleattributelist = (REAL *) NULL;
392 in.trianglearealist = (REAL *) NULL;
394 for(i=0; i<in.numberoftriangles; i++)
396 in.trianglelist[i*in.numberofcorners ] = TriTable[ptri[i].v[0]];
397 in.trianglelist[i*in.numberofcorners+1] = TriTable[ptri[i].v[1]];
398 in.trianglelist[i*in.numberofcorners+2] = TriTable[ptri[i].v[2]];
404 in.numberoftriangles = 0;
405 in.numberofcorners = 3;
406 in.numberoftriangleattributes = 0;
407 in.trianglelist = (int *) NULL;
408 in.triangleattributelist = (REAL *) NULL;
409 in.trianglearealist = (REAL *) NULL;
412 in.numberofsegments = 0;
413 in.segmentlist = (int *) NULL;
414 in.segmentmarkerlist = (int *) NULL;
416 in.numberofholes = 0;
417 in.holelist = (REAL *) NULL;
419 in.numberofregions = 0;
420 in.regionlist = (REAL *) NULL;
422 in.numberofedges = 0;
423 in.edgelist = (int *) NULL;
424 in.edgemarkerlist = (int *) NULL;
425 in.normlist = (REAL *) NULL;
427 /* Make necessary initializations */
428 out.pointlist = (REAL *) NULL; /* Not needed if -N switch used. */
429 out.pointattributelist = (REAL *) NULL; /* Not needed if -N switch used or
430 number of point attributes is zero: */
431 out.pointmarkerlist = (int *) NULL; /* Not needed if -N or -B switch used. */
432 out.trianglelist = (int *) NULL; /* Not needed if -E switch used. */
433 out.triangleattributelist = (REAL *) NULL; /* Not needed if -E switch used or
434 number of triangle attributes is
436 out.trianglearealist = (REAL *) NULL;
437 out.neighborlist = (int *) NULL; /* Needed only if -n switch used. */
438 out.segmentlist = (int *) NULL; /* Needed only if segments are output
439 (-p or -c) and -P not used: */
440 out.segmentmarkerlist = (int *) NULL; /* Needed only if segments are output
441 (-p or -c) and -P and -B not used: */
442 out.edgelist = (int *) NULL; /* Needed only if -e switch used. */
443 out.edgemarkerlist = (int *) NULL; /* Needed if -e used and -B not used. */
445 triangulate(Options, &in, &out, NULL);
447 NumTris[0] = out.numberoftriangles;
448 *Tri = (TRI *) malloc(NumTris[0] * sizeof(TRI));
451 for(i=0; i<NumTris[0]; i++)
453 ptri[i].v[0] = NodeTable[out.trianglelist[i*out.numberofcorners ]];
454 ptri[i].v[1] = NodeTable[out.trianglelist[i*out.numberofcorners+1]];
455 ptri[i].v[2] = NodeTable[out.trianglelist[i*out.numberofcorners+2]];
456 ptri[i].n[0] = out.neighborlist[i*3 ];
457 ptri[i].n[1] = out.neighborlist[i*3+1];
458 ptri[i].n[2] = out.neighborlist[i*3+2];
461 /* Free all allocated arrays, including those allocated by Triangle. */
462 if(in.pointlist) free(in.pointlist);
463 if(in.pointattributelist) free(in.pointattributelist);
464 if(in.pointmarkerlist) free(in.pointmarkerlist);
465 if(in.trianglelist) free(in.trianglelist);
466 if(in.triangleattributelist) free(in.triangleattributelist);
467 if(in.trianglearealist) free(in.trianglearealist);
468 if(in.neighborlist) free(in.neighborlist);
469 if(in.segmentlist) free(in.segmentlist);
470 if(in.segmentmarkerlist) free(in.segmentmarkerlist);
471 if(in.holelist) free(in.holelist);
472 if(in.regionlist) free(in.regionlist);
473 if(in.edgelist) free(in.edgelist);
474 if(in.edgemarkerlist) free(in.edgemarkerlist);
475 if(in.normlist) free(in.normlist);
476 if(out.pointlist) free(out.pointlist);
477 if(out.pointattributelist) free(out.pointattributelist);
478 if(out.pointmarkerlist) free(out.pointmarkerlist);
479 if(out.trianglelist) free(out.trianglelist);
480 if(out.triangleattributelist) free(out.triangleattributelist);
481 if(out.trianglearealist) free(out.trianglearealist);
482 if(out.neighborlist) free(out.neighborlist);
483 if(out.segmentlist) free(out.segmentlist);
484 if(out.segmentmarkerlist) free(out.segmentmarkerlist);
485 if(out.holelist) free(out.holelist);
486 if(out.regionlist) free(out.regionlist);
487 if(out.edgelist) free(out.edgelist);
488 if(out.edgemarkerlist) free(out.edgemarkerlist);
489 if(out.normlist) free(out.normlist);
495 void EdgeOnSide(int *v, int *edge, int *border)
503 if( (v[0] <= NV) && (v[1] <= NV) )
508 if( (v[1] <= NV) && (v[2] <= NV) )
513 if( (v[2] <= NV) && (v[0] <= NV) )
521 if( (v[0] >= R) && (v[1] >= R) )
526 if( (v[1] >= R) && (v[2] >= R) )
531 if( (v[2] >= R) && (v[0] >= R) )
541 N = Absolute(v[k0] - v[k1]);
544 if( ((v[0] % NVP1) == 0) && ((v[1] % NVP1) == 0) )
547 if( Ndv > (Absolute(v[0] - v[1])*dh)) return;
552 if( ((v[1] % NVP1) == 0) && ((v[2] % NVP1) == 0) )
555 if( Ndv > (Absolute(v[1] - v[2])*dh)) return;
560 if( ((v[2] % NVP1) == 0) && ((v[0] % NVP1) == 0) )
563 if( Ndv > (Absolute(v[2] - v[0])*dh)) return;
569 if( ((v[0] % NVP1) == NV) && ((v[1] % NVP1) == NV) )
572 if( Ndv > (Absolute(v[0] - v[1])*dh)) return;
577 if( ((v[1] % NVP1) == NV) && ((v[2] % NVP1) == NV) )
580 if( Ndv > (Absolute(v[1] - v[2])*dh)) return;
585 if( ((v[2] % NVP1) == NV) && ((v[0] % NVP1) == NV) )
588 if( Ndv > (Absolute(v[2] - v[0])*dh)) return;
596 void CalcAngles(NODE *node, int *v, float *angle)
600 vec x0, x1, x2, y0, y1, y2;
620 x0 = node[v[0]].p[i];
621 x1 = node[v[1]].p[i];
622 x2 = node[v[2]].p[i];
623 y0 = node[v[0]].p[j];
624 y1 = node[v[1]].p[j];
625 y2 = node[v[2]].p[j];
636 l = (vec)(sqrt( vv[k][0]*vv[k][0] + vv[k][1]*vv[k][1] ));
644 dot = -(vv[0][0]*vv[2][0] + vv[0][1]*vv[2][1]);
645 angle[0] = (float)(acos(dot));
646 dot = -(vv[1][0]*vv[0][0] + vv[1][1]*vv[0][1]);
647 angle[1] = (float)(acos(dot));
648 dot = -(vv[2][0]*vv[1][0] + vv[2][1]*vv[1][1]);
649 angle[2] = (float)(acos(dot));
651 //=================================================================
652 int Bisect(NODE *node, int border, int j0, int j1)
665 k = (int)((j0+j1)/(2*NVP1)) * NVP1;
668 k = (int)((j0+j1+2)/(2*NVP1)) * NVP1 - 1;
671 return( ((k != j0) && (k != j1)) ? k : 0 );
673 //=================================================================
674 int compare(TRITABLE *t1, TRITABLE *t2)
676 if(t1->error > t2->error) return -1;
677 if(t1->error < t2->error) return 1;
681 void MakeBrushes(int NumTris, NODE *Node, TRI *Tri,bool surf,
682 int offset,char *texture0, char *texture1, char *texture2)
684 extern double backface;
689 vec3_t PlaneNormal,SurfNormal;
693 // if texture2 is identical to texture0, there's no need to
694 // check surface angle
695 if(!g_strcasecmp(texture0,texture2) || !strlen(texture2))
700 Steep = (float)cos((double)SlantAngle/57.2957795);
703 case PLANE_XY0: PlaneNormal[0]= 0.;PlaneNormal[1]= 0.;PlaneNormal[2]= 1.;break;
704 case PLANE_XY1: PlaneNormal[0]= 0.;PlaneNormal[1]= 0.;PlaneNormal[2]=-1.;break;
705 case PLANE_XZ0: PlaneNormal[0]= 0.;PlaneNormal[1]= 1.;PlaneNormal[2]= 1.;break;
706 case PLANE_XZ1: PlaneNormal[0]= 0.;PlaneNormal[1]=-1.;PlaneNormal[2]= 1.;break;
707 case PLANE_YZ0: PlaneNormal[0]= 1.;PlaneNormal[1]= 0.;PlaneNormal[2]= 1.;break;
708 case PLANE_YZ1: PlaneNormal[0]=-1.;PlaneNormal[1]= 0.;PlaneNormal[2]= 1.;break;
715 if(UseDetail) contents += CONTENTS_DETAIL;
716 if(UseLadder) contents += CONTENTS_LADDER;
720 for(i=0; i<NumTris; i++)
725 brush.face[0].v[0][0] = Node[Tri[i].v[0]].p[0];
726 brush.face[0].v[0][1] = Node[Tri[i].v[0]].p[1];
727 brush.face[0].v[0][2] = Node[Tri[i].v[0]].p[2];
729 brush.face[0].v[1][0] = Node[Tri[i].v[2]].p[0];
730 brush.face[0].v[1][1] = Node[Tri[i].v[2]].p[1];
731 brush.face[0].v[1][2] = Node[Tri[i].v[2]].p[2];
733 brush.face[0].v[2][0] = Node[Tri[i].v[1]].p[0];
734 brush.face[0].v[2][1] = Node[Tri[i].v[1]].p[1];
735 brush.face[0].v[2][2] = Node[Tri[i].v[1]].p[2];
742 brush.face[0].v[0][2] += offset;
743 brush.face[0].v[1][2] += offset;
744 brush.face[0].v[1][2] += offset;
747 brush.face[0].v[0][2] -= offset;
748 brush.face[0].v[1][2] -= offset;
749 brush.face[0].v[1][2] -= offset;
752 brush.face[0].v[0][1] += offset;
753 brush.face[0].v[1][1] += offset;
754 brush.face[0].v[1][1] += offset;
757 brush.face[0].v[0][1] -= offset;
758 brush.face[0].v[1][1] -= offset;
759 brush.face[0].v[1][1] -= offset;
762 brush.face[0].v[0][0] += offset;
763 brush.face[0].v[1][0] += offset;
764 brush.face[0].v[1][0] += offset;
767 brush.face[0].v[0][0] -= offset;
768 brush.face[0].v[1][0] -= offset;
769 brush.face[0].v[1][0] -= offset;
778 brush.face[1].v[0][0] = Node[Tri[i].v[0]].p[0];
779 brush.face[1].v[0][1] = (float)backface;
780 brush.face[1].v[0][2] = Node[Tri[i].v[0]].p[2];
782 brush.face[1].v[1][0] = Node[Tri[i].v[1]].p[0];
783 brush.face[1].v[1][1] = (float)backface;
784 brush.face[1].v[1][2] = Node[Tri[i].v[1]].p[2];
786 brush.face[1].v[2][0] = Node[Tri[i].v[2]].p[0];
787 brush.face[1].v[2][1] = (float)backface;
788 brush.face[1].v[2][2] = Node[Tri[i].v[2]].p[2];
791 brush.face[2].v[0][0] = Node[Tri[i].v[0]].p[0];
792 brush.face[2].v[0][1] = Node[Tri[i].v[0]].p[1];
793 brush.face[2].v[0][2] = Node[Tri[i].v[0]].p[2];
795 brush.face[2].v[1][0] = Node[Tri[i].v[1]].p[0];
796 brush.face[2].v[1][1] = Node[Tri[i].v[1]].p[1];
797 brush.face[2].v[1][2] = Node[Tri[i].v[1]].p[2];
799 brush.face[2].v[2][0] = Node[Tri[i].v[1]].p[0];
800 brush.face[2].v[2][1] = (float)backface;
801 brush.face[2].v[2][2] = Node[Tri[i].v[1]].p[2];
804 brush.face[3].v[0][0] = Node[Tri[i].v[1]].p[0];
805 brush.face[3].v[0][1] = Node[Tri[i].v[1]].p[1];
806 brush.face[3].v[0][2] = Node[Tri[i].v[1]].p[2];
808 brush.face[3].v[1][0] = Node[Tri[i].v[2]].p[0];
809 brush.face[3].v[1][1] = Node[Tri[i].v[2]].p[1];
810 brush.face[3].v[1][2] = Node[Tri[i].v[2]].p[2];
812 brush.face[3].v[2][0] = Node[Tri[i].v[2]].p[0];
813 brush.face[3].v[2][1] = (float)backface;
814 brush.face[3].v[2][2] = Node[Tri[i].v[2]].p[2];
817 brush.face[4].v[0][0] = Node[Tri[i].v[2]].p[0];
818 brush.face[4].v[0][1] = Node[Tri[i].v[2]].p[1];
819 brush.face[4].v[0][2] = Node[Tri[i].v[2]].p[2];
821 brush.face[4].v[1][0] = Node[Tri[i].v[0]].p[0];
822 brush.face[4].v[1][1] = Node[Tri[i].v[0]].p[1];
823 brush.face[4].v[1][2] = Node[Tri[i].v[0]].p[2];
825 brush.face[4].v[2][0] = Node[Tri[i].v[0]].p[0];
826 brush.face[4].v[2][1] = (float)backface;
827 brush.face[4].v[2][2] = Node[Tri[i].v[0]].p[2];
832 brush.face[1].v[0][0] = (float)backface;
833 brush.face[1].v[0][1] = Node[Tri[i].v[0]].p[1];
834 brush.face[1].v[0][2] = Node[Tri[i].v[0]].p[2];
836 brush.face[1].v[1][0] = (float)backface;
837 brush.face[1].v[1][1] = Node[Tri[i].v[1]].p[1];
838 brush.face[1].v[1][2] = Node[Tri[i].v[1]].p[2];
840 brush.face[1].v[2][0] = (float)backface;
841 brush.face[1].v[2][1] = Node[Tri[i].v[2]].p[1];
842 brush.face[1].v[2][2] = Node[Tri[i].v[2]].p[2];
845 brush.face[2].v[0][0] = Node[Tri[i].v[0]].p[0];
846 brush.face[2].v[0][1] = Node[Tri[i].v[0]].p[1];
847 brush.face[2].v[0][2] = Node[Tri[i].v[0]].p[2];
849 brush.face[2].v[1][0] = Node[Tri[i].v[1]].p[0];
850 brush.face[2].v[1][1] = Node[Tri[i].v[1]].p[1];
851 brush.face[2].v[1][2] = Node[Tri[i].v[1]].p[2];
853 brush.face[2].v[2][0] = (float)backface;
854 brush.face[2].v[2][1] = Node[Tri[i].v[1]].p[1];
855 brush.face[2].v[2][2] = Node[Tri[i].v[1]].p[2];
858 brush.face[3].v[0][0] = Node[Tri[i].v[1]].p[0];
859 brush.face[3].v[0][1] = Node[Tri[i].v[1]].p[1];
860 brush.face[3].v[0][2] = Node[Tri[i].v[1]].p[2];
862 brush.face[3].v[1][0] = Node[Tri[i].v[2]].p[0];
863 brush.face[3].v[1][1] = Node[Tri[i].v[2]].p[1];
864 brush.face[3].v[1][2] = Node[Tri[i].v[2]].p[2];
866 brush.face[3].v[2][0] = (float)backface;
867 brush.face[3].v[2][1] = Node[Tri[i].v[2]].p[1];
868 brush.face[3].v[2][2] = Node[Tri[i].v[2]].p[2];
871 brush.face[4].v[0][0] = Node[Tri[i].v[2]].p[0];
872 brush.face[4].v[0][1] = Node[Tri[i].v[2]].p[1];
873 brush.face[4].v[0][2] = Node[Tri[i].v[2]].p[2];
875 brush.face[4].v[1][0] = Node[Tri[i].v[0]].p[0];
876 brush.face[4].v[1][1] = Node[Tri[i].v[0]].p[1];
877 brush.face[4].v[1][2] = Node[Tri[i].v[0]].p[2];
879 brush.face[4].v[2][0] = (float)backface;
880 brush.face[4].v[2][1] = Node[Tri[i].v[0]].p[1];
881 brush.face[4].v[2][2] = Node[Tri[i].v[0]].p[2];
885 brush.face[1].v[0][0] = Node[Tri[i].v[0]].p[0];
886 brush.face[1].v[0][1] = Node[Tri[i].v[0]].p[1];
887 brush.face[1].v[0][2] = (float)backface;
889 brush.face[1].v[1][0] = Node[Tri[i].v[1]].p[0];
890 brush.face[1].v[1][1] = Node[Tri[i].v[1]].p[1];
891 brush.face[1].v[1][2] = (float)backface;
893 brush.face[1].v[2][0] = Node[Tri[i].v[2]].p[0];
894 brush.face[1].v[2][1] = Node[Tri[i].v[2]].p[1];
895 brush.face[1].v[2][2] = (float)backface;
898 brush.face[2].v[0][0] = Node[Tri[i].v[0]].p[0];
899 brush.face[2].v[0][1] = Node[Tri[i].v[0]].p[1];
900 brush.face[2].v[0][2] = Node[Tri[i].v[0]].p[2];
902 brush.face[2].v[1][0] = Node[Tri[i].v[1]].p[0];
903 brush.face[2].v[1][1] = Node[Tri[i].v[1]].p[1];
904 brush.face[2].v[1][2] = Node[Tri[i].v[1]].p[2];
906 brush.face[2].v[2][0] = Node[Tri[i].v[1]].p[0];
907 brush.face[2].v[2][1] = Node[Tri[i].v[1]].p[1];
908 brush.face[2].v[2][2] = (float)backface;
911 brush.face[3].v[0][0] = Node[Tri[i].v[1]].p[0];
912 brush.face[3].v[0][1] = Node[Tri[i].v[1]].p[1];
913 brush.face[3].v[0][2] = Node[Tri[i].v[1]].p[2];
915 brush.face[3].v[1][0] = Node[Tri[i].v[2]].p[0];
916 brush.face[3].v[1][1] = Node[Tri[i].v[2]].p[1];
917 brush.face[3].v[1][2] = Node[Tri[i].v[2]].p[2];
919 brush.face[3].v[2][0] = Node[Tri[i].v[2]].p[0];
920 brush.face[3].v[2][1] = Node[Tri[i].v[2]].p[1];
921 brush.face[3].v[2][2] = (float)backface;
924 brush.face[4].v[0][0] = Node[Tri[i].v[2]].p[0];
925 brush.face[4].v[0][1] = Node[Tri[i].v[2]].p[1];
926 brush.face[4].v[0][2] = Node[Tri[i].v[2]].p[2];
928 brush.face[4].v[1][0] = Node[Tri[i].v[0]].p[0];
929 brush.face[4].v[1][1] = Node[Tri[i].v[0]].p[1];
930 brush.face[4].v[1][2] = Node[Tri[i].v[0]].p[2];
932 brush.face[4].v[2][0] = Node[Tri[i].v[0]].p[0];
933 brush.face[4].v[2][1] = Node[Tri[i].v[0]].p[1];
934 brush.face[4].v[2][2] = (float)backface;
939 strcpy(brush.face[j].texture,
940 (strlen(texture1) ? texture1 : texture0));
941 brush.face[j].Shift[0] = (float)TexOffset[0];
942 brush.face[j].Shift[1] = (float)TexOffset[1];
943 brush.face[j].Rotate = 0.;
944 brush.face[j].Scale[0] = (float)TexScale[0];
945 brush.face[j].Scale[1] = (float)TexScale[1];
946 brush.face[j].Contents = contents;
948 brush.face[j].Surface = 0;
950 brush.face[j].Surface = SURF_HINT;
951 brush.face[j].Value = 0;
956 XYZVectorSubtract(brush.face[0].v[2],brush.face[0].v[0],t[0]);
957 XYZVectorSubtract(brush.face[0].v[1],brush.face[0].v[2],t[1]);
958 CrossProduct(t[0],t[1],SurfNormal);
959 VectorNormalize(SurfNormal,SurfNormal);
960 if(DotProduct(SurfNormal,PlaneNormal) < Steep)
961 strcpy(brush.face[0].texture,texture2);
963 strcpy(brush.face[0].texture,texture0);
966 strcpy(brush.face[0].texture,texture0);
968 if(surf) brush.face[0].Value = ArghRad2;
974 //=================================================================
975 void MapOut(int NumNodes,int NumTris, NODE *Node, TRI *Tri)
977 extern double backface;
978 extern double xmin, xmax, ymin, ymax, zmin, zmax;
980 char hint[32], skip[32];
984 ghCursorCurrent = LoadCursor(NULL,IDC_WAIT);
985 SetCursor(ghCursorCurrent);
987 UseDetail = 1; // this is temporary
988 MakeBrushes(NumTris,Node,Tri,TRUE,0,Texture[Game][0],Texture[Game][1],Texture[Game][2]);
990 if(AddHints || GimpHints)
995 strcpy(hint,"generic/misc/hint");
996 strcpy(skip,"generic/misc/skip");
1000 strcpy(skip,"HINT");
1003 strcpy(hint,"general/hint");
1004 strcpy(skip,"general/skip");
1007 strcpy(hint,"common/0_hint");
1008 strcpy(skip,"common/0_skip");
1011 strcpy(hint,"common/hint");
1012 strcpy(skip,"common/skip");
1015 strcpy(hint,"e1u1/hint");
1016 strcpy(skip,"e1u1/skip");
1021 MakeBrushes(NumTris,Node,Tri,FALSE,HINT_OFFSET,hint,hint,hint);
1025 int j0, j1, j2, k, k0, k1;
1030 int MaxHints; // We don't want a whole slew of hint brushes, which we'd get
1031 // with low decimation values and our current placement scheme.
1032 // Limit number of hint brushes to number of undecimated grid
1038 front = LessThan(zmin,32.);
1041 front = MoreThan(ymax,32.);
1044 front = LessThan(ymin,32.);
1047 front = MoreThan(xmax,32.);
1050 front = LessThan(xmin,32.);
1053 front = MoreThan(zmax,32.);
1056 for(i=0; i<NumTris; i++)
1082 for(w=1; w<min(16,NH) && brush.Number < MaxHints; w++)
1084 for(h=max(1,w/2); h<min(16,NV) && brush.Number < MaxHints; h++)
1086 for(i=0; i<=NH-w && brush.Number < MaxHints; i++)
1088 for(j=0; j<=NV-h && brush.Number < MaxHints; j++)
1091 q[2] = q[0] + w*NVP1 + h;
1104 for(k=0, OK=1; k<NumTris && OK; k++)
1106 if(Tri[k].min[j1] >= max(Node[q[0]].p[j1],Node[q[2]].p[j1])) continue;
1107 if(Tri[k].min[j2] >= max(Node[q[0]].p[j2],Node[q[2]].p[j2])) continue;
1108 if(Tri[k].max[j1] <= min(Node[q[0]].p[j1],Node[q[2]].p[j1])) continue;
1109 if(Tri[k].max[j2] <= min(Node[q[0]].p[j2],Node[q[2]].p[j2])) continue;
1111 for(h0=0; h0<4 && OK; h0++)
1114 for(t=0; t<3 && OK; t++)
1116 s[t] = side(Node[q[h0]].p[j1],Node[q[h0]].p[j2],
1117 Node[q[h1]].p[j1],Node[q[h1]].p[j2],
1118 Node[Tri[k].v[t]].p[j1],Node[Tri[k].v[t]].p[j2]);
1120 if((s[1] > 0 || s[2] > 0) && s[0] < 0) OK=0;
1121 if((s[2] > 0 || s[0] > 0) && s[1] < 0) OK=0;
1122 if((s[0] > 0 || s[1] > 0) && s[2] < 0) OK=0;
1131 brush.face[0].v[0][0] = Node[q[2]].p[0];
1132 brush.face[0].v[0][1] = (float)front;
1133 brush.face[0].v[0][2] = Node[q[2]].p[2];
1135 brush.face[0].v[1][0] = Node[q[1]].p[0];
1136 brush.face[0].v[1][1] = (float)front;
1137 brush.face[0].v[1][2] = Node[q[1]].p[2];
1139 brush.face[0].v[2][0] = Node[q[0]].p[0];
1140 brush.face[0].v[2][1] = (float)front;
1141 brush.face[0].v[2][2] = Node[q[0]].p[2];
1144 brush.face[1].v[0][0] = Node[q[0]].p[0];
1145 brush.face[1].v[0][1] = (float)backface;
1146 brush.face[1].v[0][2] = Node[q[0]].p[2];
1148 brush.face[1].v[1][0] = Node[q[1]].p[0];
1149 brush.face[1].v[1][1] = (float)backface;
1150 brush.face[1].v[1][2] = Node[q[1]].p[2];
1152 brush.face[1].v[2][0] = Node[q[2]].p[0];
1153 brush.face[1].v[2][1] = (float)backface;
1154 brush.face[1].v[2][2] = Node[q[2]].p[2];
1156 for(k0=0; k0<brush.NumFaces-2; k0++)
1159 k1=(k0+1) % (brush.NumFaces-2);
1161 brush.face[k].v[0][0] = Node[q[k0]].p[0];
1162 brush.face[k].v[0][1] = (float)front;
1163 brush.face[k].v[0][2] = Node[q[k0]].p[2];
1165 brush.face[k].v[1][0] = Node[q[k1]].p[0];
1166 brush.face[k].v[1][1] = (float)front;
1167 brush.face[k].v[1][2] = Node[q[k1]].p[2];
1169 brush.face[k].v[2][0] = Node[q[k1]].p[0];
1170 brush.face[k].v[2][1] = (float)backface;
1171 brush.face[k].v[2][2] = Node[q[k1]].p[2];
1177 brush.face[0].v[0][0] = (float)front;
1178 brush.face[0].v[0][1] = Node[q[2]].p[1];
1179 brush.face[0].v[0][2] = Node[q[2]].p[2];
1181 brush.face[0].v[1][0] = (float)front;
1182 brush.face[0].v[1][1] = Node[q[1]].p[1];
1183 brush.face[0].v[1][2] = Node[q[1]].p[2];
1185 brush.face[0].v[2][0] = (float)front;
1186 brush.face[0].v[2][1] = Node[q[0]].p[1];
1187 brush.face[0].v[2][2] = Node[q[0]].p[2];
1190 brush.face[1].v[0][0] = (float)backface;
1191 brush.face[1].v[0][1] = Node[q[0]].p[1];
1192 brush.face[1].v[0][2] = Node[q[0]].p[2];
1194 brush.face[1].v[1][0] = (float)backface;
1195 brush.face[1].v[1][1] = Node[q[1]].p[1];
1196 brush.face[1].v[1][2] = Node[q[1]].p[2];
1198 brush.face[1].v[2][0] = (float)backface;
1199 brush.face[1].v[2][1] = Node[q[2]].p[1];
1200 brush.face[1].v[2][2] = Node[q[2]].p[2];
1202 for(k0=0; k0<brush.NumFaces-2; k0++)
1205 k1=(k0+1) % (brush.NumFaces-2);
1207 brush.face[k].v[0][0] = (float)front;
1208 brush.face[k].v[0][1] = Node[q[k0]].p[1];
1209 brush.face[k].v[0][2] = Node[q[k0]].p[2];
1211 brush.face[k].v[1][0] = (float)front;
1212 brush.face[k].v[1][1] = Node[q[k1]].p[1];
1213 brush.face[k].v[1][2] = Node[q[k1]].p[2];
1215 brush.face[k].v[2][0] = (float)backface;
1216 brush.face[k].v[2][1] = Node[q[k1]].p[1];
1217 brush.face[k].v[2][2] = Node[q[k1]].p[2];
1222 brush.face[0].v[0][0] = Node[q[2]].p[0];
1223 brush.face[0].v[0][1] = Node[q[2]].p[1];
1224 brush.face[0].v[0][2] = (float)front;
1226 brush.face[0].v[1][0] = Node[q[1]].p[0];
1227 brush.face[0].v[1][1] = Node[q[1]].p[1];
1228 brush.face[0].v[1][2] = (float)front;
1230 brush.face[0].v[2][0] = Node[q[0]].p[0];
1231 brush.face[0].v[2][1] = Node[q[0]].p[1];
1232 brush.face[0].v[2][2] = (float)front;
1235 brush.face[1].v[0][0] = Node[q[0]].p[0];
1236 brush.face[1].v[0][1] = Node[q[0]].p[1];
1237 brush.face[1].v[0][2] = (float)backface;
1239 brush.face[1].v[1][0] = Node[q[1]].p[0];
1240 brush.face[1].v[1][1] = Node[q[1]].p[1];
1241 brush.face[1].v[1][2] = (float)backface;
1243 brush.face[1].v[2][0] = Node[q[2]].p[0];
1244 brush.face[1].v[2][1] = Node[q[2]].p[1];
1245 brush.face[1].v[2][2] = (float)backface;
1247 for(k0=0; k0<brush.NumFaces-2; k0++)
1250 k1=(k0+1) % (brush.NumFaces-2);
1252 brush.face[k].v[0][0] = Node[q[k0]].p[0];
1253 brush.face[k].v[0][1] = Node[q[k0]].p[1];
1254 brush.face[k].v[0][2] = (float)front;
1256 brush.face[k].v[1][0] = Node[q[k1]].p[0];
1257 brush.face[k].v[1][1] = Node[q[k1]].p[1];
1258 brush.face[k].v[1][2] = (float)front;
1260 brush.face[k].v[2][0] = Node[q[k1]].p[0];
1261 brush.face[k].v[2][1] = Node[q[k1]].p[1];
1262 brush.face[k].v[2][2] = (float)backface;
1266 for(face=0; face<6; face++)
1268 strcpy(brush.face[face].texture,(face<=1 ? skip : hint));
1269 brush.face[face].Shift[0] = 0;
1270 brush.face[face].Shift[1] = 0;
1271 brush.face[face].Rotate = 0.;
1272 brush.face[face].Scale[0] = 1;
1273 brush.face[face].Scale[1] = 1;
1274 brush.face[face].Contents = CONTENTS_DETAIL;
1275 brush.face[face].Surface = (face<=1 ? SURF_SKIP : SURF_HINT);
1276 brush.face[face].Value = 0;
1278 if(!brush.Number) OpenFuncGroup();
1285 if(brush.Number) CloseFuncGroup();
1288 ghCursorCurrent = ghCursorDefault;
1289 SetCursor(ghCursorCurrent);
1292 //===========================================================================
1293 int CheckBorders(int *NumNodesUsed, int NumNodes, NODE *Node, int *NumTris, TRI **pTri)
1296 int i, j, k0, k1, N;
1300 N = NumNodesUsed[0];
1302 for(i=0; i<NumTris[0]; i++)
1304 EdgeOnSide(Tri[i].v,&k0,&border);
1305 if(border < 0) continue;
1306 CalcAngles(Node, Tri[i].v, angle);
1308 if((angle[k0] < SLIVER_ANGLE) || (angle[k1] < SLIVER_ANGLE))
1310 j = Bisect(Node, border, Tri[i].v[k0], Tri[i].v[k1]);
1313 if(!Node[j].used) // Shouldn't be used, but...
1321 if(NumNodesUsed[0] > N)
1324 tricall(NumNodes, Node, NumTris, NULL, pTri, "cnzBNPY");
1327 return (NumNodesUsed[0] - N);