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 */
41 #define Absolute(a) ( ( a ) >= 0.0 ? ( a ) : -( a ) )
43 void MakeDecimatedMap(int *NumNodes, int *NumTris, NODE **pNode, TRI **pTri)
45 int compare(TRITABLE *, TRITABLE *);
46 int Bisect(NODE *, int, int, int);
47 void CalcAngles(NODE *, int *, float *);
48 void EdgeOnSide(int *, int *, int *);
49 int tricall(int, NODE *, int *, TRI **, TRI **, const char *);
50 int CheckBorders(int *, int, NODE *, int *, TRI **);
65 ghCursorCurrent = LoadCursor(NULL,IDC_WAIT);
66 SetCursor(ghCursorCurrent);
68 dh = (Hur - Hll) / NH;
69 dv = (Vur - Vll) / NV;
72 NumNodes[0] = (NH + 1) * (NVP1);
73 *pNode = (NODE *) malloc(NumNodes[0] * sizeof(NODE));
75 memset(Node, 0, NumNodes[0] * sizeof(NODE));
77 // Copy [NH][NV] vertex array to our working node array
78 for (i = 0, N = 0; i <= NH; i++) {
79 for (j = 0; j <= NV; j++, N++) {
80 Node[N].p[0] = (float) xyz[i][j].p[0];
81 Node[N].p[1] = (float) xyz[i][j].p[1];
82 Node[N].p[2] = (float) xyz[i][j].p[2];
83 Node[N].fixed = xyz[i][j].fixed;
86 // Start things off with the corner values
89 Node[NH * NVP1].used = 1;
90 Node[NH * NVP1 + NV].used = 1;
92 tricall(NumNodes[0], Node, NumTris, NULL, pTri, "cnzBNPY");
95 // Which coordinates are we triangulating on?
115 // TriTable stores the largest error in a triangle and the node where that
117 TriTable = (TRITABLE *) malloc(NH * NV * 2 * sizeof(TRITABLE));
118 NumNodesToSave = min(NumNodes[0], (int) (0.01 * (100 - Decimate) * (NumNodes[0] - NumNodesUsed) + NumNodesUsed));
120 while (NumNodesUsed < NumNodesToSave) {
121 for (i = 0; i < NumTris[0]; i++) {
125 // For every node that's not currently used, find what triangle it
126 // lies on, and the error at this node
127 for (i = 0, biggesterror = 0; i < NumNodes[0]; i++) {
131 for (j = 0, Node[i].tri = -1; (j < NumTris[0]) && (Node[i].tri == -1); j++) {
132 if (side(Node[i].p[j1], Node[i].p[j2],
133 Node[Tri[j].v[0]].p[j1], Node[Tri[j].v[0]].p[j2],
134 Node[Tri[j].v[1]].p[j1], Node[Tri[j].v[1]].p[j2]) < 0.) {
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.) {
142 if (side(Node[i].p[j1], Node[i].p[j2],
143 Node[Tri[j].v[2]].p[j1], Node[Tri[j].v[2]].p[j2],
144 Node[Tri[j].v[0]].p[j1], Node[Tri[j].v[0]].p[j2]) < 0.) {
149 if (Node[i].tri < 0) {
151 ghCursorCurrent = ghCursorDefault;
152 SetCursor(ghCursorCurrent);
154 g_FuncTable.m_pfnMessageBox(g_pRadiantWnd,
155 "Error: Couldn't find the triangle bounding a point.",
156 "Decimation Error", eMB_OK, eMB_ICONWARNING);
159 if (!Tri[Node[i].tri].flag) {
160 PlaneFromPoints(Node[Tri[Node[i].tri].v[0]].p,
161 Node[Tri[Node[i].tri].v[1]].p,
162 Node[Tri[Node[i].tri].v[2]].p,
163 &Tri[Node[i].tri].plane);
164 Tri[Node[i].tri].flag = 1;
167 Node[i].p[j0] - (Tri[Node[i].tri].plane.dist -
168 Tri[Node[i].tri].plane.normal[j1] * Node[i].p[j1] -
169 Tri[Node[i].tri].plane.normal[j2] * Node[i].p[j2]) /
170 Tri[Node[i].tri].plane.normal[j0];
171 biggesterror = max(biggesterror, Absolute(Node[i].error));
173 if (biggesterror == 0) {
174 NumNodesToSave = NumNodesUsed;
176 // For all current triangles, build a list of worst-case nodes
177 memset(TriTable, 0, NH * NV * 2 * sizeof(TRITABLE));
178 for (i = 0; i < NumNodes[0]; i++) {
182 if (Absolute(Node[i].error) > TriTable[Node[i].tri].error) {
183 TriTable[Node[i].tri].error = (float) (Absolute(Node[i].error));
184 TriTable[Node[i].tri].node = i;
187 qsort((void *) TriTable, (size_t)(NumTris[0]), sizeof(TRITABLE),
188 (int (*)(const void *, const void *)) compare);
190 i < NumTris[0] && NumNodesUsed < NumNodesToSave && TriTable[i].error > 0.5 * biggesterror; i++) {
191 if (Node[TriTable[i].node].used) {
192 continue; // shouldn't happen
195 Node[TriTable[i].node].used++;
198 tricall(NumNodes[0], Node, NumTris, NULL, pTri, "cnzBNPY");
200 // Sliver-check along borders. Since borders are often linear, the errors
201 // along borders will often be zero, so no new points will be added. This
202 // tends to produce long, thin brushes. For all border triangles, check
203 // that minimum angle isn't less than SLIVER_ANGLE. If it is, add another
205 while (CheckBorders(&NumNodesUsed, NumNodes[0], Node, NumTris, pTri) > 0) {
211 // One last time (because we're pessimistic), check border triangles
212 // CheckBorders(&NumNodesUsed,NumNodes[0],Node,NumTris,pTri);
215 // Check that all fixed points are exact. If not, add them to the mix.
216 // First check to see if we have any fixed points that aren't already used.
217 for (i = 0, N = 0; i < NumNodes[0] && !N; i++) {
226 // Zero out the flag member of all triangles, indicating that
227 // the plane equation has not been found.
228 for (i = 0; i < NumTris[0]; i++) {
232 for (i = 0; i < NumNodes[0]; i++) {
236 if (!Node[i].fixed) {
240 for (j = 0; j < NumTris[0] && Node[i].tri == -1; j++) {
241 if (side(Node[i].p[j1], Node[i].p[j2],
242 Node[Tri[j].v[0]].p[j1], Node[Tri[j].v[0]].p[j2],
243 Node[Tri[j].v[1]].p[j1], Node[Tri[j].v[1]].p[j2]) < 0.) {
246 if (side(Node[i].p[j1], Node[i].p[j2],
247 Node[Tri[j].v[1]].p[j1], Node[Tri[j].v[1]].p[j2],
248 Node[Tri[j].v[2]].p[j1], Node[Tri[j].v[2]].p[j2]) < 0.) {
251 if (side(Node[i].p[j1], Node[i].p[j2],
252 Node[Tri[j].v[2]].p[j1], Node[Tri[j].v[2]].p[j2],
253 Node[Tri[j].v[0]].p[j1], Node[Tri[j].v[0]].p[j2]) < 0.) {
258 if (Node[i].tri < 0) {
260 ghCursorCurrent = ghCursorDefault;
261 SetCursor(ghCursorCurrent);
263 g_FuncTable.m_pfnMessageBox(g_pRadiantWnd,
264 "Error: Couldn't find the triangle bounding a point.",
265 "Decimation Error", eMB_OK, eMB_ICONWARNING);
268 if (!Tri[Node[i].tri].flag) {
269 PlaneFromPoints(Node[Tri[Node[i].tri].v[0]].p,
270 Node[Tri[Node[i].tri].v[1]].p,
271 Node[Tri[Node[i].tri].v[2]].p,
272 &Tri[Node[i].tri].plane);
273 Tri[Node[i].tri].flag = 1;
276 Node[i].p[j0] - (Tri[Node[i].tri].plane.dist -
277 Tri[Node[i].tri].plane.normal[j1] * Node[i].p[j1] -
278 Tri[Node[i].tri].plane.normal[j2] * Node[i].p[j2]) /
279 Tri[Node[i].tri].plane.normal[j0];
280 if (Absolute(Node[i].error) > 0.5) {
284 tricall(NumNodes[0], Node, NumTris, NULL, pTri, "cnzBNPY");
290 // Swap node orders for surfaces facing down, north or west so that
291 // they are counterclockwise when facing the surface
293 if ((Plane == PLANE_XY1) || (Plane == PLANE_XZ0) || (Plane == PLANE_YZ1)) {
294 for (i = 0; i < NumTris[0]; i++) {
296 Tri[i].v[1] = Tri[i].v[2];
301 // Store bounding box coords
302 for (i = 0; i < NumTris[0]; i++) {
303 Tri[i].min[0] = Node[Tri[i].v[0]].p[0];
304 Tri[i].min[0] = min(Tri[i].min[0], Node[Tri[i].v[1]].p[0]);
305 Tri[i].min[0] = min(Tri[i].min[0], Node[Tri[i].v[2]].p[0]);
306 Tri[i].min[1] = Node[Tri[i].v[0]].p[1];
307 Tri[i].min[1] = min(Tri[i].min[1], Node[Tri[i].v[1]].p[1]);
308 Tri[i].min[1] = min(Tri[i].min[1], Node[Tri[i].v[2]].p[1]);
309 Tri[i].min[2] = Node[Tri[i].v[0]].p[2];
310 Tri[i].min[2] = min(Tri[i].min[2], Node[Tri[i].v[1]].p[2]);
311 Tri[i].min[2] = min(Tri[i].min[2], Node[Tri[i].v[2]].p[2]);
312 Tri[i].max[0] = Node[Tri[i].v[0]].p[0];
313 Tri[i].max[0] = max(Tri[i].max[0], Node[Tri[i].v[1]].p[0]);
314 Tri[i].max[0] = max(Tri[i].max[0], Node[Tri[i].v[2]].p[0]);
315 Tri[i].max[1] = Node[Tri[i].v[0]].p[1];
316 Tri[i].max[1] = max(Tri[i].max[1], Node[Tri[i].v[1]].p[1]);
317 Tri[i].max[1] = max(Tri[i].max[1], Node[Tri[i].v[2]].p[1]);
318 Tri[i].max[2] = Node[Tri[i].v[0]].p[2];
319 Tri[i].max[2] = max(Tri[i].max[2], Node[Tri[i].v[1]].p[2]);
320 Tri[i].max[2] = max(Tri[i].max[2], Node[Tri[i].v[2]].p[2]);
323 ghCursorCurrent = ghCursorDefault;
324 SetCursor(ghCursorCurrent);
327 /* end MakeDecimatedMap */
329 /*****************************************************************************/
331 /* tricall Takes an array of nodes, spits out an array of triangles */
333 /*****************************************************************************/
334 int tricall(int NumNodes, NODE *Node, int *NumTris, TRI **inTri, TRI **Tri, const char *Options)
336 struct triangulateio in, out;
342 /* Define input points. */
344 for (i = 0, NumUsedNodes = 0; i < NumNodes; i++) {
350 memset(&in, 0, sizeof(in));
351 memset(&out, 0, sizeof(out));
353 NodeTable = (int *) malloc(NumUsedNodes * sizeof(int));
355 in.numberofpoints = NumUsedNodes;
356 in.numberofpointattributes = 0;
357 in.pointlist = (REAL *) malloc(in.numberofpoints * 2 * sizeof(REAL));
358 for (i = 0, N = 0; i < NumNodes; i++) {
363 in.pointlist[N * 2] = Node[i].p[0];
364 in.pointlist[N * 2 + 1] = Node[i].p[2];
368 in.pointlist[N * 2] = Node[i].p[1];
369 in.pointlist[N * 2 + 1] = Node[i].p[2];
372 in.pointlist[N * 2] = Node[i].p[0];
373 in.pointlist[N * 2 + 1] = Node[i].p[1];
379 in.pointattributelist = (REAL *) NULL;
380 in.pointmarkerlist = (int *) NULL;
382 if (strstr(Options, "r")) {
384 TriTable = (int *) malloc(NumNodes * sizeof(int));
385 for (i = 0, N = 0; i < NumNodes; i++) {
391 in.numberoftriangles = NumTris[0];
392 in.numberofcorners = 3;
393 in.numberoftriangleattributes = 0;
394 in.trianglelist = (int *) malloc(in.numberofcorners * in.numberoftriangles * sizeof(int));
395 in.triangleattributelist = (REAL *) NULL;
396 in.trianglearealist = (REAL *) NULL;
398 for (i = 0; i < in.numberoftriangles; i++) {
399 in.trianglelist[i * in.numberofcorners] = TriTable[ptri[i].v[0]];
400 in.trianglelist[i * in.numberofcorners + 1] = TriTable[ptri[i].v[1]];
401 in.trianglelist[i * in.numberofcorners + 2] = TriTable[ptri[i].v[2]];
405 in.numberoftriangles = 0;
406 in.numberofcorners = 3;
407 in.numberoftriangleattributes = 0;
408 in.trianglelist = (int *) NULL;
409 in.triangleattributelist = (REAL *) NULL;
410 in.trianglearealist = (REAL *) NULL;
413 in.numberofsegments = 0;
414 in.segmentlist = (int *) NULL;
415 in.segmentmarkerlist = (int *) NULL;
417 in.numberofholes = 0;
418 in.holelist = (REAL *) NULL;
420 in.numberofregions = 0;
421 in.regionlist = (REAL *) NULL;
423 in.numberofedges = 0;
424 in.edgelist = (int *) NULL;
425 in.edgemarkerlist = (int *) NULL;
426 in.normlist = (REAL *) NULL;
428 /* Make necessary initializations */
429 out.pointlist = (REAL *) NULL; /* Not needed if -N switch used. */
430 out.pointattributelist = (REAL *) NULL; /* Not needed if -N switch used or
431 number of point attributes is zero: */
432 out.pointmarkerlist = (int *) NULL; /* Not needed if -N or -B switch used. */
433 out.trianglelist = (int *) NULL; /* Not needed if -E switch used. */
434 out.triangleattributelist = (REAL *) NULL; /* Not needed if -E switch used or
435 number of triangle attributes is
437 out.trianglearealist = (REAL *) NULL;
438 out.neighborlist = (int *) NULL; /* Needed only if -n switch used. */
439 out.segmentlist = (int *) NULL; /* Needed only if segments are output
440 (-p or -c) and -P not used: */
441 out.segmentmarkerlist = (int *) NULL; /* Needed only if segments are output
442 (-p or -c) and -P and -B not used: */
443 out.edgelist = (int *) NULL; /* Needed only if -e switch used. */
444 out.edgemarkerlist = (int *) NULL; /* Needed if -e used and -B not used. */
446 triangulate(Options, &in, &out, NULL);
448 NumTris[0] = out.numberoftriangles;
449 *Tri = (TRI *) malloc(NumTris[0] * sizeof(TRI));
452 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. */
465 if (in.pointattributelist) {
466 free(in.pointattributelist);
468 if (in.pointmarkerlist) {
469 free(in.pointmarkerlist);
471 if (in.trianglelist) {
472 free(in.trianglelist);
474 if (in.triangleattributelist) {
475 free(in.triangleattributelist);
477 if (in.trianglearealist) {
478 free(in.trianglearealist);
480 if (in.neighborlist) {
481 free(in.neighborlist);
483 if (in.segmentlist) {
484 free(in.segmentlist);
486 if (in.segmentmarkerlist) {
487 free(in.segmentmarkerlist);
498 if (in.edgemarkerlist) {
499 free(in.edgemarkerlist);
507 if (out.pointattributelist) {
508 free(out.pointattributelist);
510 if (out.pointmarkerlist) {
511 free(out.pointmarkerlist);
513 if (out.trianglelist) {
514 free(out.trianglelist);
516 if (out.triangleattributelist) {
517 free(out.triangleattributelist);
519 if (out.trianglearealist) {
520 free(out.trianglearealist);
522 if (out.neighborlist) {
523 free(out.neighborlist);
525 if (out.segmentlist) {
526 free(out.segmentlist);
528 if (out.segmentmarkerlist) {
529 free(out.segmentmarkerlist);
534 if (out.regionlist) {
535 free(out.regionlist);
540 if (out.edgemarkerlist) {
541 free(out.edgemarkerlist);
551 void EdgeOnSide(int *v, int *edge, int *border)
559 if ((v[0] <= NV) && (v[1] <= NV)) {
563 if ((v[1] <= NV) && (v[2] <= NV)) {
567 if ((v[2] <= NV) && (v[0] <= NV)) {
574 if ((v[0] >= R) && (v[1] >= R)) {
578 if ((v[1] >= R) && (v[2] >= R)) {
582 if ((v[2] >= R) && (v[0] >= R)) {
587 if (border[0] >= 0) {
590 N = Absolute(v[k0] - v[k1]);
591 Ndv = (float) (N * dv);
593 if (((v[0] % NVP1) == 0) && ((v[1] % NVP1) == 0)) {
594 if (border[0] >= 0) {
595 if (Ndv > (Absolute(v[0] - v[1]) * dh)) {
603 if (((v[1] % NVP1) == 0) && ((v[2] % NVP1) == 0)) {
604 if (border[0] >= 0) {
605 if (Ndv > (Absolute(v[1] - v[2]) * dh)) {
613 if (((v[2] % NVP1) == 0) && ((v[0] % NVP1) == 0)) {
614 if (border[0] >= 0) {
615 if (Ndv > (Absolute(v[2] - v[0]) * dh)) {
624 if (((v[0] % NVP1) == NV) && ((v[1] % NVP1) == NV)) {
625 if (border[0] >= 0) {
626 if (Ndv > (Absolute(v[0] - v[1]) * dh)) {
634 if (((v[1] % NVP1) == NV) && ((v[2] % NVP1) == NV)) {
635 if (border[0] >= 0) {
636 if (Ndv > (Absolute(v[1] - v[2]) * dh)) {
644 if (((v[2] % NVP1) == NV) && ((v[0] % NVP1) == NV)) {
645 if (border[0] >= 0) {
646 if (Ndv > (Absolute(v[2] - v[0]) * dh)) {
657 void CalcAngles(NODE *node, int *v, float *angle)
661 vec x0, x1, x2, y0, y1, y2;
680 x0 = node[v[0]].p[i];
681 x1 = node[v[1]].p[i];
682 x2 = node[v[2]].p[i];
683 y0 = node[v[0]].p[j];
684 y1 = node[v[1]].p[j];
685 y2 = node[v[2]].p[j];
694 for (k = 0; k < 3; k++) {
695 l = (vec) (sqrt(vv[k][0] * vv[k][0] + vv[k][1] * vv[k][1]));
702 dot = -(vv[0][0] * vv[2][0] + vv[0][1] * vv[2][1]);
703 angle[0] = (float) (acos(dot));
704 dot = -(vv[1][0] * vv[0][0] + vv[1][1] * vv[0][1]);
705 angle[1] = (float) (acos(dot));
706 dot = -(vv[2][0] * vv[1][0] + vv[2][1] * vv[1][1]);
707 angle[2] = (float) (acos(dot));
710 //=================================================================
711 int Bisect(NODE *node, int border, int j0, int j1)
723 k = (int) ((j0 + j1) / (2 * NVP1)) * NVP1;
726 k = (int) ((j0 + j1 + 2) / (2 * NVP1)) * NVP1 - 1;
729 return (((k != j0) && (k != j1)) ? k : 0);
732 //=================================================================
733 int compare(TRITABLE *t1, TRITABLE *t2)
735 if (t1->error > t2->error) {
738 if (t1->error < t2->error) {
744 void MakeBrushes(int NumTris, NODE *Node, TRI *Tri, bool surf,
745 int offset, char *texture0, char *texture1, char *texture2)
747 extern double backface;
752 vec3_t PlaneNormal, SurfNormal;
756 // if texture2 is identical to texture0, there's no need to
757 // check surface angle
758 if (!g_strcasecmp(texture0, texture2) || !strlen(texture2)) {
762 Steep = (float) cos((double) SlantAngle / 57.2957795);
772 PlaneNormal[2] = -1.;
781 PlaneNormal[1] = -1.;
790 PlaneNormal[0] = -1.;
800 contents += CONTENTS_DETAIL;
803 contents += CONTENTS_LADDER;
808 for (i = 0; i < NumTris; i++) {
812 brush.face[0].v[0][0] = Node[Tri[i].v[0]].p[0];
813 brush.face[0].v[0][1] = Node[Tri[i].v[0]].p[1];
814 brush.face[0].v[0][2] = Node[Tri[i].v[0]].p[2];
816 brush.face[0].v[1][0] = Node[Tri[i].v[2]].p[0];
817 brush.face[0].v[1][1] = Node[Tri[i].v[2]].p[1];
818 brush.face[0].v[1][2] = Node[Tri[i].v[2]].p[2];
820 brush.face[0].v[2][0] = Node[Tri[i].v[1]].p[0];
821 brush.face[0].v[2][1] = Node[Tri[i].v[1]].p[1];
822 brush.face[0].v[2][2] = Node[Tri[i].v[1]].p[2];
827 brush.face[0].v[0][2] += offset;
828 brush.face[0].v[1][2] += offset;
829 brush.face[0].v[1][2] += offset;
832 brush.face[0].v[0][2] -= offset;
833 brush.face[0].v[1][2] -= offset;
834 brush.face[0].v[1][2] -= offset;
837 brush.face[0].v[0][1] += offset;
838 brush.face[0].v[1][1] += offset;
839 brush.face[0].v[1][1] += offset;
842 brush.face[0].v[0][1] -= offset;
843 brush.face[0].v[1][1] -= offset;
844 brush.face[0].v[1][1] -= offset;
847 brush.face[0].v[0][0] += offset;
848 brush.face[0].v[1][0] += offset;
849 brush.face[0].v[1][0] += offset;
852 brush.face[0].v[0][0] -= offset;
853 brush.face[0].v[1][0] -= offset;
854 brush.face[0].v[1][0] -= offset;
862 brush.face[1].v[0][0] = Node[Tri[i].v[0]].p[0];
863 brush.face[1].v[0][1] = (float) backface;
864 brush.face[1].v[0][2] = Node[Tri[i].v[0]].p[2];
866 brush.face[1].v[1][0] = Node[Tri[i].v[1]].p[0];
867 brush.face[1].v[1][1] = (float) backface;
868 brush.face[1].v[1][2] = Node[Tri[i].v[1]].p[2];
870 brush.face[1].v[2][0] = Node[Tri[i].v[2]].p[0];
871 brush.face[1].v[2][1] = (float) backface;
872 brush.face[1].v[2][2] = Node[Tri[i].v[2]].p[2];
875 brush.face[2].v[0][0] = Node[Tri[i].v[0]].p[0];
876 brush.face[2].v[0][1] = Node[Tri[i].v[0]].p[1];
877 brush.face[2].v[0][2] = Node[Tri[i].v[0]].p[2];
879 brush.face[2].v[1][0] = Node[Tri[i].v[1]].p[0];
880 brush.face[2].v[1][1] = Node[Tri[i].v[1]].p[1];
881 brush.face[2].v[1][2] = Node[Tri[i].v[1]].p[2];
883 brush.face[2].v[2][0] = Node[Tri[i].v[1]].p[0];
884 brush.face[2].v[2][1] = (float) backface;
885 brush.face[2].v[2][2] = Node[Tri[i].v[1]].p[2];
888 brush.face[3].v[0][0] = Node[Tri[i].v[1]].p[0];
889 brush.face[3].v[0][1] = Node[Tri[i].v[1]].p[1];
890 brush.face[3].v[0][2] = Node[Tri[i].v[1]].p[2];
892 brush.face[3].v[1][0] = Node[Tri[i].v[2]].p[0];
893 brush.face[3].v[1][1] = Node[Tri[i].v[2]].p[1];
894 brush.face[3].v[1][2] = Node[Tri[i].v[2]].p[2];
896 brush.face[3].v[2][0] = Node[Tri[i].v[2]].p[0];
897 brush.face[3].v[2][1] = (float) backface;
898 brush.face[3].v[2][2] = Node[Tri[i].v[2]].p[2];
901 brush.face[4].v[0][0] = Node[Tri[i].v[2]].p[0];
902 brush.face[4].v[0][1] = Node[Tri[i].v[2]].p[1];
903 brush.face[4].v[0][2] = Node[Tri[i].v[2]].p[2];
905 brush.face[4].v[1][0] = Node[Tri[i].v[0]].p[0];
906 brush.face[4].v[1][1] = Node[Tri[i].v[0]].p[1];
907 brush.face[4].v[1][2] = Node[Tri[i].v[0]].p[2];
909 brush.face[4].v[2][0] = Node[Tri[i].v[0]].p[0];
910 brush.face[4].v[2][1] = (float) backface;
911 brush.face[4].v[2][2] = Node[Tri[i].v[0]].p[2];
916 brush.face[1].v[0][0] = (float) backface;
917 brush.face[1].v[0][1] = Node[Tri[i].v[0]].p[1];
918 brush.face[1].v[0][2] = Node[Tri[i].v[0]].p[2];
920 brush.face[1].v[1][0] = (float) backface;
921 brush.face[1].v[1][1] = Node[Tri[i].v[1]].p[1];
922 brush.face[1].v[1][2] = Node[Tri[i].v[1]].p[2];
924 brush.face[1].v[2][0] = (float) backface;
925 brush.face[1].v[2][1] = Node[Tri[i].v[2]].p[1];
926 brush.face[1].v[2][2] = Node[Tri[i].v[2]].p[2];
929 brush.face[2].v[0][0] = Node[Tri[i].v[0]].p[0];
930 brush.face[2].v[0][1] = Node[Tri[i].v[0]].p[1];
931 brush.face[2].v[0][2] = Node[Tri[i].v[0]].p[2];
933 brush.face[2].v[1][0] = Node[Tri[i].v[1]].p[0];
934 brush.face[2].v[1][1] = Node[Tri[i].v[1]].p[1];
935 brush.face[2].v[1][2] = Node[Tri[i].v[1]].p[2];
937 brush.face[2].v[2][0] = (float) backface;
938 brush.face[2].v[2][1] = Node[Tri[i].v[1]].p[1];
939 brush.face[2].v[2][2] = Node[Tri[i].v[1]].p[2];
942 brush.face[3].v[0][0] = Node[Tri[i].v[1]].p[0];
943 brush.face[3].v[0][1] = Node[Tri[i].v[1]].p[1];
944 brush.face[3].v[0][2] = Node[Tri[i].v[1]].p[2];
946 brush.face[3].v[1][0] = Node[Tri[i].v[2]].p[0];
947 brush.face[3].v[1][1] = Node[Tri[i].v[2]].p[1];
948 brush.face[3].v[1][2] = Node[Tri[i].v[2]].p[2];
950 brush.face[3].v[2][0] = (float) backface;
951 brush.face[3].v[2][1] = Node[Tri[i].v[2]].p[1];
952 brush.face[3].v[2][2] = Node[Tri[i].v[2]].p[2];
955 brush.face[4].v[0][0] = Node[Tri[i].v[2]].p[0];
956 brush.face[4].v[0][1] = Node[Tri[i].v[2]].p[1];
957 brush.face[4].v[0][2] = Node[Tri[i].v[2]].p[2];
959 brush.face[4].v[1][0] = Node[Tri[i].v[0]].p[0];
960 brush.face[4].v[1][1] = Node[Tri[i].v[0]].p[1];
961 brush.face[4].v[1][2] = Node[Tri[i].v[0]].p[2];
963 brush.face[4].v[2][0] = (float) backface;
964 brush.face[4].v[2][1] = Node[Tri[i].v[0]].p[1];
965 brush.face[4].v[2][2] = Node[Tri[i].v[0]].p[2];
969 brush.face[1].v[0][0] = Node[Tri[i].v[0]].p[0];
970 brush.face[1].v[0][1] = Node[Tri[i].v[0]].p[1];
971 brush.face[1].v[0][2] = (float) backface;
973 brush.face[1].v[1][0] = Node[Tri[i].v[1]].p[0];
974 brush.face[1].v[1][1] = Node[Tri[i].v[1]].p[1];
975 brush.face[1].v[1][2] = (float) backface;
977 brush.face[1].v[2][0] = Node[Tri[i].v[2]].p[0];
978 brush.face[1].v[2][1] = Node[Tri[i].v[2]].p[1];
979 brush.face[1].v[2][2] = (float) backface;
982 brush.face[2].v[0][0] = Node[Tri[i].v[0]].p[0];
983 brush.face[2].v[0][1] = Node[Tri[i].v[0]].p[1];
984 brush.face[2].v[0][2] = Node[Tri[i].v[0]].p[2];
986 brush.face[2].v[1][0] = Node[Tri[i].v[1]].p[0];
987 brush.face[2].v[1][1] = Node[Tri[i].v[1]].p[1];
988 brush.face[2].v[1][2] = Node[Tri[i].v[1]].p[2];
990 brush.face[2].v[2][0] = Node[Tri[i].v[1]].p[0];
991 brush.face[2].v[2][1] = Node[Tri[i].v[1]].p[1];
992 brush.face[2].v[2][2] = (float) backface;
995 brush.face[3].v[0][0] = Node[Tri[i].v[1]].p[0];
996 brush.face[3].v[0][1] = Node[Tri[i].v[1]].p[1];
997 brush.face[3].v[0][2] = Node[Tri[i].v[1]].p[2];
999 brush.face[3].v[1][0] = Node[Tri[i].v[2]].p[0];
1000 brush.face[3].v[1][1] = Node[Tri[i].v[2]].p[1];
1001 brush.face[3].v[1][2] = Node[Tri[i].v[2]].p[2];
1003 brush.face[3].v[2][0] = Node[Tri[i].v[2]].p[0];
1004 brush.face[3].v[2][1] = Node[Tri[i].v[2]].p[1];
1005 brush.face[3].v[2][2] = (float) backface;
1008 brush.face[4].v[0][0] = Node[Tri[i].v[2]].p[0];
1009 brush.face[4].v[0][1] = Node[Tri[i].v[2]].p[1];
1010 brush.face[4].v[0][2] = Node[Tri[i].v[2]].p[2];
1012 brush.face[4].v[1][0] = Node[Tri[i].v[0]].p[0];
1013 brush.face[4].v[1][1] = Node[Tri[i].v[0]].p[1];
1014 brush.face[4].v[1][2] = Node[Tri[i].v[0]].p[2];
1016 brush.face[4].v[2][0] = Node[Tri[i].v[0]].p[0];
1017 brush.face[4].v[2][1] = Node[Tri[i].v[0]].p[1];
1018 brush.face[4].v[2][2] = (float) backface;
1021 for (j = 0; j < 5; j++) {
1022 strcpy(brush.face[j].texture,
1023 (strlen(texture1) ? texture1 : texture0));
1024 brush.face[j].Shift[0] = (float) TexOffset[0];
1025 brush.face[j].Shift[1] = (float) TexOffset[1];
1026 brush.face[j].Rotate = 0.;
1027 brush.face[j].Scale[0] = (float) TexScale[0];
1028 brush.face[j].Scale[1] = (float) TexScale[1];
1029 brush.face[j].Contents = contents;
1031 brush.face[j].Surface = 0;
1033 brush.face[j].Surface = SURF_HINT;
1035 brush.face[j].Value = 0;
1039 XYZVectorSubtract(brush.face[0].v[2], brush.face[0].v[0], t[0]);
1040 XYZVectorSubtract(brush.face[0].v[1], brush.face[0].v[2], t[1]);
1041 CrossProduct(t[0], t[1], SurfNormal);
1042 VectorNormalize(SurfNormal, SurfNormal);
1043 if (DotProduct(SurfNormal, PlaneNormal) < Steep) {
1044 strcpy(brush.face[0].texture, texture2);
1046 strcpy(brush.face[0].texture, texture0);
1049 strcpy(brush.face[0].texture, texture0);
1053 brush.face[0].Value = ArghRad2;
1059 } // end MakeBrushes
1060 //=================================================================
1061 void MapOut(int NumNodes, int NumTris, NODE *Node, TRI *Tri)
1063 extern double backface;
1064 extern double xmin, xmax, ymin, ymax, zmin, zmax;
1066 char hint[32], skip[32];
1070 ghCursorCurrent = LoadCursor(NULL,IDC_WAIT);
1071 SetCursor(ghCursorCurrent);
1073 UseDetail = 1; // this is temporary
1074 MakeBrushes(NumTris, Node, Tri, TRUE, 0, Texture[Game][0], Texture[Game][1], Texture[Game][2]);
1076 if (AddHints || GimpHints) {
1079 strcpy(hint, "generic/misc/hint");
1080 strcpy(skip, "generic/misc/skip");
1083 strcpy(hint, "HINT");
1084 strcpy(skip, "HINT");
1087 strcpy(hint, "general/hint");
1088 strcpy(skip, "general/skip");
1091 strcpy(hint, "common/0_hint");
1092 strcpy(skip, "common/0_skip");
1095 strcpy(hint, "common/hint");
1096 strcpy(skip, "common/skip");
1099 strcpy(hint, "e1u1/hint");
1100 strcpy(skip, "e1u1/skip");
1105 MakeBrushes(NumTris, Node, Tri, FALSE, HINT_OFFSET, hint, hint, hint);
1108 if (AddHints == 1) {
1109 int j0, j1, j2, k, k0, k1;
1111 int w, h, h0, h1, t, OK;
1114 int MaxHints; // We don't want a whole slew of hint brushes, which we'd get
1115 // with low decimation values and our current placement scheme.
1116 // Limit number of hint brushes to number of undecimated grid
1121 front = LessThan(zmin, 32.);
1124 front = MoreThan(ymax, 32.);
1127 front = LessThan(ymin, 32.);
1130 front = MoreThan(xmax, 32.);
1133 front = LessThan(xmin, 32.);
1136 front = MoreThan(zmax, 32.);
1139 for (i = 0; i < NumTris; i++) {
1164 MaxHints = NH * NV - 1;
1165 for (w = 1; w < min(16, NH) && brush.Number < MaxHints; w++) {
1166 for (h = max(1, w / 2); h < min(16, NV) && brush.Number < MaxHints; h++) {
1167 for (i = 0; i <= NH - w && brush.Number < MaxHints; i++) {
1168 for (j = 0; j <= NV - h && brush.Number < MaxHints; j++) {
1169 q[0] = i * NVP1 + j;
1170 q[2] = q[0] + w * NVP1 + h;
1182 for (k = 0, OK = 1; k < NumTris && OK; k++) {
1183 if (Tri[k].min[j1] >= max(Node[q[0]].p[j1], Node[q[2]].p[j1])) {
1186 if (Tri[k].min[j2] >= max(Node[q[0]].p[j2], Node[q[2]].p[j2])) {
1189 if (Tri[k].max[j1] <= min(Node[q[0]].p[j1], Node[q[2]].p[j1])) {
1192 if (Tri[k].max[j2] <= min(Node[q[0]].p[j2], Node[q[2]].p[j2])) {
1196 for (h0 = 0; h0 < 4 && OK; h0++) {
1198 for (t = 0; t < 3 && OK; t++) {
1199 s[t] = side(Node[q[h0]].p[j1], Node[q[h0]].p[j2],
1200 Node[q[h1]].p[j1], Node[q[h1]].p[j2],
1201 Node[Tri[k].v[t]].p[j1], Node[Tri[k].v[t]].p[j2]);
1203 if ((s[1] > 0 || s[2] > 0) && s[0] < 0) {
1206 if ((s[2] > 0 || s[0] > 0) && s[1] < 0) {
1209 if ((s[0] > 0 || s[1] > 0) && s[2] < 0) {
1221 brush.face[0].v[0][0] = Node[q[2]].p[0];
1222 brush.face[0].v[0][1] = (float) front;
1223 brush.face[0].v[0][2] = Node[q[2]].p[2];
1225 brush.face[0].v[1][0] = Node[q[1]].p[0];
1226 brush.face[0].v[1][1] = (float) front;
1227 brush.face[0].v[1][2] = Node[q[1]].p[2];
1229 brush.face[0].v[2][0] = Node[q[0]].p[0];
1230 brush.face[0].v[2][1] = (float) front;
1231 brush.face[0].v[2][2] = Node[q[0]].p[2];
1234 brush.face[1].v[0][0] = Node[q[0]].p[0];
1235 brush.face[1].v[0][1] = (float) backface;
1236 brush.face[1].v[0][2] = Node[q[0]].p[2];
1238 brush.face[1].v[1][0] = Node[q[1]].p[0];
1239 brush.face[1].v[1][1] = (float) backface;
1240 brush.face[1].v[1][2] = Node[q[1]].p[2];
1242 brush.face[1].v[2][0] = Node[q[2]].p[0];
1243 brush.face[1].v[2][1] = (float) backface;
1244 brush.face[1].v[2][2] = Node[q[2]].p[2];
1246 for (k0 = 0; k0 < brush.NumFaces - 2; k0++) {
1248 k1 = (k0 + 1) % (brush.NumFaces - 2);
1250 brush.face[k].v[0][0] = Node[q[k0]].p[0];
1251 brush.face[k].v[0][1] = (float) front;
1252 brush.face[k].v[0][2] = Node[q[k0]].p[2];
1254 brush.face[k].v[1][0] = Node[q[k1]].p[0];
1255 brush.face[k].v[1][1] = (float) front;
1256 brush.face[k].v[1][2] = Node[q[k1]].p[2];
1258 brush.face[k].v[2][0] = Node[q[k1]].p[0];
1259 brush.face[k].v[2][1] = (float) backface;
1260 brush.face[k].v[2][2] = Node[q[k1]].p[2];
1266 brush.face[0].v[0][0] = (float) front;
1267 brush.face[0].v[0][1] = Node[q[2]].p[1];
1268 brush.face[0].v[0][2] = Node[q[2]].p[2];
1270 brush.face[0].v[1][0] = (float) front;
1271 brush.face[0].v[1][1] = Node[q[1]].p[1];
1272 brush.face[0].v[1][2] = Node[q[1]].p[2];
1274 brush.face[0].v[2][0] = (float) front;
1275 brush.face[0].v[2][1] = Node[q[0]].p[1];
1276 brush.face[0].v[2][2] = Node[q[0]].p[2];
1279 brush.face[1].v[0][0] = (float) backface;
1280 brush.face[1].v[0][1] = Node[q[0]].p[1];
1281 brush.face[1].v[0][2] = Node[q[0]].p[2];
1283 brush.face[1].v[1][0] = (float) backface;
1284 brush.face[1].v[1][1] = Node[q[1]].p[1];
1285 brush.face[1].v[1][2] = Node[q[1]].p[2];
1287 brush.face[1].v[2][0] = (float) backface;
1288 brush.face[1].v[2][1] = Node[q[2]].p[1];
1289 brush.face[1].v[2][2] = Node[q[2]].p[2];
1291 for (k0 = 0; k0 < brush.NumFaces - 2; k0++) {
1293 k1 = (k0 + 1) % (brush.NumFaces - 2);
1295 brush.face[k].v[0][0] = (float) front;
1296 brush.face[k].v[0][1] = Node[q[k0]].p[1];
1297 brush.face[k].v[0][2] = Node[q[k0]].p[2];
1299 brush.face[k].v[1][0] = (float) front;
1300 brush.face[k].v[1][1] = Node[q[k1]].p[1];
1301 brush.face[k].v[1][2] = Node[q[k1]].p[2];
1303 brush.face[k].v[2][0] = (float) backface;
1304 brush.face[k].v[2][1] = Node[q[k1]].p[1];
1305 brush.face[k].v[2][2] = Node[q[k1]].p[2];
1310 brush.face[0].v[0][0] = Node[q[2]].p[0];
1311 brush.face[0].v[0][1] = Node[q[2]].p[1];
1312 brush.face[0].v[0][2] = (float) front;
1314 brush.face[0].v[1][0] = Node[q[1]].p[0];
1315 brush.face[0].v[1][1] = Node[q[1]].p[1];
1316 brush.face[0].v[1][2] = (float) front;
1318 brush.face[0].v[2][0] = Node[q[0]].p[0];
1319 brush.face[0].v[2][1] = Node[q[0]].p[1];
1320 brush.face[0].v[2][2] = (float) front;
1323 brush.face[1].v[0][0] = Node[q[0]].p[0];
1324 brush.face[1].v[0][1] = Node[q[0]].p[1];
1325 brush.face[1].v[0][2] = (float) backface;
1327 brush.face[1].v[1][0] = Node[q[1]].p[0];
1328 brush.face[1].v[1][1] = Node[q[1]].p[1];
1329 brush.face[1].v[1][2] = (float) backface;
1331 brush.face[1].v[2][0] = Node[q[2]].p[0];
1332 brush.face[1].v[2][1] = Node[q[2]].p[1];
1333 brush.face[1].v[2][2] = (float) backface;
1335 for (k0 = 0; k0 < brush.NumFaces - 2; k0++) {
1337 k1 = (k0 + 1) % (brush.NumFaces - 2);
1339 brush.face[k].v[0][0] = Node[q[k0]].p[0];
1340 brush.face[k].v[0][1] = Node[q[k0]].p[1];
1341 brush.face[k].v[0][2] = (float) front;
1343 brush.face[k].v[1][0] = Node[q[k1]].p[0];
1344 brush.face[k].v[1][1] = Node[q[k1]].p[1];
1345 brush.face[k].v[1][2] = (float) front;
1347 brush.face[k].v[2][0] = Node[q[k1]].p[0];
1348 brush.face[k].v[2][1] = Node[q[k1]].p[1];
1349 brush.face[k].v[2][2] = (float) backface;
1353 for (face = 0; face < 6; face++) {
1354 strcpy(brush.face[face].texture, (face <= 1 ? skip : hint));
1355 brush.face[face].Shift[0] = 0;
1356 brush.face[face].Shift[1] = 0;
1357 brush.face[face].Rotate = 0.;
1358 brush.face[face].Scale[0] = 1;
1359 brush.face[face].Scale[1] = 1;
1360 brush.face[face].Contents = CONTENTS_DETAIL;
1361 brush.face[face].Surface = (face <= 1 ? SURF_SKIP : SURF_HINT);
1362 brush.face[face].Value = 0;
1364 if (!brush.Number) {
1378 ghCursorCurrent = ghCursorDefault;
1379 SetCursor(ghCursorCurrent);
1383 //===========================================================================
1384 int CheckBorders(int *NumNodesUsed, int NumNodes, NODE *Node, int *NumTris, TRI **pTri)
1387 int i, j, k0, k1, N;
1391 N = NumNodesUsed[0];
1393 for (i = 0; i < NumTris[0]; i++) {
1394 EdgeOnSide(Tri[i].v, &k0, &border);
1398 CalcAngles(Node, Tri[i].v, angle);
1400 if ((angle[k0] < SLIVER_ANGLE) || (angle[k1] < SLIVER_ANGLE)) {
1401 j = Bisect(Node, border, Tri[i].v[k0], Tri[i].v[k1]);
1403 if (!Node[j].used) { // Shouldn't be used, but...
1410 if (NumNodesUsed[0] > N) {
1412 tricall(NumNodes, Node, NumTris, NULL, pTri, "cnzBNPY");
1415 return (NumNodesUsed[0] - N);