00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "stdafx.h"
00028 #include "qe3.h"
00029 #include "DialogInfo.h"
00030 #include "CapDialog.h"
00031
00032
00033 extern void MemFile_fprintf(CMemFile* pMemFile, const char* pText, ...);
00034 extern face_t *Face_Alloc( void );
00035 void _Write3DMatrix (FILE *f, int y, int x, int z, float *m);
00036 void _Write3DMatrix (CMemFile *f, int y, int x, int z, float *m);
00037
00038
00039
00040 #define CBLOCK_SUBDIVISIONS 6
00041
00042
00043 patchMesh_t* MakeNewPatch()
00044 {
00045 patchMesh_t *pm = reinterpret_cast<patchMesh_t*>(qmalloc(sizeof(patchMesh_t)));
00046 if (g_qeglobals.bSurfacePropertiesPlugin)
00047 {
00048 pm->pData = static_cast<void *>( g_SurfaceTable.m_pfnPatchAlloc( pm ) );
00049 }
00050 return pm;
00051 }
00052
00053
00054
00055
00056
00057
00058
00059 patchMesh_t patchSave;
00060
00061
00062
00063
00064
00065
00066
00067
00068 int g_nPatchClickedView = -1;
00069 bool g_bSameView = false;
00070
00071
00072
00073 bool g_bPatchShowBounds = true;
00074 bool g_bPatchWireFrame = false;
00075 bool g_bPatchWeld = true;
00076 bool g_bPatchDrillDown = true;
00077 bool g_bPatchInsertMode = false;
00078 bool g_bPatchBendMode = false;
00079 int g_nPatchBendState = -1;
00080 int g_nPatchInsertState = -1;
00081 int g_nBendOriginIndex = 0;
00082 vec3_t g_vBendOrigin;
00083
00084 bool g_bPatchAxisOnRow = true;
00085 int g_nPatchAxisIndex = 0;
00086 bool g_bPatchLowerEdge = true;
00087
00088
00089 enum
00090 {
00091 BEND_SELECT_ROTATION = 0,
00092 BEND_SELECT_ORIGIN,
00093 BEND_SELECT_EDGE,
00094 BEND_BENDIT,
00095 BEND_STATE_COUNT
00096 };
00097
00098 const char *g_pBendStateMsg[] =
00099 {
00100 "Use TAB to cycle through available bend axis. Press ENTER when the desired one is highlighted.",
00101 "Use TAB to cycle through available rotation axis. This will LOCK around that point. You may also use Shift + Middle Click to select an arbitrary point. Press ENTER when the desired one is highlighted",
00102 "Use TAB to choose which side to bend. Press ENTER when the desired one is highlighted.",
00103 "Use the MOUSE to bend the patch. It uses the same ui rules as Free Rotation. Press ENTER to accept the bend, press ESC to abandon it and exit Bend mode",
00104 ""
00105 };
00106
00107
00108 enum
00109 {
00110 INSERT_SELECT_EDGE = 0,
00111 INSERT_STATE_COUNT
00112 };
00113
00114 const char* g_pInsertStateMsg[] =
00115 {
00116 "Use TAB to cycle through available rows/columns for insertion/deletion. Press INS to insert at the highlight, DEL to remove the pair"
00117 };
00118
00119
00120 float *g_InversePoints[1024];
00121
00122 const float fFullBright = 1.0;
00123 const float fLowerLimit = .50;
00124 const float fDec = .05;
00125 void _SetColor(face_t* f, float fColor[3])
00126 {
00127 return;
00128 fColor[0] = f->d_color[0];
00129 fColor[1] = f->d_color[1];
00130 fColor[2] = f->d_color[2];
00131 qglColor3fv(fColor);
00132 }
00133
00134
00135 void _DecColor(float fColor[3])
00136 {
00137 return;
00138 fColor[0] -= fDec;
00139 fColor[1] -= fDec ;
00140 fColor[2] -= fDec;
00141 for (int i = 0; i < 3; i++)
00142 {
00143 if (fColor[i] <= fLowerLimit)
00144 {
00145 fColor[0] = fFullBright;
00146 fColor[1] = fFullBright;
00147 fColor[2] = fFullBright;
00148 break;
00149 }
00150 }
00151 qglColor3fv(fColor);
00152 }
00153
00154 vec_t __VectorNormalize (vec3_t in, vec3_t out)
00155 {
00156 vec_t length, ilength;
00157
00158 length = sqrt (in[0]*in[0] + in[1]*in[1] + in[2]*in[2]);
00159 if (length == 0)
00160 {
00161 VectorClear (out);
00162 return 0;
00163 }
00164
00165 ilength = 1.0/length;
00166 out[0] = in[0]*ilength;
00167 out[1] = in[1]*ilength;
00168 out[2] = in[2]*ilength;
00169
00170 return length;
00171 }
00172
00173
00174 void Patch_SetType(patchMesh_t *p, int nType)
00175 {
00176 p->type = (p->type & PATCH_STYLEMASK) | nType;
00177 }
00178
00179 void Patch_SetStyle(patchMesh_t *p, int nStyle)
00180 {
00181 p->type = (p->type & PATCH_TYPEMASK) | nStyle;
00182 }
00183
00184
00185
00186
00187
00188
00189 int Patch_MemorySize(patchMesh_t *p)
00190 {
00191 return _msize(p);
00192 }
00193
00194
00195
00196
00197
00198
00199
00200
00201 void InterpolateInteriorPoints( patchMesh_t *p )
00202 {
00203 int i, j, k;
00204 int next, prev;
00205
00206 for ( i = 0 ; i < p->width ; i += 2 )
00207 {
00208
00209 next = ( i == p->width - 1 ) ? 1 : ( i + 1 ) % p->width;
00210 prev = ( i == 0 ) ? p->width - 2 : i - 1;
00211
00212 #if 0
00213 if ( i == 0 )
00214 {
00215 next = ( i + 1 ) % p->width;
00216 prev = p->width - 2;
00217 }
00218 else if ( i == p->width - 1 )
00219 {
00220 next = 1;
00221 prev = i - 1;
00222 }
00223 else
00224 {
00225 next = ( i + 1 ) % p->width;
00226 prev = i - 1;
00227 }
00228 #endif
00229
00230 for ( j = 0 ; j < p->height ; j++ )
00231 {
00232 for ( k = 0 ; k < 3 ; k++ )
00233 {
00234 p->ctrl[i][j].xyz[k] = ( p->ctrl[next][j].xyz[k] + p->ctrl[prev][j].xyz[k] ) * 0.5;
00235 }
00236 }
00237 }
00238 }
00239
00240
00241
00242
00243
00244
00245
00246 int neighbors[8][2] = {
00247 {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {-1,1}
00248 };
00249
00250 void Patch_MeshNormals(patchMesh_t *in )
00251 {
00252 int i, j, k, dist;
00253 vec3_t normal;
00254 vec3_t sum;
00255 int count;
00256 vec3_t base;
00257 vec3_t delta;
00258 int x, y;
00259 drawVert_t *dv;
00260 vec3_t around[8], temp;
00261 qboolean good[8];
00262 qboolean wrapWidth, wrapHeight;
00263 float len;
00264
00265 wrapWidth = false;
00266 for ( i = 0 ; i < in->height ; i++ )
00267 {
00268
00269 VectorSubtract( in->ctrl[0][i].xyz,
00270 in->ctrl[in->width-1][i].xyz, delta );
00271 len = VectorLength( delta );
00272 if ( len > 1.0 )
00273 {
00274 break;
00275 }
00276 }
00277 if ( i == in->height )
00278 {
00279 wrapWidth = true;
00280 }
00281
00282 wrapHeight = false;
00283 for ( i = 0 ; i < in->width ; i++ )
00284 {
00285 VectorSubtract( in->ctrl[i][0].xyz,
00286 in->ctrl[i][in->height-1].xyz, delta );
00287 len = VectorLength( delta );
00288 if ( len > 1.0 )
00289 {
00290 break;
00291 }
00292 }
00293 if ( i == in->width)
00294 {
00295 wrapHeight = true;
00296 }
00297
00298
00299 for ( i = 0 ; i < in->width ; i++ )
00300 {
00301 for ( j = 0 ; j < in->height ; j++ )
00302 {
00303 count = 0;
00304
00305 dv = &in->ctrl[i][j];
00306 VectorCopy( dv->xyz, base );
00307 for ( k = 0 ; k < 8 ; k++ )
00308 {
00309 VectorClear( around[k] );
00310 good[k] = false;
00311
00312 for ( dist = 1 ; dist <= 3 ; dist++ )
00313 {
00314 x = i + neighbors[k][0] * dist;
00315 y = j + neighbors[k][1] * dist;
00316 if ( wrapWidth )
00317 {
00318 if ( x < 0 )
00319 {
00320 x = in->width - 1 + x;
00321 }
00322 else if ( x >= in->width )
00323 {
00324 x = 1 + x - in->width;
00325 }
00326 }
00327 if ( wrapHeight )
00328 {
00329 if ( y < 0 )
00330 {
00331 y = in->height - 1 + y;
00332 }
00333 else if ( y >= in->height )
00334 {
00335 y = 1 + y - in->height;
00336 }
00337 }
00338
00339 if ( x < 0 || x >= in->width || y < 0 || y >= in->height )
00340 {
00341 break;
00342 }
00343
00344 VectorSubtract( in->ctrl[x][y].xyz, base, temp );
00345 if ( __VectorNormalize( temp, temp ) == 0 )
00346 {
00347 continue;
00348 }
00349 else
00350 {
00351 good[k] = true;
00352 VectorCopy( temp, around[k] );
00353 break;
00354 }
00355 }
00356 }
00357
00358 VectorClear( sum );
00359 for ( k = 0 ; k < 8 ; k++ )
00360 {
00361 if ( !good[k] || !good[(k+1)&7] )
00362 {
00363 continue;
00364 }
00365 CrossProduct( around[(k+1)&7], around[k], normal );
00366 if ( __VectorNormalize( normal, normal ) == 0 )
00367 {
00368 continue;
00369 }
00370 VectorAdd( normal, sum, sum );
00371 count++;
00372 }
00373 if ( count == 0 )
00374 {
00375
00376 count = 1;
00377
00378 }
00379 __VectorNormalize( sum, dv->normal );
00380 }
00381 }
00382 }
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392 void Patch_CalcBounds(patchMesh_t *p, vec3_t& vMin, vec3_t& vMax)
00393 {
00394 vMin[0] = vMin[1] = vMin[2] = 99999;
00395 vMax[0] = vMax[1] = vMax[2] = -99999;
00396
00397 p->bDirty = true;
00398 for (int w = 0; w < p->width; w++)
00399 {
00400 for (int h = 0; h < p->height; h++)
00401 {
00402 for (int j = 0; j < 3; j++)
00403 {
00404 float f = p->ctrl[w][h].xyz[j];
00405 if (f < vMin[j])
00406 vMin[j] = f;
00407 if (f > vMax[j])
00408 vMax[j] = f;
00409 }
00410 }
00411 }
00412 }
00413
00414
00415
00416
00417
00418
00419 void Brush_RebuildBrush(brush_t *b, vec3_t vMins, vec3_t vMaxs)
00420 {
00421
00422
00423
00424 int i, j;
00425 face_t *f, *next;
00426 vec3_t pts[4][2];
00427 texdef_t texdef;
00428
00429
00430 for (j = 0; j < 3; j++)
00431 {
00432 if ((int)vMins[j] == (int)vMaxs[j])
00433 {
00434 vMins[j] -= 4;
00435 vMaxs[j] += 4;
00436 }
00437 }
00438
00439
00440 for (f=b->brush_faces ; f ; f=next)
00441 {
00442 next = f->next;
00443 if (f)
00444 texdef = f->texdef;
00445 Face_Free( f );
00446 }
00447
00448 b->brush_faces = NULL;
00449
00450
00451
00452 for (i=0 ; i<3 ; i++)
00453 if (vMaxs[i] < vMins[i])
00454 Error ("Brush_RebuildBrush: backwards");
00455
00456 pts[0][0][0] = vMins[0];
00457 pts[0][0][1] = vMins[1];
00458
00459 pts[1][0][0] = vMins[0];
00460 pts[1][0][1] = vMaxs[1];
00461
00462 pts[2][0][0] = vMaxs[0];
00463 pts[2][0][1] = vMaxs[1];
00464
00465 pts[3][0][0] = vMaxs[0];
00466 pts[3][0][1] = vMins[1];
00467
00468 for (i=0 ; i<4 ; i++)
00469 {
00470 pts[i][0][2] = vMins[2];
00471 pts[i][1][0] = pts[i][0][0];
00472 pts[i][1][1] = pts[i][0][1];
00473 pts[i][1][2] = vMaxs[2];
00474 }
00475
00476 for (i=0 ; i<4 ; i++)
00477 {
00478 f = Face_Alloc();
00479 f->texdef = texdef;
00480 f->texdef.flags &= ~SURF_KEEP;
00481 f->texdef.contents &= ~CONTENTS_KEEP;
00482 if ( b->patchBrush )
00483 {
00484 f->texdef.flags |= SURF_PATCH;
00485 }
00486 f->next = b->brush_faces;
00487 b->brush_faces = f;
00488 j = (i+1)%4;
00489
00490 VectorCopy (pts[j][1], f->planepts[0]);
00491 VectorCopy (pts[i][1], f->planepts[1]);
00492 VectorCopy (pts[i][0], f->planepts[2]);
00493 }
00494
00495 f = Face_Alloc();
00496 f->texdef = texdef;
00497 f->texdef.flags &= ~SURF_KEEP;
00498 f->texdef.contents &= ~CONTENTS_KEEP;
00499 if ( b->patchBrush )
00500 {
00501 f->texdef.flags |= SURF_PATCH;
00502 }
00503 f->next = b->brush_faces;
00504 b->brush_faces = f;
00505
00506 VectorCopy (pts[0][1], f->planepts[0]);
00507 VectorCopy (pts[1][1], f->planepts[1]);
00508 VectorCopy (pts[2][1], f->planepts[2]);
00509
00510 f = Face_Alloc();
00511 f->texdef = texdef;
00512 f->texdef.flags &= ~SURF_KEEP;
00513 f->texdef.contents &= ~CONTENTS_KEEP;
00514 if ( b->patchBrush )
00515 {
00516 f->texdef.flags |= SURF_PATCH;
00517 }
00518 f->next = b->brush_faces;
00519 b->brush_faces = f;
00520
00521 VectorCopy (pts[2][0], f->planepts[0]);
00522 VectorCopy (pts[1][0], f->planepts[1]);
00523 VectorCopy (pts[0][0], f->planepts[2]);
00524
00525 Brush_Build(b);
00526 }
00527
00528 void WINAPI Patch_Rebuild(patchMesh_t *p)
00529 {
00530 vec3_t vMin, vMax;
00531 Patch_CalcBounds(p, vMin, vMax);
00532 Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
00533 p->bDirty = true;
00534 }
00535
00536
00537
00538
00539
00540
00541
00542 brush_t* AddBrushForPatch(patchMesh_t *pm, bool bLinkToWorld )
00543 {
00544
00545 vec3_t vMin, vMax;
00546 Patch_CalcBounds(pm, vMin, vMax);
00547
00548 for (int j = 0; j < 3; j++)
00549 {
00550 if (vMin[j] == vMax[j])
00551 {
00552 vMin[j] -= 4;
00553 vMax[j] += 4;
00554 }
00555 }
00556
00557 brush_t *b = Brush_Create(vMin, vMax, &g_qeglobals.d_texturewin.texdef);
00558 face_t *f;
00559 for (f=b->brush_faces ; f ; f=f->next)
00560 {
00561 f->texdef.flags |= SURF_PATCH;
00562 }
00563
00564
00565 b->pPatch = pm;
00566 pm->pSymbiot = b;
00567 pm->bSelected = false;
00568 pm->bOverlay = false;
00569 pm->bDirty = true;
00570 pm->nListID = -1;
00571
00572 if (bLinkToWorld)
00573 {
00574 Brush_AddToList (b, &active_brushes);
00575 Entity_LinkBrush (world_entity, b);
00576 Brush_Build(b);
00577 }
00578
00579 return b;
00580 }
00581
00582 void Patch_SetPointIntensities(int n)
00583 {
00584 #if 0
00585 patchMesh_t *p = patchMeshes[n];
00586 for (int i = 0; i < p->width; i++)
00587 {
00588 for (int j = 0; j < p->height; j++)
00589 {
00590
00591 }
00592 }
00593 #endif
00594 }
00595
00596
00597
00598
00599
00600
00601
00602
00603 float Patch_Width(patchMesh_t *p)
00604 {
00605 float f = 0;
00606 for (int i = 0; i < p->width-1; i++)
00607 {
00608 vec3_t vTemp;
00609 VectorSubtract(p->ctrl[i][0].xyz, p->ctrl[i+1][0].xyz, vTemp);
00610 f += VectorLength(vTemp);
00611 }
00612 return f;
00613 }
00614
00615 float Patch_WidthDistanceTo(patchMesh_t *p, int j)
00616 {
00617 float f = 0;
00618 for (int i = 0; i < j; i++)
00619 {
00620 vec3_t vTemp;
00621 VectorSubtract(p->ctrl[i][0].xyz, p->ctrl[i+1][0].xyz, vTemp);
00622 f += VectorLength(vTemp);
00623 }
00624 return f;
00625 }
00626
00627
00628
00629
00630
00631
00632
00633
00634 float Patch_Height(patchMesh_t *p)
00635 {
00636 float f = 0;
00637 for (int i = 0; i < p->height-1; i++)
00638 {
00639 vec3_t vTemp;
00640 VectorSubtract(p->ctrl[0][i].xyz, p->ctrl[0][i+1].xyz, vTemp);
00641 f += VectorLength(vTemp);
00642 }
00643 return f;
00644 }
00645
00646 float Patch_HeightDistanceTo(patchMesh_t *p, int j)
00647 {
00648 float f = 0;
00649 for (int i = 0; i < j; i++)
00650 {
00651 vec3_t vTemp;
00652 VectorSubtract(p->ctrl[0][i].xyz, p->ctrl[0][i+1].xyz, vTemp);
00653 f += VectorLength(vTemp);
00654 }
00655 return f;
00656 }
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668 void Patch_Naturalize(patchMesh_t *p)
00669 {
00670 int nWidth = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? p->d_texture->width * 0.5 : p->d_texture->width;
00671 int nHeight = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? p->d_texture->height * 0.5 : p->d_texture->height;
00672 float fPWidth = Patch_Width(p);
00673 float fPHeight = Patch_Height(p);
00674 float xAccum = 0;
00675 for ( int i = 0 ; i < p->width ; i++ )
00676 {
00677 float yAccum = 0;
00678 for ( int j = 0 ; j < p->height ; j++ )
00679 {
00680 p->ctrl[i][j].st[0] = (fPWidth / nWidth) * xAccum / fPWidth;
00681 p->ctrl[i][j].st[1] = (fPHeight / nHeight) * yAccum / fPHeight;
00682 yAccum = Patch_HeightDistanceTo(p,j+1);
00683
00684
00685 }
00686 xAccum = Patch_WidthDistanceTo(p,i+1);
00687 }
00688 p->bDirty = true;
00689 }
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712 int Index3By[][2] =
00713 {
00714 {0,0},
00715 {1,0},
00716 {2,0},
00717 {2,1},
00718 {2,2},
00719 {1,2},
00720 {0,2},
00721 {0,1},
00722 {0,0},
00723 {0,0},
00724 {0,0},
00725 {0,0},
00726 {0,0},
00727 {0,0},
00728 {0,0}
00729 };
00730
00731 int Index5By[][2] =
00732 {
00733 {0,0},
00734 {1,0},
00735 {2,0},
00736 {3,0},
00737 {4,0},
00738 {4,1},
00739 {4,2},
00740 {4,3},
00741 {4,4},
00742 {3,4},
00743 {2,4},
00744 {1,4},
00745 {0,4},
00746 {0,3},
00747 {0,2},
00748 {0,1}
00749 };
00750
00751
00752
00753 int Interior3By[][2] =
00754 {
00755 {1,1}
00756 };
00757
00758 int Interior5By[][2] =
00759 {
00760 {1,1},
00761 {2,1},
00762 {3,1},
00763 {1,2},
00764 {2,2},
00765 {3,2},
00766 {1,3},
00767 {2,3},
00768 {3,3}
00769 };
00770
00771 int Interior3ByCount = sizeof(Interior3By) / sizeof(int[2]);
00772 int Interior5ByCount = sizeof(Interior5By) / sizeof(int[2]);
00773
00774 face_t* Patch_GetAxisFace(patchMesh_t *p)
00775 {
00776 face_t *f = NULL;
00777 vec3_t vTemp;
00778 brush_t *b = p->pSymbiot;
00779
00780 for (f = b->brush_faces ; f ; f = f->next)
00781 {
00782 VectorSubtract(f->face_winding->points[1], f->face_winding->points[0], vTemp);
00783 int nScore = 0;
00784
00785
00786
00787 for (int j = 0; j < 3; j++)
00788 {
00789 if (vTemp[j] > 8)
00790 nScore++;
00791 }
00792
00793 if (nScore > 0)
00794 break;
00795 }
00796
00797 if (f == NULL)
00798 f = b->brush_faces;
00799 return f;
00800 }
00801
00802 int g_nFaceCycle = 0;
00803
00804 face_t* nextFace(patchMesh_t *p)
00805 {
00806 brush_t *b = p->pSymbiot;
00807 face_t *f = NULL;
00808 int n = 0;
00809 for (f = b->brush_faces ; f && n <= g_nFaceCycle; f = f->next)
00810 {
00811 n++;
00812 }
00813 g_nFaceCycle++;
00814 if (g_nFaceCycle > 5)
00815 {
00816 g_nFaceCycle =0;
00817 f = b->brush_faces;
00818 }
00819
00820 return f;
00821 }
00822
00823
00824 extern void EmitTextureCoordinates ( float *xyzst, qtexture_t *q, face_t *f);
00825 void Patch_CapTexture(patchMesh_t *p, bool bFaceCycle = false)
00826 {
00827 Patch_MeshNormals(p);
00828 face_t *f = (bFaceCycle) ? nextFace(p) : Patch_GetAxisFace(p);
00829 vec3_t vSave;
00830 VectorCopy(f->plane.normal, vSave);
00831
00832 float fRotate = f->texdef.rotate;
00833 f->texdef.rotate = 0;
00834 float fScale[2];
00835 fScale[0] = f->texdef.scale[0];
00836 fScale[1] = f->texdef.scale[1];
00837 f->texdef.scale[0] = 0.5;
00838 f->texdef.scale[1] = 0.5;
00839 float fShift[2];
00840 fShift[0] = f->texdef.shift[0];
00841 fShift[1] = f->texdef.shift[1];
00842 f->texdef.shift[0] = 0;
00843 f->texdef.shift[1] = 0;
00844
00845 for (int i = 0; i < p->width; i++)
00846 {
00847 for (int j = 0; j < p->height; j++)
00848 {
00849 if (!bFaceCycle)
00850 {
00851 VectorCopy(p->ctrl[i][j].normal, f->plane.normal);
00852 }
00853 EmitTextureCoordinates( p->ctrl[i][j].xyz, f->d_texture, f);
00854 }
00855 }
00856 VectorCopy(vSave, f->plane.normal);
00857 f->texdef.rotate = fRotate;
00858 f->texdef.scale[0] = fScale[0];
00859 f->texdef.scale[1] = fScale[1];
00860 f->texdef.shift[0] = fShift[0];
00861 f->texdef.shift[1] = fShift[1];
00862 p->bDirty = true;
00863 }
00864
00865 void FillPatch(patchMesh_t *p, vec3_t v)
00866 {
00867 for (int i = 0; i < p->width; i++)
00868 {
00869 for (int j = 0; j < p->height; j++)
00870 {
00871 VectorCopy(v, p->ctrl[i][j].xyz);
00872 }
00873 }
00874 }
00875
00876 brush_t* Cap(patchMesh_t *pParent, bool bByColumn, bool bFirst)
00877 {
00878 brush_t *b;
00879 patchMesh_t *p;
00880 vec3_t vMin, vMax;
00881 int i, j;
00882
00883 bool bSmall = true;
00884
00885 if (pParent->width <= 9)
00886 {
00887 b = Patch_GenericMesh(3, 3, 2, false);
00888 }
00889 else
00890 {
00891 b = Patch_GenericMesh(5, 5, 2, false);
00892 bSmall = false;
00893 }
00894
00895 if (!b)
00896 {
00897 Sys_Printf("Unable to cap. You may need to ungroup the patch.\n");
00898 return NULL;
00899 }
00900
00901 p = b->pPatch;
00902 p->type |= PATCH_CAP;
00903
00904 vMin[0] = vMin[1] = vMin[2] = 9999;
00905 vMax[0] = vMax[1] = vMax[2] = -9999;
00906
00907
00908
00909 int nSize = (bByColumn) ? pParent->width : pParent->height;
00910 int nIndex = (bFirst) ? 0 : (bByColumn) ? pParent->height-1 : pParent->width-1;
00911
00912 FillPatch(p, pParent->ctrl[0][nIndex].xyz);
00913
00914 for (i = 0; i < nSize; i++)
00915 {
00916 if (bByColumn)
00917 {
00918 if (bSmall)
00919 {
00920 VectorCopy(pParent->ctrl[i][nIndex].xyz, p->ctrl[Index3By[i][0]][Index3By[i][1]].xyz);
00921 }
00922 else
00923 {
00924 VectorCopy(pParent->ctrl[i][nIndex].xyz, p->ctrl[Index5By[i][0]][Index5By[i][1]].xyz);
00925 }
00926 }
00927 else
00928 {
00929 if (bSmall)
00930 {
00931 VectorCopy(pParent->ctrl[nIndex][i].xyz, p->ctrl[Index3By[i][0]][Index3By[i][1]].xyz);
00932 }
00933 else
00934 {
00935 VectorCopy(pParent->ctrl[nIndex][i].xyz, p->ctrl[Index5By[i][0]][Index5By[i][1]].xyz);
00936 }
00937 }
00938
00939 for (j = 0; j < 3; j++)
00940 {
00941 float f = (bSmall) ? p->ctrl[Index3By[i][0]][Index3By[i][1]].xyz[j] : p->ctrl[Index5By[i][0]][Index5By[i][1]].xyz[j];
00942 if (f < vMin[j])
00943 vMin[j] = f;
00944 if (f > vMax[j])
00945 vMax[j] = f;
00946 }
00947 }
00948
00949 vec3_t vTemp;
00950 for (j = 0; j < 3; j++)
00951 {
00952 vTemp[j] = vMin[j] + abs((vMax[j] - vMin[j]) * 0.5);
00953 }
00954
00955 int nCount = (bSmall) ? Interior3ByCount : Interior5ByCount;
00956 for (j = 0; j < nCount; j++)
00957 {
00958 if (bSmall)
00959 {
00960 VectorCopy(vTemp, p->ctrl[Interior3By[j][0]][Interior3By[j][1]].xyz);
00961 }
00962 else
00963 {
00964 VectorCopy(vTemp, p->ctrl[Interior5By[j][0]][Interior5By[j][1]].xyz);
00965 }
00966 }
00967
00968 if (bFirst)
00969 {
00970 drawVert_t vertTemp;
00971 for (i = 0; i < p->width; i++)
00972 {
00973 for (j = 0; j < p->height / 2; j++)
00974 {
00975 memcpy(&vertTemp, &p->ctrl[i][p->height - 1- j], sizeof (drawVert_t));
00976 memcpy(&p->ctrl[i][p->height - 1 - j], &p->ctrl[i][j], sizeof(drawVert_t));
00977 memcpy(&p->ctrl[i][j], &vertTemp, sizeof(drawVert_t));
00978 }
00979 }
00980 }
00981
00982 Patch_Rebuild(p);
00983 Patch_CapTexture(p);
00984 return p->pSymbiot;
00985 }
00986
00987 brush_t* CapSpecial(patchMesh_t *pParent, int nType, bool bFirst)
00988 {
00989 brush_t *b;
00990 patchMesh_t *p;
00991 vec3_t vMin, vMax, vTemp;
00992 int i, j;
00993
00994 if (nType == CCapDialog::IENDCAP)
00995 b = Patch_GenericMesh(5, 3, 2, false);
00996 else
00997 b = Patch_GenericMesh(3, 3, 2, false);
00998
00999 if (!b)
01000 {
01001 Sys_Printf("Unable to cap. Make sure you ungroup before re-capping.");
01002 return NULL;
01003 }
01004
01005 p = b->pPatch;
01006 p->type |= PATCH_CAP;
01007
01008 vMin[0] = vMin[1] = vMin[2] = 9999;
01009 vMax[0] = vMax[1] = vMax[2] = -9999;
01010
01011 int nSize = pParent->width;
01012 int nIndex = (bFirst) ? 0 : pParent->height-1;
01013
01014
01015 Patch_CalcBounds(pParent, vMin, vMax);
01016
01017 for (j = 0; j < 3; j++)
01018 {
01019 vTemp[j] = vMin[j] + abs((vMax[j] - vMin[j]) * 0.5);
01020 }
01021
01022 if (nType == CCapDialog::IBEVEL)
01023 {
01024 VectorCopy(pParent->ctrl[0][nIndex].xyz, p->ctrl[0][0].xyz);
01025 VectorCopy(pParent->ctrl[2][nIndex].xyz, p->ctrl[0][2].xyz);
01026 VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[0][1].xyz);
01027 VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[2][2].xyz);
01028 VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[1][0].xyz);
01029 VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[1][1].xyz);
01030 VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[1][2].xyz);
01031 VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[2][0].xyz);
01032 VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[2][1].xyz);
01033 }
01034 else if (nType == CCapDialog::BEVEL)
01035 {
01036 vec3_t p1, p2, p3, p4, temp, dir;
01037
01038 VectorCopy(pParent->ctrl[0][nIndex].xyz, p3);
01039 VectorCopy(pParent->ctrl[1][nIndex].xyz, p1);
01040 VectorCopy(pParent->ctrl[2][nIndex].xyz, p2);
01041
01042 VectorSubtract(p3, p2, dir);
01043 VectorNormalize(dir);
01044 VectorSubtract(p1, p2, temp);
01045 vec_t dist = _DotProduct(temp, dir);
01046
01047 VectorScale(dir, dist, temp);
01048
01049 VectorAdd(p2, temp, temp);
01050
01051 VectorSubtract(temp, p1, temp);
01052 VectorScale(temp, 2, temp);
01053 VectorAdd(p1, temp, p4);
01054
01055 VectorCopy(p4, p->ctrl[0][0].xyz);
01056 VectorCopy(p4, p->ctrl[1][0].xyz);
01057 VectorCopy(p4, p->ctrl[0][1].xyz);
01058 VectorCopy(p4, p->ctrl[1][1].xyz);
01059 VectorCopy(p4, p->ctrl[0][2].xyz);
01060 VectorCopy(p4, p->ctrl[1][2].xyz);
01061 VectorCopy(p3, p->ctrl[2][0].xyz);
01062 VectorCopy(p1, p->ctrl[2][1].xyz);
01063 VectorCopy(p2, p->ctrl[2][2].xyz);
01064
01065 }
01066 else if (nType == CCapDialog::ENDCAP)
01067 {
01068 VectorAdd(pParent->ctrl[4][nIndex].xyz, pParent->ctrl[0][nIndex].xyz, vTemp);
01069 VectorScale(vTemp, 0.5, vTemp);
01070 VectorCopy(pParent->ctrl[0][nIndex].xyz, p->ctrl[0][0].xyz);
01071 VectorCopy(vTemp, p->ctrl[1][0].xyz);
01072 VectorCopy(pParent->ctrl[4][nIndex].xyz, p->ctrl[2][0].xyz);
01073
01074 VectorCopy(pParent->ctrl[2][nIndex].xyz, p->ctrl[0][2].xyz);
01075 VectorCopy(pParent->ctrl[2][nIndex].xyz, p->ctrl[1][2].xyz);
01076 VectorCopy(pParent->ctrl[2][nIndex].xyz, p->ctrl[2][2].xyz);
01077 VectorCopy(pParent->ctrl[2][nIndex].xyz, p->ctrl[1][1].xyz);
01078
01079 VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[0][1].xyz);
01080 VectorCopy(pParent->ctrl[3][nIndex].xyz, p->ctrl[2][1].xyz);
01081 }
01082 else
01083 {
01084 VectorCopy(pParent->ctrl[0][nIndex].xyz, p->ctrl[0][0].xyz);
01085 VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[1][0].xyz);
01086 VectorCopy(pParent->ctrl[2][nIndex].xyz, p->ctrl[2][0].xyz);
01087 VectorCopy(pParent->ctrl[3][nIndex].xyz, p->ctrl[3][0].xyz);
01088 VectorCopy(pParent->ctrl[4][nIndex].xyz, p->ctrl[4][0].xyz);
01089
01090 VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[0][1].xyz);
01091 VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[1][1].xyz);
01092 VectorCopy(pParent->ctrl[2][nIndex].xyz, p->ctrl[2][1].xyz);
01093 VectorCopy(pParent->ctrl[3][nIndex].xyz, p->ctrl[3][1].xyz);
01094 VectorCopy(pParent->ctrl[3][nIndex].xyz, p->ctrl[4][1].xyz);
01095
01096 VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[0][2].xyz);
01097 VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[1][2].xyz);
01098 VectorCopy(pParent->ctrl[2][nIndex].xyz, p->ctrl[2][2].xyz);
01099 VectorCopy(pParent->ctrl[3][nIndex].xyz, p->ctrl[3][2].xyz);
01100 VectorCopy(pParent->ctrl[3][nIndex].xyz, p->ctrl[4][2].xyz);
01101 }
01102
01103
01104 bool bEndCap = (nType == CCapDialog::ENDCAP || nType == CCapDialog::IENDCAP);
01105 if ((!bFirst && !bEndCap) || (bFirst && bEndCap))
01106 {
01107 drawVert_t vertTemp;
01108 for (i = 0; i < p->width; i++)
01109 {
01110 for (j = 0; j < p->height / 2; j++)
01111 {
01112 memcpy(&vertTemp, &p->ctrl[i][p->height - 1- j], sizeof (drawVert_t));
01113 memcpy(&p->ctrl[i][p->height - 1 - j], &p->ctrl[i][j], sizeof(drawVert_t));
01114 memcpy(&p->ctrl[i][j], &vertTemp, sizeof(drawVert_t));
01115 }
01116 }
01117 }
01118
01119
01120
01121 Patch_Rebuild(p);
01122 Patch_CapTexture(p);
01123 return p->pSymbiot;
01124 }
01125
01126
01127 void Patch_CapCurrent(bool bInvertedBevel, bool bInvertedEndcap)
01128 {
01129 patchMesh_t *pParent = NULL;
01130 brush_t *b[4];
01131 brush_t *pCap = NULL;
01132 b[0] = b[1] = b[2] = b[3] = NULL;
01133 int nIndex = 0;
01134
01135 if (!QE_SingleBrush())
01136 {
01137 Sys_Printf("Cannot cap multiple selection. Please select a single patch.\n");
01138 return;
01139 }
01140
01141
01142 for (brush_t *pb = selected_brushes.next ; pb != NULL && pb != &selected_brushes ; pb = pb->next)
01143 {
01144 if (pb->patchBrush)
01145 {
01146 pParent = pb->pPatch;
01147
01148
01149
01150
01151 if (VectorCompare(pParent->ctrl[0][0].xyz, pParent->ctrl[pParent->width-1][0].xyz))
01152 {
01153 pCap = Cap(pParent, true, false);
01154 if (pCap != NULL)
01155 {
01156 b[nIndex++] = pCap;
01157 }
01158 }
01159 if (VectorCompare(pParent->ctrl[0][pParent->height-1].xyz, pParent->ctrl[pParent->width-1][pParent->height-1].xyz))
01160 {
01161 pCap = Cap(pParent, true, true);
01162 if (pCap != NULL)
01163 {
01164 b[nIndex++] = pCap;
01165 }
01166 }
01167 if (VectorCompare(pParent->ctrl[0][0].xyz, pParent->ctrl[0][pParent->height-1].xyz))
01168 {
01169 pCap = Cap(pParent, false, false);
01170 if (pCap != NULL)
01171 {
01172 b[nIndex++] = pCap;
01173 }
01174 }
01175 if (VectorCompare(pParent->ctrl[pParent->width-1][0].xyz, pParent->ctrl[pParent->width-1][pParent->height-1].xyz))
01176 {
01177 pCap = Cap(pParent, false, true);
01178 if (pCap != NULL)
01179 {
01180 b[nIndex++] = pCap;
01181 }
01182 }
01183 }
01184 }
01185
01186 if (pParent)
01187 {
01188
01189 if (nIndex == 0)
01190 {
01191 CCapDialog dlg;
01192 if (dlg.DoModal() == IDOK)
01193 {
01194 b[nIndex++] = CapSpecial(pParent, dlg.getCapType(), false);
01195 b[nIndex++] = CapSpecial(pParent, dlg.getCapType(), true);
01196 }
01197 }
01198
01199 if (nIndex > 0)
01200 {
01201 while (nIndex > 0)
01202 {
01203 nIndex--;
01204 if (b[nIndex])
01205 {
01206 Select_Brush(b[nIndex]);
01207 }
01208 }
01209 eclass_t *pecNew = Eclass_ForName("func_group", false);
01210 if (pecNew)
01211 {
01212 entity_t *e = Entity_Create(pecNew);
01213 SetKeyValue(e, "type", "patchCapped");
01214 }
01215 }
01216 }
01217 }
01218
01219
01220
01221
01222 void GenerateEndCaps(brush_t *brushParent, bool bBevel, bool bEndcap, bool bInverted)
01223 {
01224 brush_t *b, *b2;
01225 patchMesh_t *p, *p2, *pParent;
01226 vec3_t vTemp, vMin, vMax;
01227 int i, j;
01228
01229 pParent = brushParent->pPatch;
01230
01231 Patch_CalcBounds(pParent, vMin, vMax);
01232
01233
01234 if (pParent->width > 9)
01235 b = Patch_GenericMesh(5, 3, 2, false);
01236 else
01237 b = Patch_GenericMesh(3, 3, 2, false);
01238 p = b->pPatch;
01239
01240 vMin[0] = vMin[1] = vMin[2] = 9999;
01241 vMax[0] = vMax[1] = vMax[2] = -9999;
01242
01243 for (i = 0; i < pParent->width; i++)
01244 {
01245 VectorCopy(pParent->ctrl[i][0].xyz, p->ctrl[Index3By[i][0]][Index3By[i][1]].xyz);
01246 for (j = 0; j < 3; j++)
01247 {
01248 if (pParent->ctrl[i][0].