/* 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 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 */ #include #include #include #include "gensurf.h" double xmin,xmax,ymin,ymax,zmin,zmax; double backface; extern double dh, dv; FILE *fmap; XYZ xyz[MAX_ROWS+1][MAX_ROWS+1]; int contents; int surface[3]; #include "iundo.h" #include "refcounted_ptr.h" #include #include #include #include #include "scenelib.h" scene::Node* h_func_group; scene::Node* h_worldspawn; //============================================================= // Hydra : snap-to-grid begin double CalculateSnapValue(double value) { long snapvalue; // simple uncomplicated snapping, rounding both UP and DOWN to the nearest // grid unit. if (SnapToGrid >0) { snapvalue = (int)value / SnapToGrid; if ((long)value % SnapToGrid < (SnapToGrid / 2)) // Snap Downwards if less than halfway between to grid units value = snapvalue * SnapToGrid; else // Snap Upwards if more than halfway between to grid units value = (snapvalue+1) * SnapToGrid; } return value; } // Hydra : snap-to-grid end //============================================================= bool ValidSurface() { if(WaveType == WAVE_BITMAP && !gbmp.colors) return FALSE; if(NH < 1) return FALSE; if(NH > MAX_ROWS) return FALSE; if(NV < 1) return FALSE; if(NV > MAX_ROWS) return FALSE; if(Hll >= Hur) return FALSE; if(Vll >= Vur) return FALSE; return TRUE; } //============================================================= int MapPatches() { int NH_remain; int NV_remain; int NH_patch; int NV_patch; int BrushNum = 0; int i, j, k1, k2, k3; int i0, j0, ii; char szOops[128]; dh = (Hur-Hll)/NH; dv = (Vur-Vll)/NV; // Generate control points in pp array to give desired values currently // in p array. switch(Plane) { case PLANE_XY0: case PLANE_XY1: k1 = 0; k2 = 1; k3 = 2; break; case PLANE_XZ0: case PLANE_XZ1: k1 = 0; k2 = 2; k3 = 1; break; case PLANE_YZ0: case PLANE_YZ1: k1 = 1; k2 = 2; k3 = 0; break; } for(i=0; i<=NH; i++) { for(j=0; j<=NV; j++) { xyz[i][j].pp[k1] = xyz[i][j].p[k1]; xyz[i][j].pp[k2] = xyz[i][j].p[k2]; } } for(i=0; i<=NH; i+=2) { for(j=0; j<=NV; j+=2) xyz[i][j].pp[k3] = xyz[i][j].p[k3]; } for(i=1; i 1) { if(( (NH_remain-1) % 14) == 0) NH_patch = 15; else if(( (NH_remain-1) % 12) == 0) NH_patch = 13; else if(( (NH_remain-1) % 10) == 0) NH_patch = 11; else if(( (NH_remain-1) % 8) == 0) NH_patch = 9; else if(( (NH_remain-1) % 6) == 0) NH_patch = 7; else if(( (NH_remain-1) % 4) == 0) NH_patch = 5; else if(( (NH_remain-1) % 2) == 0) NH_patch = 3; else if(NH_remain > 16) NH_patch = 7; else if(NH_remain > 4) NH_patch = 5; else NH_patch = 3; while( NH_patch > 3 && (NH_patch-1)*dh > 512 ) NH_patch -= 2; NH_remain -= (NH_patch-1); if(NH_remain < 0) { sprintf(szOops,"Oops... screwed up with NH=%d",NH); g_FuncTable.m_pfnMessageBox(NULL,szOops,"Uh oh"); } NV_remain = NV+1; j0 = 0; while(NV_remain > 1) { if(( (NV_remain-1) % 14) == 0) NV_patch = 15; else if(( (NV_remain-1) % 12) == 0) NV_patch = 13; else if(( (NV_remain-1) % 10) == 0) NV_patch = 11; else if(( (NV_remain-1) % 8) == 0) NV_patch = 9; else if(( (NV_remain-1) % 6) == 0) NV_patch = 7; else if(( (NV_remain-1) % 4) == 0) NV_patch = 5; else if(( (NV_remain-1) % 2) == 0) NV_patch = 3; else if(NV_remain > 16) NV_patch = 7; else if(NV_remain > 4) NV_patch = 5; else NV_patch = 3; while( NV_patch > 3 && (NV_patch-1)*dh > 512 ) NV_patch -= 2; NV_remain -= (NV_patch-1); if(NV_remain < 0) { sprintf(szOops,"Oops... screwed up with NV=%d",NV); g_FuncTable.m_pfnMessageBox(NULL,szOops,"Uh oh"); } scene::Node* patch = MakePatch(); #if 0 b->pPatch->setDims(NH_patch, NV_patch); for(i=0; ipPatch->ctrlAt(COL,i,j)[0] = (float)xyz[ii][j0+j].pp[0]; b->pPatch->ctrlAt(COL,i,j)[1] = (float)xyz[ii][j0+j].pp[1]; b->pPatch->ctrlAt(COL,i,j)[2] = (float)xyz[ii][j0+j].pp[2]; b->pPatch->ctrlAt(COL,i,j)[3] = (float)i; b->pPatch->ctrlAt(COL,i,j)[4] = (float)j; } } b->pPatch->UpdateCachedData(); #endif BrushNum++; j0 += NV_patch-1; } i0 += NH_patch-1; } return BrushNum; } //============================================================= void MapBrushes() { char hint[128]; char skip[128]; char sidetext[64]; char surftext[64]; char surftext2[64]; char surft[64]; float Steep; vec3_t PlaneNormal,SurfNormal; vec3_t t[2]; int i, j, k; int surf; bool CheckAngle; BRUSH brush; XYZ v[8]; strcpy(surftext,Texture[Game][0]); strcpy(sidetext,(strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0])); strcpy(surftext2,(strlen(Texture[Game][2]) ? Texture[Game][2] : Texture[Game][0])); // if surftext2 is identical to surftext, there's no need to // check surface angle if(!g_strcasecmp(surftext,surftext2)) 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; } } OpenFuncGroup(); for(i=0; i 0 && (Game != QUAKE3 || UsePatches==0) ) { MapOut(gNumNodes,gNumTris,gNode,gTri); /* ghCursorCurrent = ghCursorDefault; SetCursor(ghCursorCurrent); */ return; } contents = 0; // HL doesn't have detail property if((Game != HALFLIFE) && UseDetail) contents += CONTENTS_DETAIL; // HL and Q3 don't have ladder property if((Game != HALFLIFE && Game != QUAKE3) && UseLadder) contents += CONTENTS_LADDER; // Genesis requires solid property to be set explicitly if(Game == GENESIS3D) contents |= CONTENTS_SOLID; // Heretic 2 uses different sounds (in surface props) for different texture types if(Game == HERETIC2) { surface[0] = GetDefSurfaceProps(Texture[Game][0]); surface[1] = GetDefSurfaceProps(Texture[Game][1]); surface[2] = GetDefSurfaceProps(Texture[Game][2]); } else { surface[0] = 0; surface[1] = 0; surface[2] = 0; } if(Game!=QUAKE3 || UsePatches == 0) MapBrushes(); /* ghCursorCurrent = ghCursorDefault; SetCursor(ghCursorCurrent); */ } //============================================================= void GenerateXYZ() { extern void MakeDecimatedMap(int *, int *, NODE **, TRI **); double zl, zu; double wh, wv; int NHalfcycles; double a,v,h,ha,va; double delta, dr, rate; double range, maxrange; double r; int i, j, k, N; int i0, i1, j0, j1; int ii, jj; // FILE *f; // char CSV[64]; if(!ValidSurface()) return; srand(1); srand(RandomSeed); dh = (Hur-Hll)/NH; dv = (Vur-Vll)/NV; // H & V for(i=0; i<=NH; i++) { for(j=0;j<=NV;j++) { switch(Plane) { case PLANE_XZ0: case PLANE_XZ1: xyz[i][j].p[0] = Hll + i*dh; xyz[i][j].p[2] = Vll + j*dv; break; case PLANE_YZ0: case PLANE_YZ1: xyz[i][j].p[1] = Hll + i*dh; xyz[i][j].p[2] = Vll + j*dv; break; default: xyz[i][j].p[0] = Hll + i*dh; xyz[i][j].p[1] = Vll + j*dv; } } } if(WaveType == WAVE_BITMAP) GenerateBitmapMapping(); /* else if(WaveType == WAVE_FORMULA) DoFormula(); */ else { // Initialize Z values using bilinear interpolation for(i=0; i<=NH; i++) { zl = Z00 + i*(Z10 - Z00)/NH; zu = Z01 + i*(Z11 - Z01)/NH; switch(Plane) { case PLANE_XZ0: case PLANE_XZ1: for(j=0; j<=NV; j++) xyz[i][j].p[1] = zl + j*(zu-zl)/NV; break; case PLANE_YZ0: case PLANE_YZ1: for(j=0; j<=NV; j++) xyz[i][j].p[0] = zl + j*(zu-zl)/NV; break; default: for(j=0; j<=NV; j++) xyz[i][j].p[2] = zl + j*(zu-zl)/NV; } } } switch(WaveType) { case WAVE_COS_SIN: if(FixBorders) { NHalfcycles = (int)((Hur-Hll)/(WaveLength/2.)); NHalfcycles = max(NHalfcycles,1); wh = 2.*(Hur-Hll)/NHalfcycles; NHalfcycles = (int)((Vur-Vll)/(WaveLength/2.)); wv = 2.*(Vur-Vll)/NHalfcycles; NHalfcycles = max(NHalfcycles,1); i0 = 1; i1 = NH-1; j0 = 1; j1 = NV-1; } else { wh = WaveLength; wv = WaveLength; i0 = 0; i1 = NH; j0 = 0; j1 = NV; } for(i=i0; i<=i1; i++) { h = Hll + i*dh; ha = ((h-Hll)/wh)*2.*PI - PI/2.; for(j=j0; j<=j1; j++) { v = Vll + j*dv; va = ((v-Vll)/wv)*2.*PI; a = Amplitude * cos( ha ) * sin( va ); switch(Plane) { case PLANE_XY1: xyz[i][j].p[2] -= a; break; case PLANE_XZ0: xyz[i][j].p[1] += a; break; case PLANE_XZ1: xyz[i][j].p[1] -= a; break; case PLANE_YZ0: xyz[i][j].p[0] += a; break; case PLANE_YZ1: xyz[i][j].p[0] -= a; break; default: xyz[i][j].p[2] += a; } } } break; case WAVE_HCYLINDER: for(i=0; i<=NH; i++) { h = Hll + i*dh; ha = ((h-Hll)/WaveLength)*2.*PI - PI/2.; for(j=0; j<=NV; j++) { a = Amplitude * cos( ha ); switch(Plane) { case PLANE_XY1: xyz[i][j].p[2] -= a; break; case PLANE_XZ0: xyz[i][j].p[1] += a; break; case PLANE_XZ1: xyz[i][j].p[1] -= a; break; case PLANE_YZ0: xyz[i][j].p[0] += a; break; case PLANE_YZ1: xyz[i][j].p[0] -= a; break; default: xyz[i][j].p[2] += a; } } } break; case WAVE_VCYLINDER: for(i=0; i<=NH; i++) { h = Hll + i*dh; for(j=0; j<=NV; j++) { v = Vll + j*dv; va = ((v-Vll)/WaveLength)*2.*PI; a = Amplitude * sin( va ); switch(Plane) { case PLANE_XY1: xyz[i][j].p[2] -= a; break; case PLANE_XZ0: xyz[i][j].p[1] += a; break; case PLANE_XZ1: xyz[i][j].p[1] -= a; break; case PLANE_YZ0: xyz[i][j].p[0] += a; break; case PLANE_YZ1: xyz[i][j].p[0] -= a; break; default: xyz[i][j].p[2] += a; } } } break; case WAVE_ROUGH_ONLY: PlasmaCloud(); break; } if(WaveType != WAVE_ROUGH_ONLY) { // Fixed values for(i=0; i<=NH; i++) { for(j=0; j<=NV; j++) { if(xyz[i][j].fixed) { switch(Plane) { case PLANE_XZ0: case PLANE_XZ1: xyz[i][j].p[1] = xyz[i][j].fixed_value; break; case PLANE_YZ0: case PLANE_YZ1: xyz[i][j].p[0] = xyz[i][j].fixed_value; break; default: xyz[i][j].p[2] = xyz[i][j].fixed_value; } if(xyz[i][j].range > 0) { maxrange = pow(xyz[i][j].range,2); // so we don't have to do sqrt's i0 = i - (int)( floor(xyz[i][j].range/dh - 0.5) + 1 ); i1 = i + i - i0; j0 = j - (int)( floor(xyz[i][j].range/dv - 0.5) + 1 ); j1 = j + j - j0; if(FixBorders) { i0 = max(i0,1); i1 = min(i1,NH-1); j0 = max(j0,1); j1 = min(j1,NV-1); } else { i0 = max(i0,0); i1 = min(i1,NH); j0 = max(j0,0); j1 = min(j1,NV); } for(ii=i0; ii<=i1; ii++) { for(jj=j0; jj<=j1; jj++) { if(ii==i && jj==j) continue; range = pow( dh*(i-ii), 2) + pow( dv*(j-jj), 2); if(range > maxrange) continue; dr = sqrt(range/maxrange); rate = max(-30.,min(xyz[i][j].rate,30.)); if(rate < -1.) { delta = pow((1.-dr),-rate+1.); } else if(rate < 0.) { delta = (1+rate)*0.5*(cos(dr*PI)+1.0) - rate*pow((1.-dr),2); } else if(rate == 0.) { delta = 0.5*(cos(dr*PI)+1.0); } else if(rate <= 1.) { delta = (1.-rate)*0.5*(cos(dr*PI)+1.0) + rate*(1.-pow(dr,2)); } else { delta = 1.-pow(dr,rate+1); } switch(Plane) { case PLANE_XZ0: case PLANE_XZ1: xyz[ii][jj].p[1] += (xyz[i][j].p[1] - xyz[ii][jj].p[1])*delta; break; case PLANE_YZ0: case PLANE_YZ1: xyz[ii][jj].p[0] += (xyz[i][j].p[0] - xyz[ii][jj].p[0])*delta; break; default: xyz[ii][jj].p[2] += (xyz[i][j].p[2] - xyz[ii][jj].p[2])*delta; } } } } } } } } if((Roughness > 0.) && (WaveType != WAVE_ROUGH_ONLY) ) { for(i=0; i<=NH; i++) { for(j=0; j<=NV; j++) { if(CanEdit(i,j) && !xyz[i][j].fixed) { switch(Plane) { case PLANE_XZ0: case PLANE_XZ1: xyz[i][j].p[1] += -Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX); break; case PLANE_YZ0: case PLANE_YZ1: xyz[i][j].p[0] += -Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX); break; default: xyz[i][j].p[2] += -Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX); } } else r = rand(); // We still get a random number, so that fixing points // doesn't change the sequence. } } } for(i=0; i<=NH; i++) { for(j=0; j<=NV; j++) { for(k=0; k<3; k++) { xyz[i][j].p[k] = Nearest(xyz[i][j].p[k],2.0); } } } // Find minima and maxima switch(Plane) { case PLANE_XZ0: case PLANE_XZ1: xmin = Hll; xmax = Hur; zmin = Vll; zmax = Vur; ymin = xyz[0][0].p[1]; ymax = ymin; for(i=0; i<=NH; i++) { for(j=0; j<=NV; j++) { ymin = min(ymin,xyz[i][j].p[1]); ymax = max(ymax,xyz[i][j].p[1]); } } break; case PLANE_YZ0: case PLANE_YZ1: ymin = Hll; ymax = Hur; zmin = Vll; zmax = Vur; xmin = xyz[0][0].p[0]; xmax = ymin; for(i=0; i<=NH; i++) { for(j=0; j<=NV; j++) { xmin = min(xmin,xyz[i][j].p[0]); xmax = max(xmax,xyz[i][j].p[0]); } } break; break; default: xmin = Hll; xmax = Hur; ymin = Vll; ymax = Vur; zmin = xyz[0][0].p[2]; zmax = zmin; for(i=0; i<=NH; i++) { for(j=0; j<=NV; j++) { zmin = min(zmin,xyz[i][j].p[2]); zmax = max(zmax,xyz[i][j].p[2]); } } } xmin = Nearest(xmin,2.); xmax = Nearest(xmax,2.); ymin = Nearest(ymin,2.); ymax = Nearest(ymax,2.); zmin = Nearest(zmin,2.); zmax = Nearest(zmax,2.); switch(Plane) { case PLANE_XY1: backface = AtLeast(zmax+32.,32.); break; case PLANE_XZ0: backface = NoMoreThan(ymin-32.,32.); break; case PLANE_XZ1: backface = AtLeast(ymax+32.,32.); break; case PLANE_YZ0: backface = NoMoreThan(xmin-32.,32.); break; case PLANE_YZ1: backface = AtLeast(xmax+32.,32.); break; default: backface = NoMoreThan(zmin-32.,32.); } if(gNode) { free(gNode); free(gTri); gNode = (NODE *)NULL; gTri = (TRI *)NULL; } if(Decimate > 0 && (Game != QUAKE3 || UsePatches==0) ) { MakeDecimatedMap(&gNumNodes,&gNumTris,&gNode,&gTri); } else { gNumNodes = (NH+1)*(NV+1); gNumTris = NH*NV*2; gNode = (NODE *) malloc(gNumNodes * sizeof(NODE)); gTri = (TRI *) malloc(gNumTris * sizeof(TRI)); for(i=0,N=0; i<=NH; i++) { for(j=0; j<=NV; j++, N++) { gNode[N].used = 1; gNode[N].p[0] = (float)xyz[i][j].p[0]; gNode[N].p[1] = (float)xyz[i][j].p[1]; gNode[N].p[2] = (float)xyz[i][j].p[2]; } } for(i=0; i 0) { for(i=0; i x) xx -= dx; return xx; } //============================================================= double AtLeast(double x, double dx) { double xx; xx = (double)(floor(x/dx - 0.5)+1.)*dx; if(xx < x) xx += dx; return xx; } //============================================================= double LessThan(double x,double dx) { double xx; xx = (double)(floor(x/dx - 0.5)+1.)*dx; if(xx >= x) xx -= dx; return xx; } //============================================================= double MoreThan(double x,double dx) { double xx; xx = (double)(floor(x/dx - 0.5)+1.)*dx; while(xx <= x) xx += dx; return xx; } //============================================================= void SubdividePlasma(int i0,int j0,int i1,int j1) { int i, j; double z1, z2; double r; // NOTE: This is used to keep the random number sequence the same // when we fix a point. If we did NOT do this, then simply // fixing a point at its current value would change the entire // surface. i = (i0+i1)/2; j = (j0+j1)/2; if(i1 > i0+1) { if(!xyz[i][j0].done) { xyz[i][j0].pp[2] = xyz[i0][j0].pp[2] + (xyz[i1][j0].pp[2] - xyz[i0][j0].pp[2])*(double)(i-i0)/(double)(i1-i0) + ((double)(i-i0))*(-Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX)); xyz[i][j0].done = 1; } else r = rand(); if((j1 > j0) && (!xyz[i][j1].done) ) { xyz[i][j1].pp[2] = xyz[i0][j1].pp[2] + (xyz[i1][j1].pp[2] - xyz[i0][j1].pp[2])*(double)(i-i0)/(double)(i1-i0) + ((double)(i-i0))*(-Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX)); xyz[i][j1].done = 1; } else r = rand(); } if(j1 > j0 + 1) { if(!xyz[i0][j].done) { xyz[i0][j].pp[2] = xyz[i0][j0].pp[2] + (xyz[i0][j1].pp[2] - xyz[i0][j0].pp[2])*(double)(j-j0)/(double)(j1-j0) + ((double)(j-j0))*(-Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX)); xyz[i0][j].done = 1; } else r = rand(); if((i1 > i0) && (!xyz[i1][j].done)) { xyz[i1][j].pp[2] = xyz[i1][j0].pp[2] + (xyz[i1][j1].pp[2] - xyz[i1][j0].pp[2])*(double)(j-j0)/(double)(j1-j0) + ((double)(j-j0))*(-Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX)); xyz[i1][j].done = 1; } else r = rand(); } if((i1 > i0+1) && (j1 > j0+1)) { if(!xyz[i][j].done) { z1 = xyz[i0][j].pp[2] + (xyz[i1][j].pp[2] - xyz[i0][j].pp[2])*(double)(i-i0)/(double)(i1-i0); z2 = xyz[i][j0].pp[2] + (xyz[i][j1].pp[2] - xyz[i][j0].pp[2])*(double)(j-j0)/(double)(j1-j0); xyz[i][j].pp[2] = (z1+z2)/2. + ((double)(i-i0))*(-Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX)); xyz[i][j].done = 1; } else r = rand(); } if(i > i0+1 || j > j0+1) SubdividePlasma(i0,j0,i,j); if(i1 > i+1 || j > j0+1) SubdividePlasma(i,j0,i1,j); if(i > i0+1 || j1 > j0+1) SubdividePlasma(i0,j,i,j1); if(i1 > i+1 || j1 > j0+1) SubdividePlasma(i,j,i1,j1); } //================================================================================== void PlasmaCloud() { int i, j; /* use pp[2] values until done to avoid messing with a bunch of switch statements */ for(i=0; i<=NH; i++) { for(j=0; j<=NV; j++) { if(FixedPoint(i,j)) xyz[i][j].done = 1; else xyz[i][j].done = 0; } } switch(Plane) { case PLANE_XZ0: case PLANE_XZ1: for(i=0; i<=NH; i++) { for(j=0; j<=NV; j++) { if(xyz[i][j].fixed) xyz[i][j].pp[2] = xyz[i][j].fixed_value; else xyz[i][j].pp[2] = xyz[i][j].p[1]; } } break; case PLANE_YZ0: case PLANE_YZ1: for(i=0; i<=NH; i++) { for(j=0; j<=NV; j++) { if(xyz[i][j].fixed) xyz[i][j].pp[2] = xyz[i][j].fixed_value; else xyz[i][j].pp[2] = xyz[i][j].p[0]; } } break; default: for(i=0; i<=NH; i++) { for(j=0; j<=NV; j++) { if(xyz[i][j].fixed) xyz[i][j].pp[2] = xyz[i][j].fixed_value; else xyz[i][j].pp[2] = xyz[i][j].p[2]; } } break; } SubdividePlasma(0,0,NH,NV); switch(Plane) { case PLANE_XZ0: case PLANE_XZ1: for(i=0; i<=NH; i++) { for(j=0; j<=NV; j++) { xyz[i][j].p[1] = xyz[i][j].pp[2]; } } break; case PLANE_YZ0: case PLANE_YZ1: for(i=0; i<=NH; i++) { for(j=0; j<=NV; j++) { xyz[i][j].p[0] = xyz[i][j].pp[2]; } } break; default: for(i=0; i<=NH; i++) { for(j=0; j<=NV; j++) { xyz[i][j].p[2] = xyz[i][j].pp[2]; } } break; } } //=========================================================================== bool FixedPoint(int i, int j) { if(xyz[i][j].fixed) return TRUE; return !CanEdit(i,j); } //=========================================================================== bool CanEdit(int i, int j) { if(FixBorders && ( (WaveType==WAVE_COS_SIN) || (WaveType==WAVE_ROUGH_ONLY) ) ) { if(i== 0) return FALSE; if(i==NH) return FALSE; if(j== 0) return FALSE; if(j==NV) return FALSE; } if(i== 0 && j== 0) return FALSE; if(i==NH && j== 0) return FALSE; if(i== 0 && j==NV) return FALSE; if(i==NH && j==NV) return FALSE; return TRUE; } /*============================================================================ TriangleFromPoint Determines which triangle in the gTri array bounds the input point. Doesn't do anything special with border points. */ int TriangleFromPoint(double x, double y) { int j, tri; if(!gTri) return -1; for(j=0, tri=-1; jp[0],2.); v[0][1] = (vec)Nearest(xyz->p[1],2.); v[0][2] = (vec)Nearest(xyz->p[2],2.); } //============================================================= scene::Node* MakePatch(void) { scene::Node* patch = Patch_AllocNode(); #if 0 patch->m_patch->SetShader(Texture[Game][0]); #endif Node_getTraversable(h_worldspawn)->insert(patch); return patch; } //============================================================= void MakeBrush(BRUSH *brush) { NodePtr node(Brush_AllocNode()); #if 0 for(int i=0; iNumFaces; i++) { _QERFaceData QERFaceData; if(!strncmp(brush->face[i].texture, "textures/", 9)) strcpy(QERFaceData.m_TextureName,brush->face[i].texture); else { strcpy(QERFaceData.m_TextureName,"textures/"); strcpy(QERFaceData.m_TextureName+9,brush->face[i].texture); } QERFaceData.m_nContents = brush->face[i].Contents; QERFaceData.m_nFlags = brush->face[i].Surface; QERFaceData.m_nValue = brush->face[i].Value; QERFaceData.m_fShift[0] = brush->face[i].Shift[0]; QERFaceData.m_fShift[1] = brush->face[i].Shift[1]; QERFaceData.m_fRotate = brush->face[i].Rotate; QERFaceData.m_fScale[0] = brush->face[i].Scale[0]; QERFaceData.m_fScale[1] = brush->face[i].Scale[1]; QERFaceData.m_v1[0] = brush->face[i].v[0][0]; QERFaceData.m_v1[1] = brush->face[i].v[0][1]; QERFaceData.m_v1[2] = brush->face[i].v[0][2]; QERFaceData.m_v2[0] = brush->face[i].v[1][0]; QERFaceData.m_v2[1] = brush->face[i].v[1][1]; QERFaceData.m_v2[2] = brush->face[i].v[1][2]; QERFaceData.m_v3[0] = brush->face[i].v[2][0]; QERFaceData.m_v3[1] = brush->face[i].v[2][1]; QERFaceData.m_v3[2] = brush->face[i].v[2][2]; QERFaceData.m_bBPrimit = false; (g_FuncTable.m_pfnAddFaceData)(vp,&QERFaceData); } #endif Node_getTraversable(h_func_group)->insert(node); } //============================================================= void OpenFuncGroup() { h_func_group = GlobalEntityCreator().createEntity("func_group"); h_func_group->IncRef(); if(AddTerrainKey) h_func_group->m_entity->setkeyvalue("terrain", "1"); } //============================================================= void CloseFuncGroup() { h_func_group->DecRef(); if (g_FuncTable.m_pfnSysUpdateWindows != NULL) g_FuncTable.m_pfnSysUpdateWindows (W_ALL); }