X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=contrib%2Fgtkgensurf%2Fdec.cpp;h=e080f266abd1a2e394a4c0a37d87c2dd67da2fdc;hb=9dfae1c9b270ee369c6362903a9205b30751b95f;hp=cc9083dedd54b21e05d205ee3776056b1b23e971;hpb=bfc8a12a6b315ae261101a34db8ba1b682c67bb7;p=xonotic%2Fnetradiant.git diff --git a/contrib/gtkgensurf/dec.cpp b/contrib/gtkgensurf/dec.cpp index cc9083de..e080f266 100644 --- a/contrib/gtkgensurf/dec.cpp +++ b/contrib/gtkgensurf/dec.cpp @@ -1,21 +1,21 @@ /* -GenSurf plugin for GtkRadiant -Copyright (C) 2001 David Hyde, Loki software and qeradiant.com + GenSurf plugin for GtkRadiant + Copyright (C) 2001 David Hyde, Loki software and qeradiant.com -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ #define SINGLE #ifdef SINGLE @@ -30,291 +30,299 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "gensurf.h" #include "triangle.h" -typedef struct -{ - float error; - int node; +typedef struct { + float error; + int node; } TRITABLE; double dh, dv; -int NVP1; +int NVP1; -#define Absolute(a) ((a) >= 0.0 ? (a) : -(a)) +#define Absolute(a) ( ( a ) >= 0.0 ? ( a ) : -( a ) ) void MakeDecimatedMap(int *NumNodes, int *NumTris, NODE **pNode, TRI **pTri) { - int compare(TRITABLE *, TRITABLE *); - int Bisect(NODE *, int, int, int); - void CalcAngles(NODE *, int *, float *); - void EdgeOnSide(int *, int *, int *); - int tricall(int, NODE *, int *, TRI **, TRI **, const char *); - int CheckBorders(int *,int,NODE *,int *,TRI **); - - float biggesterror; - int i, j, N; - int j0, j1, j2; - int NumNodesToSave; - int NumNodesUsed; - NODE *Node; - TRI *Tri; - TRITABLE *TriTable; - - if(Decimate <= 0) return; - /* - ghCursorCurrent = LoadCursor(NULL,IDC_WAIT); - SetCursor(ghCursorCurrent); - */ - dh = (Hur-Hll)/NH; - dv = (Vur-Vll)/NV; - NVP1 = NV+1; - - NumNodes[0] = (NH+1)*(NVP1); - *pNode = (NODE *) malloc(NumNodes[0] * sizeof(NODE)); - Node = *pNode; - memset(Node,0,NumNodes[0]*sizeof(NODE)); - - // Copy [NH][NV] vertex array to our working node array - for(i=0,N=0; i<=NH; i++) - { - for(j=0; j<=NV; j++, N++) - { - Node[N].p[0] = (float)xyz[i][j].p[0]; - Node[N].p[1] = (float)xyz[i][j].p[1]; - Node[N].p[2] = (float)xyz[i][j].p[2]; - Node[N].fixed = xyz[i][j].fixed; - } - } - // Start things off with the corner values - Node[ 0].used = 1; - Node[NV].used = 1; - Node[NH*NVP1].used = 1; - Node[NH*NVP1+NV].used = 1; - NumNodesUsed = 4; - tricall(NumNodes[0], Node, NumTris, NULL, pTri, "cnzBNPY"); - Tri = *pTri; - - // Which coordinates are we triangulating on? - switch(Plane) - { - case PLANE_XZ0: - case PLANE_XZ1: - j0 = 1; - j1 = 0; - j2 = 2; - break; - case PLANE_YZ0: - case PLANE_YZ1: - j0 = 0; - j1 = 1; - j2 = 2; - break; - default: - j0 = 2; - j1 = 0; - j2 = 1; - } - - // TriTable stores the largest error in a triangle and the node where that - // error occurs - TriTable = (TRITABLE *) malloc(NH*NV*2 * sizeof(TRITABLE)); - NumNodesToSave = min(NumNodes[0], (int)(0.01*(100-Decimate)*(NumNodes[0]-NumNodesUsed)+NumNodesUsed)); - - while(NumNodesUsed < NumNodesToSave) - { - for(i=0; i TriTable[Node[i].tri].error) - { - TriTable[Node[i].tri].error = (float)(Absolute(Node[i].error)); - TriTable[Node[i].tri].node = i; - } - } - qsort( (void *)TriTable, (size_t)(NumTris[0]), sizeof(TRITABLE), (int (*)(const void *, const void *))compare ); - for(i=0; i 0.5*biggesterror; i++) - { - if(Node[TriTable[i].node].used) continue; // shouldn't happen - NumNodesUsed++; - Node[TriTable[i].node].used++; - } - free(Tri); - tricall(NumNodes[0], Node, NumTris, NULL, pTri, "cnzBNPY"); - Tri = *pTri; - // Sliver-check along borders. Since borders are often linear, the errors - // along borders will often be zero, so no new points will be added. This - // tends to produce long, thin brushes. For all border triangles, check - // that minimum angle isn't less than SLIVER_ANGLE. If it is, add another - // vertex. - while(CheckBorders(&NumNodesUsed,NumNodes[0],Node,NumTris,pTri) > 0) - { - } - Tri = *pTri; - } - } - free(TriTable); - // One last time (because we're pessimistic), check border triangles + int compare(TRITABLE *, TRITABLE *); + int Bisect(NODE *, int, int, int); + void CalcAngles(NODE *, int *, float *); + void EdgeOnSide(int *, int *, int *); + int tricall(int, NODE *, int *, TRI **, TRI **, const char *); + int CheckBorders(int *, int, NODE *, int *, TRI **); + + float biggesterror; + int i, j, N; + int j0, j1, j2; + int NumNodesToSave; + int NumNodesUsed; + NODE *Node; + TRI *Tri; + TRITABLE *TriTable; + + if (Decimate <= 0) { + return; + } + /* + ghCursorCurrent = LoadCursor(NULL,IDC_WAIT); + SetCursor(ghCursorCurrent); + */ + dh = (Hur - Hll) / NH; + dv = (Vur - Vll) / NV; + NVP1 = NV + 1; + + NumNodes[0] = (NH + 1) * (NVP1); + *pNode = (NODE *) malloc(NumNodes[0] * sizeof(NODE)); + Node = *pNode; + memset(Node, 0, NumNodes[0] * sizeof(NODE)); + + // Copy [NH][NV] vertex array to our working node array + for (i = 0, N = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++, N++) { + Node[N].p[0] = (float) xyz[i][j].p[0]; + Node[N].p[1] = (float) xyz[i][j].p[1]; + Node[N].p[2] = (float) xyz[i][j].p[2]; + Node[N].fixed = xyz[i][j].fixed; + } + } + // Start things off with the corner values + Node[0].used = 1; + Node[NV].used = 1; + Node[NH * NVP1].used = 1; + Node[NH * NVP1 + NV].used = 1; + NumNodesUsed = 4; + tricall(NumNodes[0], Node, NumTris, NULL, pTri, "cnzBNPY"); + Tri = *pTri; + + // Which coordinates are we triangulating on? + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + j0 = 1; + j1 = 0; + j2 = 2; + break; + case PLANE_YZ0: + case PLANE_YZ1: + j0 = 0; + j1 = 1; + j2 = 2; + break; + default: + j0 = 2; + j1 = 0; + j2 = 1; + } + + // TriTable stores the largest error in a triangle and the node where that + // error occurs + TriTable = (TRITABLE *) malloc(NH * NV * 2 * sizeof(TRITABLE)); + NumNodesToSave = min(NumNodes[0], (int) (0.01 * (100 - Decimate) * (NumNodes[0] - NumNodesUsed) + NumNodesUsed)); + + while (NumNodesUsed < NumNodesToSave) { + for (i = 0; i < NumTris[0]; i++) { + Tri[i].flag = 0; + } + + // For every node that's not currently used, find what triangle it + // lies on, and the error at this node + for (i = 0, biggesterror = 0; i < NumNodes[0]; i++) { + if (Node[i].used) { + continue; + } + for (j = 0, Node[i].tri = -1; (j < NumTris[0]) && (Node[i].tri == -1); j++) { + if (side(Node[i].p[j1], Node[i].p[j2], + Node[Tri[j].v[0]].p[j1], Node[Tri[j].v[0]].p[j2], + Node[Tri[j].v[1]].p[j1], Node[Tri[j].v[1]].p[j2]) < 0.) { + continue; + } + if (side(Node[i].p[j1], Node[i].p[j2], + Node[Tri[j].v[1]].p[j1], Node[Tri[j].v[1]].p[j2], + Node[Tri[j].v[2]].p[j1], Node[Tri[j].v[2]].p[j2]) < 0.) { + continue; + } + if (side(Node[i].p[j1], Node[i].p[j2], + Node[Tri[j].v[2]].p[j1], Node[Tri[j].v[2]].p[j2], + Node[Tri[j].v[0]].p[j1], Node[Tri[j].v[0]].p[j2]) < 0.) { + continue; + } + Node[i].tri = j; + } + if (Node[i].tri < 0) { + /* + ghCursorCurrent = ghCursorDefault; + SetCursor(ghCursorCurrent); + */ + g_FuncTable.m_pfnMessageBox(g_pRadiantWnd, + "Error: Couldn't find the triangle bounding a point.", + "Decimation Error", eMB_OK, eMB_ICONWARNING); + return; + } + if (!Tri[Node[i].tri].flag) { + PlaneFromPoints(Node[Tri[Node[i].tri].v[0]].p, + Node[Tri[Node[i].tri].v[1]].p, + Node[Tri[Node[i].tri].v[2]].p, + &Tri[Node[i].tri].plane); + Tri[Node[i].tri].flag = 1; + } + Node[i].error = + Node[i].p[j0] - (Tri[Node[i].tri].plane.dist - + Tri[Node[i].tri].plane.normal[j1] * Node[i].p[j1] - + Tri[Node[i].tri].plane.normal[j2] * Node[i].p[j2]) / + Tri[Node[i].tri].plane.normal[j0]; + biggesterror = max(biggesterror, Absolute(Node[i].error)); + } + if (biggesterror == 0) { + NumNodesToSave = NumNodesUsed; + } else { + // For all current triangles, build a list of worst-case nodes + memset(TriTable, 0, NH * NV * 2 * sizeof(TRITABLE)); + for (i = 0; i < NumNodes[0]; i++) { + if (Node[i].used) { + continue; + } + if (Absolute(Node[i].error) > TriTable[Node[i].tri].error) { + TriTable[Node[i].tri].error = (float) (Absolute(Node[i].error)); + TriTable[Node[i].tri].node = i; + } + } + qsort((void *) TriTable, (size_t)(NumTris[0]), sizeof(TRITABLE), + (int (*)(const void *, const void *)) compare); + for (i = 0; + i < NumTris[0] && NumNodesUsed < NumNodesToSave && TriTable[i].error > 0.5 * biggesterror; i++) { + if (Node[TriTable[i].node].used) { + continue; // shouldn't happen + } + NumNodesUsed++; + Node[TriTable[i].node].used++; + } + free(Tri); + tricall(NumNodes[0], Node, NumTris, NULL, pTri, "cnzBNPY"); + Tri = *pTri; + // Sliver-check along borders. Since borders are often linear, the errors + // along borders will often be zero, so no new points will be added. This + // tends to produce long, thin brushes. For all border triangles, check + // that minimum angle isn't less than SLIVER_ANGLE. If it is, add another + // vertex. + while (CheckBorders(&NumNodesUsed, NumNodes[0], Node, NumTris, pTri) > 0) { + } + Tri = *pTri; + } + } + free(TriTable); + // One last time (because we're pessimistic), check border triangles // CheckBorders(&NumNodesUsed,NumNodes[0],Node,NumTris,pTri); // Tri = *pTri; - // Check that all fixed points are exact. If not, add them to the mix. - // First check to see if we have any fixed points that aren't already used. - for(i=0, N=0; i 0.5) - { - NumNodesUsed++; - Node[i].used++; - free(Tri); - tricall(NumNodes[0], Node, NumTris, NULL, pTri, "cnzBNPY"); - Tri = *pTri; - } - } - } - - // Swap node orders for surfaces facing down, north or west so that - // they are counterclockwise when facing the surface - - if((Plane == PLANE_XY1) || (Plane == PLANE_XZ0) || (Plane == PLANE_YZ1) ) - { - for(i=0; i 0.5) { + NumNodesUsed++; + Node[i].used++; + free(Tri); + tricall(NumNodes[0], Node, NumTris, NULL, pTri, "cnzBNPY"); + Tri = *pTri; + } + } + } + + // Swap node orders for surfaces facing down, north or west so that + // they are counterclockwise when facing the surface + + if ((Plane == PLANE_XY1) || (Plane == PLANE_XZ0) || (Plane == PLANE_YZ1)) { + for (i = 0; i < NumTris[0]; i++) { + j = Tri[i].v[1]; + Tri[i].v[1] = Tri[i].v[2]; + Tri[i].v[2] = j; + } + } + + // Store bounding box coords + for (i = 0; i < NumTris[0]; i++) { + Tri[i].min[0] = Node[Tri[i].v[0]].p[0]; + Tri[i].min[0] = min(Tri[i].min[0], Node[Tri[i].v[1]].p[0]); + Tri[i].min[0] = min(Tri[i].min[0], Node[Tri[i].v[2]].p[0]); + Tri[i].min[1] = Node[Tri[i].v[0]].p[1]; + Tri[i].min[1] = min(Tri[i].min[1], Node[Tri[i].v[1]].p[1]); + Tri[i].min[1] = min(Tri[i].min[1], Node[Tri[i].v[2]].p[1]); + Tri[i].min[2] = Node[Tri[i].v[0]].p[2]; + Tri[i].min[2] = min(Tri[i].min[2], Node[Tri[i].v[1]].p[2]); + Tri[i].min[2] = min(Tri[i].min[2], Node[Tri[i].v[2]].p[2]); + Tri[i].max[0] = Node[Tri[i].v[0]].p[0]; + Tri[i].max[0] = max(Tri[i].max[0], Node[Tri[i].v[1]].p[0]); + Tri[i].max[0] = max(Tri[i].max[0], Node[Tri[i].v[2]].p[0]); + Tri[i].max[1] = Node[Tri[i].v[0]].p[1]; + Tri[i].max[1] = max(Tri[i].max[1], Node[Tri[i].v[1]].p[1]); + Tri[i].max[1] = max(Tri[i].max[1], Node[Tri[i].v[2]].p[1]); + Tri[i].max[2] = Node[Tri[i].v[0]].p[2]; + Tri[i].max[2] = max(Tri[i].max[2], Node[Tri[i].v[1]].p[2]); + Tri[i].max[2] = max(Tri[i].max[2], Node[Tri[i].v[2]].p[2]); + } + /* + ghCursorCurrent = ghCursorDefault; + SetCursor(ghCursorCurrent); + */ } /* end MakeDecimatedMap */ @@ -325,1003 +333,1084 @@ void MakeDecimatedMap(int *NumNodes, int *NumTris, NODE **pNode, TRI **pTri) /*****************************************************************************/ int tricall(int NumNodes, NODE *Node, int *NumTris, TRI **inTri, TRI **Tri, const char *Options) { - struct triangulateio in, out; - int i, N; - int NumUsedNodes; - int *NodeTable; - TRI *ptri; - - /* Define input points. */ - - for(i=0,NumUsedNodes=0; i= R) && (v[1] >= R) ) - { - edge[0] = 0; - border[0] = 1; - } - if( (v[1] >= R) && (v[2] >= R) ) - { - edge[0] = 1; - border[0] = 1; - } - if( (v[2] >= R) && (v[0] >= R) ) - { - edge[0] = 2; - border[0] = 1; - } - - if(border[0] >= 0) - { - k0 = edge[0]; - k1 = (k0+1) % 3; - N = Absolute(v[k0] - v[k1]); - Ndv = (float)(N*dv); - } - if( ((v[0] % NVP1) == 0) && ((v[1] % NVP1) == 0) ) - { - if(border[0] >= 0) - if( Ndv > (Absolute(v[0] - v[1])*dh)) return; - edge[0] = 0; - border[0] = 2; - return; - } - if( ((v[1] % NVP1) == 0) && ((v[2] % NVP1) == 0) ) - { - if(border[0] >= 0) - if( Ndv > (Absolute(v[1] - v[2])*dh)) return; - edge[0] = 1; - border[0] = 2; - return; - } - if( ((v[2] % NVP1) == 0) && ((v[0] % NVP1) == 0) ) - { - if(border[0] >= 0) - if( Ndv > (Absolute(v[2] - v[0])*dh)) return; - edge[0] = 2; - border[0] = 2; - return; - } - - if( ((v[0] % NVP1) == NV) && ((v[1] % NVP1) == NV) ) - { - if(border[0] >= 0) - if( Ndv > (Absolute(v[0] - v[1])*dh)) return; - edge[0] = 0; - border[0] = 3; - return; - } - if( ((v[1] % NVP1) == NV) && ((v[2] % NVP1) == NV) ) - { - if(border[0] >= 0) - if( Ndv > (Absolute(v[1] - v[2])*dh)) return; - edge[0] = 1; - border[0] = 3; - return; - } - if( ((v[2] % NVP1) == NV) && ((v[0] % NVP1) == NV) ) - { - if(border[0] >= 0) - if( Ndv > (Absolute(v[2] - v[0])*dh)) return; - edge[0] = 2; - border[0] = 3; - return; - } - return; + int R; + int k0, k1, N; + float Ndv; + + border[0] = -1; + + if ((v[0] <= NV) && (v[1] <= NV)) { + edge[0] = 0; + border[0] = 0; + } + if ((v[1] <= NV) && (v[2] <= NV)) { + edge[0] = 1; + border[0] = 0; + } + if ((v[2] <= NV) && (v[0] <= NV)) { + edge[0] = 2; + border[0] = 0; + } + + R = NH * NVP1; + + if ((v[0] >= R) && (v[1] >= R)) { + edge[0] = 0; + border[0] = 1; + } + if ((v[1] >= R) && (v[2] >= R)) { + edge[0] = 1; + border[0] = 1; + } + if ((v[2] >= R) && (v[0] >= R)) { + edge[0] = 2; + border[0] = 1; + } + + if (border[0] >= 0) { + k0 = edge[0]; + k1 = (k0 + 1) % 3; + N = Absolute(v[k0] - v[k1]); + Ndv = (float) (N * dv); + } + if (((v[0] % NVP1) == 0) && ((v[1] % NVP1) == 0)) { + if (border[0] >= 0) { + if (Ndv > (Absolute(v[0] - v[1]) * dh)) { + return; + } + } + edge[0] = 0; + border[0] = 2; + return; + } + if (((v[1] % NVP1) == 0) && ((v[2] % NVP1) == 0)) { + if (border[0] >= 0) { + if (Ndv > (Absolute(v[1] - v[2]) * dh)) { + return; + } + } + edge[0] = 1; + border[0] = 2; + return; + } + if (((v[2] % NVP1) == 0) && ((v[0] % NVP1) == 0)) { + if (border[0] >= 0) { + if (Ndv > (Absolute(v[2] - v[0]) * dh)) { + return; + } + } + edge[0] = 2; + border[0] = 2; + return; + } + + if (((v[0] % NVP1) == NV) && ((v[1] % NVP1) == NV)) { + if (border[0] >= 0) { + if (Ndv > (Absolute(v[0] - v[1]) * dh)) { + return; + } + } + edge[0] = 0; + border[0] = 3; + return; + } + if (((v[1] % NVP1) == NV) && ((v[2] % NVP1) == NV)) { + if (border[0] >= 0) { + if (Ndv > (Absolute(v[1] - v[2]) * dh)) { + return; + } + } + edge[0] = 1; + border[0] = 3; + return; + } + if (((v[2] % NVP1) == NV) && ((v[0] % NVP1) == NV)) { + if (border[0] >= 0) { + if (Ndv > (Absolute(v[2] - v[0]) * dh)) { + return; + } + } + edge[0] = 2; + border[0] = 3; + return; + } + return; } void CalcAngles(NODE *node, int *v, float *angle) { - int i, j, k; - vec l; - vec x0, x1, x2, y0, y1, y2; - vec2 vv[3]; - vec dot; - - switch(Plane) - { - case PLANE_XZ0: - case PLANE_XZ1: - i = 0; - j = 2; - break; - case PLANE_YZ0: - case PLANE_YZ1: - i = 1; - j = 2; - break; - default: - i = 0; - j = 1; - } - x0 = node[v[0]].p[i]; - x1 = node[v[1]].p[i]; - x2 = node[v[2]].p[i]; - y0 = node[v[0]].p[j]; - y1 = node[v[1]].p[j]; - y2 = node[v[2]].p[j]; - - vv[0][0] = x1-x0; - vv[0][1] = y1-y0; - vv[1][0] = x2-x1; - vv[1][1] = y2-y1; - vv[2][0] = x0-x2; - vv[2][1] = y0-y2; - - for(k=0; k<3; k++) - { - l = (vec)(sqrt( vv[k][0]*vv[k][0] + vv[k][1]*vv[k][1] )); - if(l > 0.) - { - vv[k][0] /= l; - vv[k][1] /= l; - } - } - - dot = -(vv[0][0]*vv[2][0] + vv[0][1]*vv[2][1]); - angle[0] = (float)(acos(dot)); - dot = -(vv[1][0]*vv[0][0] + vv[1][1]*vv[0][1]); - angle[1] = (float)(acos(dot)); - dot = -(vv[2][0]*vv[1][0] + vv[2][1]*vv[1][1]); - angle[2] = (float)(acos(dot)); + int i, j, k; + vec l; + vec x0, x1, x2, y0, y1, y2; + vec2 vv[3]; + vec dot; + + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + i = 0; + j = 2; + break; + case PLANE_YZ0: + case PLANE_YZ1: + i = 1; + j = 2; + break; + default: + i = 0; + j = 1; + } + x0 = node[v[0]].p[i]; + x1 = node[v[1]].p[i]; + x2 = node[v[2]].p[i]; + y0 = node[v[0]].p[j]; + y1 = node[v[1]].p[j]; + y2 = node[v[2]].p[j]; + + vv[0][0] = x1 - x0; + vv[0][1] = y1 - y0; + vv[1][0] = x2 - x1; + vv[1][1] = y2 - y1; + vv[2][0] = x0 - x2; + vv[2][1] = y0 - y2; + + for (k = 0; k < 3; k++) { + l = (vec) (sqrt(vv[k][0] * vv[k][0] + vv[k][1] * vv[k][1])); + if (l > 0.) { + vv[k][0] /= l; + vv[k][1] /= l; + } + } + + dot = -(vv[0][0] * vv[2][0] + vv[0][1] * vv[2][1]); + angle[0] = (float) (acos(dot)); + dot = -(vv[1][0] * vv[0][0] + vv[1][1] * vv[0][1]); + angle[1] = (float) (acos(dot)); + dot = -(vv[2][0] * vv[1][0] + vv[2][1] * vv[1][1]); + angle[2] = (float) (acos(dot)); } + //================================================================= int Bisect(NODE *node, int border, int j0, int j1) { - int k; - - switch(border) - { - case 0: - k = (j0+j1)/2; - break; - case 1: - k = (j0+j1)/2; - break; - case 2: - k = (int)((j0+j1)/(2*NVP1)) * NVP1; - break; - case 3: - k = (int)((j0+j1+2)/(2*NVP1)) * NVP1 - 1; - break; - } - return( ((k != j0) && (k != j1)) ? k : 0 ); + int k; + + switch (border) { + case 0: + k = (j0 + j1) / 2; + break; + case 1: + k = (j0 + j1) / 2; + break; + case 2: + k = (int) ((j0 + j1) / (2 * NVP1)) * NVP1; + break; + case 3: + k = (int) ((j0 + j1 + 2) / (2 * NVP1)) * NVP1 - 1; + break; + } + return (((k != j0) && (k != j1)) ? k : 0); } + //================================================================= int compare(TRITABLE *t1, TRITABLE *t2) { - if(t1->error > t2->error) return -1; - if(t1->error < t2->error) return 1; - return 0; + if (t1->error > t2->error) { + return -1; + } + if (t1->error < t2->error) { + return 1; + } + return 0; } -void MakeBrushes(int NumTris, NODE *Node, TRI *Tri,bool surf, - int offset,char *texture0, char *texture1, char *texture2) +void MakeBrushes(int NumTris, NODE *Node, TRI *Tri, bool surf, + int offset, char *texture0, char *texture1, char *texture2) { - extern double backface; - BRUSH brush; - int contents; - int i, j; - float Steep; - vec3_t PlaneNormal,SurfNormal; - bool CheckAngle; - vec3_t t[2]; - - // if texture2 is identical to texture0, there's no need to - // check surface angle - if(!g_strcasecmp(texture0,texture2) || !strlen(texture2)) - CheckAngle = FALSE; - else - { - CheckAngle = TRUE; - Steep = (float)cos((double)SlantAngle/57.2957795); - switch(Plane) - { - case PLANE_XY0: PlaneNormal[0]= 0.;PlaneNormal[1]= 0.;PlaneNormal[2]= 1.;break; - case PLANE_XY1: PlaneNormal[0]= 0.;PlaneNormal[1]= 0.;PlaneNormal[2]=-1.;break; - case PLANE_XZ0: PlaneNormal[0]= 0.;PlaneNormal[1]= 1.;PlaneNormal[2]= 1.;break; - case PLANE_XZ1: PlaneNormal[0]= 0.;PlaneNormal[1]=-1.;PlaneNormal[2]= 1.;break; - case PLANE_YZ0: PlaneNormal[0]= 1.;PlaneNormal[1]= 0.;PlaneNormal[2]= 1.;break; - case PLANE_YZ1: PlaneNormal[0]=-1.;PlaneNormal[1]= 0.;PlaneNormal[2]= 1.;break; - } - } - - contents = 0; - if(surf) - { - if(UseDetail) contents += CONTENTS_DETAIL; - if(UseLadder) contents += CONTENTS_LADDER; - } - - OpenFuncGroup(); - for(i=0; i= max(Node[q[0]].p[j1],Node[q[2]].p[j1])) continue; - if(Tri[k].min[j2] >= max(Node[q[0]].p[j2],Node[q[2]].p[j2])) continue; - if(Tri[k].max[j1] <= min(Node[q[0]].p[j1],Node[q[2]].p[j1])) continue; - if(Tri[k].max[j2] <= min(Node[q[0]].p[j2],Node[q[2]].p[j2])) continue; - - for(h0=0; h0<4 && OK; h0++) - { - h1 = (h0+1)%4; - for(t=0; t<3 && OK; t++) - { - s[t] = side(Node[q[h0]].p[j1],Node[q[h0]].p[j2], - Node[q[h1]].p[j1],Node[q[h1]].p[j2], - Node[Tri[k].v[t]].p[j1],Node[Tri[k].v[t]].p[j2]); - } - if((s[1] > 0 || s[2] > 0) && s[0] < 0) OK=0; - if((s[2] > 0 || s[0] > 0) && s[1] < 0) OK=0; - if((s[0] > 0 || s[1] > 0) && s[2] < 0) OK=0; - } - } - if(!OK) continue; - switch(Plane) - { - case PLANE_XZ0: - case PLANE_XZ1: - // front - brush.face[0].v[0][0] = Node[q[2]].p[0]; - brush.face[0].v[0][1] = (float)front; - brush.face[0].v[0][2] = Node[q[2]].p[2]; - - brush.face[0].v[1][0] = Node[q[1]].p[0]; - brush.face[0].v[1][1] = (float)front; - brush.face[0].v[1][2] = Node[q[1]].p[2]; - - brush.face[0].v[2][0] = Node[q[0]].p[0]; - brush.face[0].v[2][1] = (float)front; - brush.face[0].v[2][2] = Node[q[0]].p[2]; - - // back - brush.face[1].v[0][0] = Node[q[0]].p[0]; - brush.face[1].v[0][1] = (float)backface; - brush.face[1].v[0][2] = Node[q[0]].p[2]; - - brush.face[1].v[1][0] = Node[q[1]].p[0]; - brush.face[1].v[1][1] = (float)backface; - brush.face[1].v[1][2] = Node[q[1]].p[2]; - - brush.face[1].v[2][0] = Node[q[2]].p[0]; - brush.face[1].v[2][1] = (float)backface; - brush.face[1].v[2][2] = Node[q[2]].p[2]; - - for(k0=0; k0= max(Node[q[0]].p[j1], Node[q[2]].p[j1])) { + continue; + } + if (Tri[k].min[j2] >= max(Node[q[0]].p[j2], Node[q[2]].p[j2])) { + continue; + } + if (Tri[k].max[j1] <= min(Node[q[0]].p[j1], Node[q[2]].p[j1])) { + continue; + } + if (Tri[k].max[j2] <= min(Node[q[0]].p[j2], Node[q[2]].p[j2])) { + continue; + } + + for (h0 = 0; h0 < 4 && OK; h0++) { + h1 = (h0 + 1) % 4; + for (t = 0; t < 3 && OK; t++) { + s[t] = side(Node[q[h0]].p[j1], Node[q[h0]].p[j2], + Node[q[h1]].p[j1], Node[q[h1]].p[j2], + Node[Tri[k].v[t]].p[j1], Node[Tri[k].v[t]].p[j2]); + } + if ((s[1] > 0 || s[2] > 0) && s[0] < 0) { + OK = 0; + } + if ((s[2] > 0 || s[0] > 0) && s[1] < 0) { + OK = 0; + } + if ((s[0] > 0 || s[1] > 0) && s[2] < 0) { + OK = 0; + } + } + } + if (!OK) { + continue; + } + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + // front + brush.face[0].v[0][0] = Node[q[2]].p[0]; + brush.face[0].v[0][1] = (float) front; + brush.face[0].v[0][2] = Node[q[2]].p[2]; + + brush.face[0].v[1][0] = Node[q[1]].p[0]; + brush.face[0].v[1][1] = (float) front; + brush.face[0].v[1][2] = Node[q[1]].p[2]; + + brush.face[0].v[2][0] = Node[q[0]].p[0]; + brush.face[0].v[2][1] = (float) front; + brush.face[0].v[2][2] = Node[q[0]].p[2]; + + // back + brush.face[1].v[0][0] = Node[q[0]].p[0]; + brush.face[1].v[0][1] = (float) backface; + brush.face[1].v[0][2] = Node[q[0]].p[2]; + + brush.face[1].v[1][0] = Node[q[1]].p[0]; + brush.face[1].v[1][1] = (float) backface; + brush.face[1].v[1][2] = Node[q[1]].p[2]; + + brush.face[1].v[2][0] = Node[q[2]].p[0]; + brush.face[1].v[2][1] = (float) backface; + brush.face[1].v[2][2] = Node[q[2]].p[2]; + + for (k0 = 0; k0 < brush.NumFaces - 2; k0++) { + k = k0 + 2; + k1 = (k0 + 1) % (brush.NumFaces - 2); + + brush.face[k].v[0][0] = Node[q[k0]].p[0]; + brush.face[k].v[0][1] = (float) front; + brush.face[k].v[0][2] = Node[q[k0]].p[2]; + + brush.face[k].v[1][0] = Node[q[k1]].p[0]; + brush.face[k].v[1][1] = (float) front; + brush.face[k].v[1][2] = Node[q[k1]].p[2]; + + brush.face[k].v[2][0] = Node[q[k1]].p[0]; + brush.face[k].v[2][1] = (float) backface; + brush.face[k].v[2][2] = Node[q[k1]].p[2]; + } + break; + case PLANE_YZ0: + case PLANE_YZ1: + // front + brush.face[0].v[0][0] = (float) front; + brush.face[0].v[0][1] = Node[q[2]].p[1]; + brush.face[0].v[0][2] = Node[q[2]].p[2]; + + brush.face[0].v[1][0] = (float) front; + brush.face[0].v[1][1] = Node[q[1]].p[1]; + brush.face[0].v[1][2] = Node[q[1]].p[2]; + + brush.face[0].v[2][0] = (float) front; + brush.face[0].v[2][1] = Node[q[0]].p[1]; + brush.face[0].v[2][2] = Node[q[0]].p[2]; + + // back + brush.face[1].v[0][0] = (float) backface; + brush.face[1].v[0][1] = Node[q[0]].p[1]; + brush.face[1].v[0][2] = Node[q[0]].p[2]; + + brush.face[1].v[1][0] = (float) backface; + brush.face[1].v[1][1] = Node[q[1]].p[1]; + brush.face[1].v[1][2] = Node[q[1]].p[2]; + + brush.face[1].v[2][0] = (float) backface; + brush.face[1].v[2][1] = Node[q[2]].p[1]; + brush.face[1].v[2][2] = Node[q[2]].p[2]; + + for (k0 = 0; k0 < brush.NumFaces - 2; k0++) { + k = k0 + 2; + k1 = (k0 + 1) % (brush.NumFaces - 2); + + brush.face[k].v[0][0] = (float) front; + brush.face[k].v[0][1] = Node[q[k0]].p[1]; + brush.face[k].v[0][2] = Node[q[k0]].p[2]; + + brush.face[k].v[1][0] = (float) front; + brush.face[k].v[1][1] = Node[q[k1]].p[1]; + brush.face[k].v[1][2] = Node[q[k1]].p[2]; + + brush.face[k].v[2][0] = (float) backface; + brush.face[k].v[2][1] = Node[q[k1]].p[1]; + brush.face[k].v[2][2] = Node[q[k1]].p[2]; + } + break; + default: + // front + brush.face[0].v[0][0] = Node[q[2]].p[0]; + brush.face[0].v[0][1] = Node[q[2]].p[1]; + brush.face[0].v[0][2] = (float) front; + + brush.face[0].v[1][0] = Node[q[1]].p[0]; + brush.face[0].v[1][1] = Node[q[1]].p[1]; + brush.face[0].v[1][2] = (float) front; + + brush.face[0].v[2][0] = Node[q[0]].p[0]; + brush.face[0].v[2][1] = Node[q[0]].p[1]; + brush.face[0].v[2][2] = (float) front; + + // back + brush.face[1].v[0][0] = Node[q[0]].p[0]; + brush.face[1].v[0][1] = Node[q[0]].p[1]; + brush.face[1].v[0][2] = (float) backface; + + brush.face[1].v[1][0] = Node[q[1]].p[0]; + brush.face[1].v[1][1] = Node[q[1]].p[1]; + brush.face[1].v[1][2] = (float) backface; + + brush.face[1].v[2][0] = Node[q[2]].p[0]; + brush.face[1].v[2][1] = Node[q[2]].p[1]; + brush.face[1].v[2][2] = (float) backface; + + for (k0 = 0; k0 < brush.NumFaces - 2; k0++) { + k = k0 + 2; + k1 = (k0 + 1) % (brush.NumFaces - 2); + + brush.face[k].v[0][0] = Node[q[k0]].p[0]; + brush.face[k].v[0][1] = Node[q[k0]].p[1]; + brush.face[k].v[0][2] = (float) front; + + brush.face[k].v[1][0] = Node[q[k1]].p[0]; + brush.face[k].v[1][1] = Node[q[k1]].p[1]; + brush.face[k].v[1][2] = (float) front; + + brush.face[k].v[2][0] = Node[q[k1]].p[0]; + brush.face[k].v[2][1] = Node[q[k1]].p[1]; + brush.face[k].v[2][2] = (float) backface; + } + break; + } // switch (Plane) + for (face = 0; face < 6; face++) { + strcpy(brush.face[face].texture, (face <= 1 ? skip : hint)); + brush.face[face].Shift[0] = 0; + brush.face[face].Shift[1] = 0; + brush.face[face].Rotate = 0.; + brush.face[face].Scale[0] = 1; + brush.face[face].Scale[1] = 1; + brush.face[face].Contents = CONTENTS_DETAIL; + brush.face[face].Surface = (face <= 1 ? SURF_SKIP : SURF_HINT); + brush.face[face].Value = 0; + } + if (!brush.Number) { + OpenFuncGroup(); + } + MakeBrush(&brush); + brush.Number++; + } // for(j= + } // for(i= + } // for(h= + } // for(w= + if (brush.Number) { + CloseFuncGroup(); + } + } + /* + ghCursorCurrent = ghCursorDefault; + SetCursor(ghCursorCurrent); + */ } + //=========================================================================== int CheckBorders(int *NumNodesUsed, int NumNodes, NODE *Node, int *NumTris, TRI **pTri) { - int border; - int i, j, k0, k1, N; - float angle[3]; - TRI *Tri; - - N = NumNodesUsed[0]; - Tri = *pTri; - for(i=0; i= 0) - { - if(!Node[j].used) // Shouldn't be used, but... - { - NumNodesUsed[0]++; - Node[j].used++; - } - } - } - } - if(NumNodesUsed[0] > N) - { - free(*pTri); - tricall(NumNodes, Node, NumTris, NULL, pTri, "cnzBNPY"); - Tri = *pTri; - } - return (NumNodesUsed[0] - N); + int border; + int i, j, k0, k1, N; + float angle[3]; + TRI *Tri; + + N = NumNodesUsed[0]; + Tri = *pTri; + for (i = 0; i < NumTris[0]; i++) { + EdgeOnSide(Tri[i].v, &k0, &border); + if (border < 0) { + continue; + } + CalcAngles(Node, Tri[i].v, angle); + k1 = (k0 + 1) % 3; + if ((angle[k0] < SLIVER_ANGLE) || (angle[k1] < SLIVER_ANGLE)) { + j = Bisect(Node, border, Tri[i].v[k0], Tri[i].v[k1]); + if (j >= 0) { + if (!Node[j].used) { // Shouldn't be used, but... + NumNodesUsed[0]++; + Node[j].used++; + } + } + } + } + if (NumNodesUsed[0] > N) { + free(*pTri); + tricall(NumNodes, Node, NumTris, NULL, pTri, "cnzBNPY"); + Tri = *pTri; + } + return (NumNodesUsed[0] - N); }