00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "stdafx.h"
00025 #include <assert.h>
00026 #include "qe3.h"
00027 #include "winding.h"
00028
00029
00030
00031
00032 int g_nBrushId = 0;
00033
00034 const char* Brush_Name(brush_t *b)
00035 {
00036 static char cBuff[1024];
00037 b->numberId = g_nBrushId++;
00038 if (g_qeglobals.m_bBrushPrimitMode)
00039 {
00040 sprintf(cBuff, "Brush %i", b->numberId);
00041 Brush_SetEpair(b, "Name", cBuff);
00042 }
00043 return cBuff;
00044 }
00045
00046 brush_t *Brush_Alloc()
00047 {
00048 brush_t *b = (brush_t*)qmalloc(sizeof(brush_t));
00049 return b;
00050 }
00051
00052
00053
00054
00055 void PrintWinding (winding_t *w)
00056 {
00057 int i;
00058
00059 printf ("-------------\n");
00060 for (i=0 ; i<w->numpoints ; i++)
00061 printf ("(%5.2f, %5.2f, %5.2f)\n", w->points[i][0]
00062 , w->points[i][1], w->points[i][2]);
00063 }
00064
00065 void PrintPlane (plane_t *p)
00066 {
00067 printf ("(%5.2f, %5.2f, %5.2f) : %5.2f\n", p->normal[0], p->normal[1],
00068 p->normal[2], p->dist);
00069 }
00070
00071 void PrintVector (vec3_t v)
00072 {
00073 printf ("(%5.2f, %5.2f, %5.2f)\n", v[0], v[1], v[2]);
00074 }
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 vec3_t baseaxis[18] =
00092 {
00093 {0,0,1}, {1,0,0}, {0,-1,0},
00094 {0,0,-1}, {1,0,0}, {0,-1,0},
00095 {1,0,0}, {0,1,0}, {0,0,-1},
00096 {-1,0,0}, {0,1,0}, {0,0,-1},
00097 {0,1,0}, {1,0,0}, {0,0,-1},
00098 {0,-1,0}, {1,0,0}, {0,0,-1}
00099 };
00100
00101 void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv)
00102 {
00103 int bestaxis;
00104 float dot,best;
00105 int i;
00106
00107 best = 0;
00108 bestaxis = 0;
00109
00110 for (i=0 ; i<6 ; i++)
00111 {
00112 dot = DotProduct (pln->normal, baseaxis[i*3]);
00113 if (dot > best)
00114 {
00115 best = dot;
00116 bestaxis = i;
00117 }
00118 }
00119
00120 VectorCopy (baseaxis[bestaxis*3+1], xv);
00121 VectorCopy (baseaxis[bestaxis*3+2], yv);
00122 }
00123
00124
00125
00126 float lightaxis[3] = {0.6, 0.8, 1.0};
00127
00128
00129
00130
00131
00132
00133
00134
00135 float SetShadeForPlane (plane_t *p)
00136 {
00137 int i;
00138 float f;
00139
00140
00141 for (i=0 ; i<3 ; i++)
00142 if (fabs(p->normal[i]) > 0.9)
00143 {
00144 f = lightaxis[i];
00145 return f;
00146 }
00147
00148
00149 for (i=0 ; i<3 ; i++)
00150 if (fabs(p->normal[i]) < 0.1)
00151 {
00152 f = (lightaxis[(i+1)%3] + lightaxis[(i+2)%3])/2;
00153 return f;
00154 }
00155
00156
00157 f= (lightaxis[0] + lightaxis[1] + lightaxis[2]) / 3;
00158 return f;
00159 }
00160
00161 vec3_t vecs[2];
00162 float shift[2];
00163
00164
00165
00166
00167
00168
00169 face_t *Face_Alloc( void )
00170 {
00171 face_t *f = (face_t*)qmalloc( sizeof( *f ) );
00172
00173 if (g_qeglobals.bSurfacePropertiesPlugin)
00174 f->pData = static_cast<void *>( g_SurfaceTable.m_pfnTexdefAlloc( f ) );
00175
00176 return f;
00177 }
00178
00179
00180
00181
00182
00183
00184 void Face_Free( face_t *f )
00185 {
00186 assert( f != 0 );
00187
00188 if ( f->face_winding )
00189 {
00190 free( f->face_winding );
00191 f->face_winding = 0;
00192 }
00193
00194 if (g_qeglobals.bSurfacePropertiesPlugin)
00195 {
00196 #ifdef _DEBUG
00197 if ( !f->pData )
00198 {
00199 Sys_Printf("WARNING: unexpected IPluginTexdef is NULL in Face_Free\n");
00200 }
00201 else
00202 #endif
00203 GETPLUGINTEXDEF(f)->DecRef();
00204 }
00205
00206 f->texdef.~texdef_t();;
00207
00208 free( f );
00209 }
00210
00211
00212
00213
00214
00215
00216 face_t *Face_Clone (face_t *f)
00217 {
00218 face_t *n;
00219
00220 n = Face_Alloc();
00221 n->texdef = f->texdef;
00222
00223 memcpy (n->planepts, f->planepts, sizeof(n->planepts));
00224
00225
00226 return n;
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236 face_t *Face_FullClone (face_t *f)
00237 {
00238 face_t *n;
00239
00240 n = Face_Alloc();
00241 n->texdef = f->texdef;
00242 memcpy(n->planepts, f->planepts, sizeof(n->planepts));
00243 memcpy(&n->plane, &f->plane, sizeof(plane_t));
00244 if (f->face_winding)
00245 n->face_winding = Winding_Clone(f->face_winding);
00246 else
00247 n->face_winding = NULL;
00248 n->d_texture = Texture_ForName( n->texdef.name );
00249 return n;
00250 }
00251
00252
00253
00254
00255
00256
00257 void Clamp(float& f, int nClamp)
00258 {
00259 float fFrac = f - static_cast<int>(f);
00260 f = static_cast<int>(f) % nClamp;
00261 f += fFrac;
00262 }
00263
00264
00265
00266
00267
00268
00269 void Face_MoveTexture(face_t *f, vec3_t delta)
00270 {
00271 vec3_t vX, vY;
00272
00273
00274
00275
00276
00277
00278 if (g_qeglobals.m_bBrushPrimitMode)
00279 Face_MoveTexture_BrushPrimit( f, delta );
00280 else
00281 {
00282 TextureAxisFromPlane(&f->plane, vX, vY);
00283
00284 vec3_t vDP, vShift;
00285 vDP[0] = DotProduct(delta, vX);
00286 vDP[1] = DotProduct(delta, vY);
00287
00288 double fAngle = f->texdef.rotate / 180 * Q_PI;
00289 double c = cos(fAngle);
00290 double s = sin(fAngle);
00291
00292 vShift[0] = vDP[0] * c - vDP[1] * s;
00293 vShift[1] = vDP[0] * s + vDP[1] * c;
00294
00295 if (!f->texdef.scale[0])
00296 f->texdef.scale[0] = 1;
00297 if (!f->texdef.scale[1])
00298 f->texdef.scale[1] = 1;
00299
00300 f->texdef.shift[0] -= vShift[0] / f->texdef.scale[0];
00301 f->texdef.shift[1] -= vShift[1] / f->texdef.scale[1];
00302
00303
00304 Clamp(f->texdef.shift[0], f->d_texture->width);
00305 Clamp(f->texdef.shift[1], f->d_texture->height);
00306 }
00307 }
00308
00309
00310
00311
00312
00313
00314 void Face_SetColor (brush_t *b, face_t *f, float fCurveColor)
00315 {
00316 float shade;
00317 qtexture_t *q;
00318
00319 q = f->d_texture;
00320
00321
00322 shade = SetShadeForPlane (&f->plane);
00323 if (g_pParentWnd->GetCamera()->Camera().draw_mode == cd_texture && !b->owner->eclass->fixedsize)
00324 {
00325
00326
00327 f->d_color[0] =
00328 f->d_color[1] =
00329 f->d_color[2] = shade;
00330 }
00331 else
00332 {
00333 f->d_color[0] = shade*q->color[0];
00334 f->d_color[1] = shade*q->color[1];
00335 f->d_color[2] = shade*q->color[2];
00336 }
00337 }
00338
00339
00340
00341
00342
00343
00344
00345 void Face_TextureVectors (face_t *f, float STfromXYZ[2][4])
00346 {
00347 vec3_t pvecs[2];
00348 int sv, tv;
00349 float ang, sinv, cosv;
00350 float ns, nt;
00351 int i,j;
00352 qtexture_t *q;
00353 texdef_t *td;
00354
00355 #ifdef _DEBUG
00356
00357
00358 if (g_qeglobals.m_bBrushPrimitMode && !g_qeglobals.bNeedConvert)
00359 Sys_Printf("Warning : illegal call of Face_TextureVectors in brush primitive mode\n");
00360 #endif
00361
00362 td = &f->texdef;
00363 q = f->d_texture;
00364
00365 memset (STfromXYZ, 0, 8*sizeof(float));
00366
00367 if (!td->scale[0])
00368 td->scale[0] = (g_PrefsDlg.m_bHiColorTextures) ? 0.5 : 1;
00369 if (!td->scale[1])
00370 td->scale[1] = (g_PrefsDlg.m_bHiColorTextures) ? 0.5 : 1;
00371
00372
00373 TextureAxisFromPlane(&f->plane, pvecs[0], pvecs[1]);
00374
00375
00376 if (td->rotate == 0)
00377 { sinv = 0 ; cosv = 1; }
00378 else if (td->rotate == 90)
00379 { sinv = 1 ; cosv = 0; }
00380 else if (td->rotate == 180)
00381 { sinv = 0 ; cosv = -1; }
00382 else if (td->rotate == 270)
00383 { sinv = -1 ; cosv = 0; }
00384 else
00385 {
00386 ang = td->rotate / 180 * Q_PI;
00387 sinv = sin(ang);
00388 cosv = cos(ang);
00389 }
00390
00391 if (pvecs[0][0])
00392 sv = 0;
00393 else if (pvecs[0][1])
00394 sv = 1;
00395 else
00396 sv = 2;
00397
00398 if (pvecs[1][0])
00399 tv = 0;
00400 else if (pvecs[1][1])
00401 tv = 1;
00402 else
00403 tv = 2;
00404
00405 for (i=0 ; i<2 ; i++) {
00406 ns = cosv * pvecs[i][sv] - sinv * pvecs[i][tv];
00407 nt = sinv * pvecs[i][sv] + cosv * pvecs[i][tv];
00408 STfromXYZ[i][sv] = ns;
00409 STfromXYZ[i][tv] = nt;
00410 }
00411
00412
00413 for (i=0 ; i<2 ; i++)
00414 for (j=0 ; j<3 ; j++)
00415 STfromXYZ[i][j] = STfromXYZ[i][j] / td->scale[i];
00416
00417
00418 STfromXYZ[0][3] = td->shift[0];
00419 STfromXYZ[1][3] = td->shift[1];
00420
00421 for (j=0 ; j<4 ; j++) {
00422 STfromXYZ[0][j] /= q->width;
00423 STfromXYZ[1][j] /= q->height;
00424 }
00425 }
00426
00427
00428
00429
00430
00431
00432 void Face_MakePlane (face_t *f)
00433 {
00434 int j;
00435 vec3_t t1, t2, t3;
00436
00437
00438 for (j=0 ; j<3 ; j++)
00439 {
00440 t1[j] = f->planepts[0][j] - f->planepts[1][j];
00441 t2[j] = f->planepts[2][j] - f->planepts[1][j];
00442 t3[j] = f->planepts[1][j];
00443 }
00444
00445 CrossProduct(t1,t2, f->plane.normal);
00446 if (VectorCompare (f->plane.normal, vec3_origin))
00447 printf ("WARNING: brush plane with no normal\n");
00448 VectorNormalize (f->plane.normal);
00449 f->plane.dist = DotProduct (t3, f->plane.normal);
00450 }
00451
00452
00453
00454
00455
00456
00457 void EmitTextureCoordinates ( float *xyzst, qtexture_t *q, face_t *f)
00458 {
00459 float STfromXYZ[2][4];
00460
00461 Face_TextureVectors (f, STfromXYZ);
00462 xyzst[3] = DotProduct (xyzst, STfromXYZ[0]) + STfromXYZ[0][3];
00463 xyzst[4] = DotProduct (xyzst, STfromXYZ[1]) + STfromXYZ[1][3];
00464 }
00465
00466
00467
00468
00469
00470
00471
00472
00473 void Brush_MakeFacePlanes (brush_t *b)
00474 {
00475 face_t *f;
00476
00477 for (f=b->brush_faces ; f ; f=f->next)
00478 {
00479 Face_MakePlane (f);
00480 }
00481 }
00482
00483
00484
00485
00486
00487
00488 void DrawBrushEntityName (brush_t *b)
00489 {
00490 char *name;
00491
00492
00493
00494
00495 if (!b->owner)
00496 return;
00497
00498 if (b->owner == world_entity)
00499 return;
00500
00501 if (b != b->owner->brushes.onext)
00502 return;
00503
00504
00505 #if 0
00506 if (!(g_qeglobals.d_savedinfo.exclude & EXCLUDE_ANGLES))
00507 {
00508
00509 a = FloatForKey (b->owner, "angle");
00510 if (a)
00511 {
00512 s = sin (a/180*Q_PI);
00513 c = cos (a/180*Q_PI);
00514 for (i=0 ; i<3 ; i++)
00515 mid[i] = (b->mins[i] + b->maxs[i])*0.5;
00516
00517 qglBegin (GL_LINE_STRIP);
00518 qglVertex3fv (mid);
00519 mid[0] += c*8;
00520 mid[1] += s*8;
00521 mid[2] += s*8;
00522 qglVertex3fv (mid);
00523 mid[0] -= c*4;
00524 mid[1] -= s*4;
00525 mid[2] -= s*4;
00526 mid[0] -= s*4;
00527 mid[1] += c*4;
00528 mid[2] += c*4;
00529 qglVertex3fv (mid);
00530 mid[0] += c*4;
00531 mid[1] += s*4;
00532 mid[2] += s*4;
00533 mid[0] += s*4;
00534 mid[1] -= c*4;
00535 mid[2] -= c*4;
00536 qglVertex3fv (mid);
00537 mid[0] -= c*4;
00538 mid[1] -= s*4;
00539 mid[2] -= s*4;
00540 mid[0] += s*4;
00541 mid[1] -= c*4;
00542 mid[2] -= c*4;
00543 qglVertex3fv (mid);
00544 qglEnd ();
00545 }
00546 }
00547 #endif
00548
00549 if (g_qeglobals.d_savedinfo.show_names)
00550 {
00551 name = ValueForKey (b->owner, "classname");
00552 qglRasterPos3f (b->mins[0]+4, b->mins[1]+4, b->mins[2]+4);
00553 qglCallLists (strlen(name), GL_UNSIGNED_BYTE, name);
00554 }
00555 }
00556
00557
00558
00559
00560
00561
00562
00563
00564 winding_t *Brush_MakeFaceWinding (brush_t *b, face_t *face)
00565 {
00566 winding_t *w;
00567 face_t *clip;
00568 plane_t plane;
00569 qboolean past;
00570
00571
00572 w = Winding_BaseForPlane (&face->plane);
00573
00574
00575 past = false;
00576 for (clip = b->brush_faces ; clip && w ; clip=clip->next)
00577 {
00578 if (clip == face)
00579 {
00580 past = true;
00581 continue;
00582 }
00583 if (DotProduct (face->plane.normal, clip->plane.normal) > 0.999
00584 && fabs(face->plane.dist - clip->plane.dist) < 0.01 )
00585 {
00586 if (past)
00587 {
00588 free (w);
00589 return NULL;
00590 }
00591 continue;
00592 }
00593
00594
00595 VectorSubtract (vec3_origin,clip->plane.normal, plane.normal);
00596 plane.dist = -clip->plane.dist;
00597
00598 w = Winding_Clip (w, &plane, false);
00599 if (!w)
00600 return w;
00601 }
00602
00603 if (w->numpoints < 3)
00604 {
00605 free(w);
00606 w = NULL;
00607 }
00608
00609 if (!w)
00610 printf ("unused plane\n");
00611
00612 return w;
00613 }
00614
00615
00616
00617
00618
00619
00620 void Brush_SnapPlanepts (brush_t *b)
00621 {
00622 int i, j;
00623 face_t *f;
00624
00625 if (g_PrefsDlg.m_bNoClamp)
00626 return;
00627
00628 for (f=b->brush_faces ; f; f=f->next)
00629 for (i=0 ; i<3 ; i++)
00630 for (j=0 ; j<3 ; j++)
00631 f->planepts[i][j] = floor (f->planepts[i][j] + 0.5);
00632 }
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 void Brush_Build( brush_t *b, bool bSnap, bool bMarkMap, bool bConvert )
00644 {
00645 bool bLocalConvert;
00646
00647 #ifdef _DEBUG
00648 if (!g_qeglobals.m_bBrushPrimitMode && bConvert)
00649 Sys_Printf("Warning : conversion from brush primitive to old brush format not implemented\n");
00650 #endif
00651
00652
00653 if (bConvert && !g_qeglobals.bNeedConvert)
00654 {
00655 bLocalConvert = true;
00656 g_qeglobals.bNeedConvert = true;
00657 }
00658
00659
00660
00661
00662 Brush_BuildWindings(b, bSnap);
00663
00664 Patch_BuildPoints (b);
00665
00666
00667
00668
00669 if (g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_edge)
00670 SetupVertexSelection ();
00671
00672 if (b->itemOwner == NULL)
00673 Group_AddToProperGroup(b);
00674
00675 if (bMarkMap)
00676 {
00677 Sys_MarkMapModified();
00678 }
00679
00680 if (bLocalConvert)
00681 g_qeglobals.bNeedConvert = false;
00682 }
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692 void Brush_SplitBrushByFace (brush_t *in, face_t *f, brush_t **front, brush_t **back)
00693 {
00694 brush_t *b;
00695 face_t *nf;
00696 vec3_t temp;
00697
00698 b = Brush_Clone (in);
00699 nf = Face_Clone (f);
00700
00701 nf->texdef = b->brush_faces->texdef;
00702 nf->next = b->brush_faces;
00703 b->brush_faces = nf;
00704
00705 Brush_Build( b );
00706 Brush_RemoveEmptyFaces ( b );
00707 if ( !b->brush_faces )
00708 {
00709 Brush_Free (b);
00710 *back = NULL;
00711 }
00712 else
00713 {
00714 Entity_LinkBrush (in->owner, b);
00715 *back = b;
00716 }
00717
00718 b = Brush_Clone (in);
00719 nf = Face_Clone (f);
00720
00721 VectorCopy (nf->planepts[0], temp);
00722 VectorCopy (nf->planepts[1], nf->planepts[0]);
00723 VectorCopy (temp, nf->planepts[1]);
00724
00725 nf->texdef = b->brush_faces->texdef;
00726 nf->next = b->brush_faces;
00727 b->brush_faces = nf;
00728
00729 Brush_Build( b );
00730 Brush_RemoveEmptyFaces ( b );
00731 if ( !b->brush_faces )
00732 {
00733 Brush_Free (b);
00734 *front = NULL;
00735 }
00736 else
00737 {
00738 Entity_LinkBrush (in->owner, b);
00739 *front = b;
00740 }
00741 }
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751 face_t *Brush_BestSplitFace(brush_t *b)
00752 {
00753 face_t *face, *f, *bestface;
00754 winding_t *front, *back;
00755 int splits, tinywindings, value, bestvalue;
00756
00757 bestvalue = 999999;
00758 bestface = NULL;
00759 for (face = b->brush_faces; face; face = face->next)
00760 {
00761 splits = 0;
00762 tinywindings = 0;
00763 for (f = b->brush_faces; f; f = f->next)
00764 {
00765 if (f == face) continue;
00766
00767 Winding_SplitEpsilon(f->face_winding, face->plane.normal, face->plane.dist, 0.1, &front, &back);
00768
00769 if (!front)
00770 {
00771 Winding_Free(back);
00772 }
00773 else if (!back)
00774 {
00775 Winding_Free(front);
00776 }
00777 else
00778 {
00779 splits++;
00780 if (Winding_IsTiny(front)) tinywindings++;
00781 if (Winding_IsTiny(back)) tinywindings++;
00782 }
00783 }
00784 if (splits)
00785 {
00786 value = splits + 50 * tinywindings;
00787 if (value < bestvalue)
00788 {
00789 bestvalue = value;
00790 bestface = face;
00791 }
00792 }
00793 }
00794 return bestface;
00795 }
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809 brush_t *Brush_MakeConvexBrushes(brush_t *b)
00810 {
00811 brush_t *front, *back, *end;
00812 face_t *face;
00813
00814 b->next = NULL;
00815 face = Brush_BestSplitFace(b);
00816 if (!face) return b;
00817 Brush_SplitBrushByFace(b, face, &front, &back);
00818
00819 if (!front && !back) return b;
00820 Brush_Free(b);
00821 if (!front)
00822 return Brush_MakeConvexBrushes(back);
00823 b = Brush_MakeConvexBrushes(front);
00824 if (back)
00825 {
00826 for (end = b; end->next; end = end->next);
00827 end->next = Brush_MakeConvexBrushes(back);
00828 }
00829 return b;
00830 }
00831
00832
00833
00834
00835
00836
00837 int Brush_Convex(brush_t *b)
00838 {
00839 face_t *face1, *face2;
00840
00841 for (face1 = b->brush_faces; face1; face1 = face1->next)
00842 {
00843 if (!face1->face_winding) continue;
00844 for (face2 = b->brush_faces; face2; face2 = face2->next)
00845 {
00846 if (face1 == face2) continue;
00847 if (!face2->face_winding) continue;
00848 if (Winding_PlanesConcave(face1->face_winding, face2->face_winding,
00849 face1->plane.normal, face2->plane.normal,
00850 face1->plane.dist, face2->plane.dist))
00851 {
00852 return false;
00853 }
00854 }
00855 }
00856 return true;
00857 }
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876 #define MAX_MOVE_FACES 64
00877 #define INTERSECT_EPSILON 0.1
00878 #define POINT_EPSILON 0.3
00879
00880 int Brush_MoveVertex_old1(brush_t *b, vec3_t vertex, vec3_t delta, vec3_t end, bool bSnap)
00881 {
00882 face_t *f, *face, *newface, *lastface, *nextface;
00883 face_t *movefaces[MAX_MOVE_FACES];
00884 int movefacepoints[MAX_MOVE_FACES];
00885 winding_t *w, tmpw;
00886 int i, j, k, nummovefaces, result;
00887 float dot;
00888
00889 result = false;
00890
00891 tmpw.numpoints = 3;
00892 tmpw.maxpoints = 3;
00893 VectorAdd(vertex, delta, end);
00894
00895 if (bSnap)
00896 for (i = 0; i < 3; i++)
00897 end[i] = floor(end[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
00898
00899
00900 nummovefaces = 0;
00901 for (face = b->brush_faces; face; face = face->next)
00902 {
00903 w = face->face_winding;
00904 if (!w) continue;
00905 for (i = 0; i < w->numpoints; i++)
00906 {
00907 if (Point_Equal(w->points[i], vertex, POINT_EPSILON))
00908 {
00909 if (face->face_winding->numpoints <= 3)
00910 {
00911 movefacepoints[nummovefaces] = i;
00912 movefaces[nummovefaces++] = face;
00913 break;
00914 }
00915 dot = DotProduct(end, face->plane.normal) - face->plane.dist;
00916
00917 if (dot > 0.1)
00918 {
00919
00920 for (k = i; k < i + w->numpoints-3; k++)
00921 {
00922 VectorCopy(w->points[i], tmpw.points[0]);
00923 VectorCopy(w->points[(k+1) % w->numpoints], tmpw.points[1]);
00924 VectorCopy(w->points[(k+2) % w->numpoints], tmpw.points[2]);
00925
00926 newface = Face_Clone(face);
00927
00928 for (f = face; f->original; f = f->original) ;
00929 newface->original = f;
00930
00931 if (newface->face_winding) Winding_Free(newface->face_winding);
00932 newface->face_winding = Winding_Clone(&tmpw);
00933
00934 newface->d_texture = Texture_ForName( newface->texdef.name );
00935
00936 newface->next = b->brush_faces;
00937 b->brush_faces = newface;
00938
00939 movefacepoints[nummovefaces] = 0;
00940 movefaces[nummovefaces++] = newface;
00941 }
00942
00943 VectorCopy(w->points[(i-2+w->numpoints) % w->numpoints], tmpw.points[0]);
00944 VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[1]);
00945 VectorCopy(w->points[i], tmpw.points[2]);
00946 Winding_Free(face->face_winding);
00947 face->face_winding = Winding_Clone(&tmpw);
00948
00949 movefacepoints[nummovefaces] = 2;
00950 movefaces[nummovefaces++] = face;
00951 }
00952 else
00953 {
00954
00955 VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[0]);
00956 VectorCopy(w->points[i], tmpw.points[1]);
00957 VectorCopy(w->points[(i+1) % w->numpoints], tmpw.points[2]);
00958
00959 Winding_RemovePoint(w, i);
00960
00961 Face_SetColor(b, face, 1.0);
00962 for (j = 0; j < w->numpoints; j++)
00963 EmitTextureCoordinates(w->points[j], face->d_texture, face);
00964
00965 newface = Face_Clone(face);
00966
00967 for (f = face; f->original; f = f->original) ;
00968 newface->original = f;
00969
00970 if (newface->face_winding) Winding_Free(newface->face_winding);
00971 newface->face_winding = Winding_Clone(&tmpw);
00972
00973 newface->d_texture = Texture_ForName( newface->texdef.name );
00974
00975 newface->next = b->brush_faces;
00976 b->brush_faces = newface;
00977
00978 movefacepoints[nummovefaces] = 1;
00979 movefaces[nummovefaces++] = newface;
00980 }
00981 break;
00982 }
00983 }
00984 }
00985
00986
00987
00988
00989 int l;
00990 vec3_t p1, p2;
00991 winding_t *w2;
00992 plane_t plane;
00993
00994 face = NULL;
00995 VectorCopy(vertex, tmpw.points[1]);
00996 VectorCopy(end, tmpw.points[2]);
00997 for (face = b->brush_faces; face; face = face->next)
00998 {
00999 for (i = 0; i < nummovefaces; i++)
01000 {
01001 if (face == movefaces[i])
01002 break;
01003 }
01004 if (i < nummovefaces)
01005 continue;
01006
01007 if (Winding_VectorIntersect(face->face_winding, &face->plane, vertex, end, INTERSECT_EPSILON))
01008 break;
01009
01010 if (abs(DotProduct(face->plane.normal, end) - face->plane.dist) < 0.5)
01011 {
01012
01013 if (Winding_PointInside(face->face_winding, &face->plane, end, 0.5))
01014 break;
01015 }
01016 for (i = 0; i < nummovefaces; i++)
01017 {
01018 w = movefaces[i]->face_winding;
01019 j = movefacepoints[i];
01020 for (k = -1; k <= 1; k += 2)
01021 {
01022
01023 VectorCopy(w->points[(j + k + w->numpoints) % w->numpoints], tmpw.points[0]);
01024 if (Winding_VectorIntersect(face->face_winding, &face->plane, tmpw.points[0], end, INTERSECT_EPSILON))
01025 {
01026
01027
01028
01029 }
01030
01031 Winding_Plane(&tmpw, plane.normal, &plane.dist);
01032 w2 = face->face_winding;
01033 for (l = 0; l < w2->numpoints; l++)
01034 {
01035 VectorCopy(w2->points[l], p1);
01036 if (Point_Equal(p1, tmpw.points[0], POINT_EPSILON)) continue;
01037 VectorCopy(w2->points[(l+1) % w2->numpoints], p2);
01038 if (Point_Equal(p2, tmpw.points[0], POINT_EPSILON)) continue;
01039 if (Winding_VectorIntersect(&tmpw, &plane, p1, p2, INTERSECT_EPSILON))
01040 break;
01041 }
01042 if (l < w2->numpoints)
01043 {
01044
01045
01046 break;
01047 }
01048 }
01049 if (k <= 1) break;
01050 }
01051 if (i < nummovefaces)
01052 break;
01053 }
01054 if (!face)
01055 {
01056
01057
01058 for (i = 0; i < nummovefaces; i++)
01059 {
01060 VectorCopy(end, movefaces[i]->face_winding->points[movefacepoints[i]]);
01061
01062 for (j = 0; j < 3; j++)
01063 {
01064 VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
01065 }
01066 Face_MakePlane(movefaces[i]);
01067 }
01068 result = true;
01069 }
01070
01071 for (i = 0; i < nummovefaces; i++)
01072 {
01073 Face_SetColor(b, movefaces[i], 1.0);
01074 for (j = 0; j < movefaces[i]->face_winding->numpoints; j++)
01075 EmitTextureCoordinates(movefaces[i]->face_winding->points[j], movefaces[i]->d_texture, movefaces[i]);
01076 }
01077
01078
01079 lastface = NULL;
01080 for (face = b->brush_faces; face; face = nextface)
01081 {
01082 nextface = face->next;
01083 if (!face->original)
01084 {
01085 lastface = face;
01086 continue;
01087 }
01088 if (!Plane_Equal(&face->plane, &face->original->plane, false))
01089 {
01090 lastface = face;
01091 continue;
01092 }
01093 w = Winding_TryMerge(face->face_winding, face->original->face_winding, face->plane.normal, true);
01094 if (!w)
01095 {
01096 lastface = face;
01097 continue;
01098 }
01099 Winding_Free(face->original->face_winding);
01100 face->original->face_winding = w;
01101
01102 Face_SetColor(b, face->original, 1.0);
01103 for (j = 0; j < face->original->face_winding->numpoints; j++)
01104 EmitTextureCoordinates(face->original->face_winding->points[j], face->original->d_texture, face->original);
01105
01106 if (lastface) lastface->next = face->next;
01107 else b->brush_faces = face->next;
01108 Face_Free(face);
01109 }
01110 return result;
01111 }
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124 #define MAX_MOVE_FACES 64
01125 #define INTERSECT_EPSILON 0.1
01126 #define POINT_EPSILON 0.3
01127
01128 int Brush_MoveVertex_old2(brush_t *b, vec3_t vertex, vec3_t delta, vec3_t end, bool bSnap)
01129 {
01130 face_t *f, *face, *newface, *lastface, *nextface;
01131 face_t *movefaces[MAX_MOVE_FACES];
01132 int movefacepoints[MAX_MOVE_FACES];
01133 winding_t *w, tmpw;
01134 int i, j, k, nummovefaces, result;
01135 float dot;
01136
01137 result = true;
01138
01139 tmpw.numpoints = 3;
01140 tmpw.maxpoints = 3;
01141 VectorAdd(vertex, delta, end);
01142
01143 if (bSnap)
01144 for (i = 0; i < 3; i++)
01145 end[i] = floor(end[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
01146
01147
01148 nummovefaces = 0;
01149 for (face = b->brush_faces; face; face = face->next)
01150 {
01151 w = face->face_winding;
01152 if (!w) continue;
01153 for (i = 0; i < w->numpoints; i++)
01154 {
01155 if (Point_Equal(w->points[i], vertex, POINT_EPSILON))
01156 {
01157 if (face->face_winding->numpoints <= 3)
01158 {
01159 movefacepoints[nummovefaces] = i;
01160 movefaces[nummovefaces++] = face;
01161 break;
01162 }
01163 dot = DotProduct(end, face->plane.normal) - face->plane.dist;
01164
01165 if (dot > 0.1)
01166 {
01167
01168 for (k = i; k < i + w->numpoints-3; k++)
01169 {
01170 VectorCopy(w->points[i], tmpw.points[0]);
01171 VectorCopy(w->points[(k+1) % w->numpoints], tmpw.points[1]);
01172 VectorCopy(w->points[(k+2) % w->numpoints], tmpw.points[2]);
01173
01174 newface = Face_Clone(face);
01175
01176 for (f = face; f->original; f = f->original) ;
01177 newface->original = f;
01178
01179 if (newface->face_winding) Winding_Free(newface->face_winding);
01180 newface->face_winding = Winding_Clone(&tmpw);
01181
01182 newface->d_texture = Texture_ForName( newface->texdef.name );
01183
01184 newface->next = b->brush_faces;
01185 b->brush_faces = newface;
01186
01187 movefacepoints[nummovefaces] = 0;
01188 movefaces[nummovefaces++] = newface;
01189 }
01190
01191 VectorCopy(w->points[(i-2+w->numpoints) % w->numpoints], tmpw.points[0]);
01192 VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[1]);
01193 VectorCopy(w->points[i], tmpw.points[2]);
01194 Winding_Free(face->face_winding);
01195 face->face_winding = Winding_Clone(&tmpw);
01196
01197 movefacepoints[nummovefaces] = 2;
01198 movefaces[nummovefaces++] = face;
01199 }
01200 else
01201 {
01202
01203 VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[0]);
01204 VectorCopy(w->points[i], tmpw.points[1]);
01205 VectorCopy(w->points[(i+1) % w->numpoints], tmpw.points[2]);
01206
01207 Winding_RemovePoint(w, i);
01208
01209 Face_SetColor(b, face, 1.0);
01210 for (j = 0; j < w->numpoints; j++)
01211 EmitTextureCoordinates(w->points[j], face->d_texture, face);
01212
01213 newface = Face_Clone(face);
01214
01215 for (f = face; f->original; f = f->original) ;
01216 newface->original = f;
01217
01218 if (newface->face_winding) Winding_Free(newface->face_winding);
01219 newface->face_winding = Winding_Clone(&tmpw);
01220
01221 newface->d_texture = Texture_ForName( newface->texdef.name );
01222
01223 newface->next = b->brush_faces;
01224 b->brush_faces = newface;
01225
01226 movefacepoints[nummovefaces] = 1;
01227 movefaces[nummovefaces++] = newface;
01228 }
01229 break;
01230 }
01231 }
01232 }
01233
01234
01235
01236
01237 for (i = 0; i < nummovefaces; i++)
01238 {
01239
01240 VectorCopy(end, movefaces[i]->face_winding->points[movefacepoints[i]]);
01241
01242 for (j = 0; j < 3; j++)
01243 {
01244 VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
01245 }
01246 Face_MakePlane(movefaces[i]);
01247 }
01248
01249 if (!Brush_Convex(b))
01250 {
01251 for (i = 0; i < nummovefaces; i++)
01252 {
01253
01254 VectorCopy(vertex, movefaces[i]->face_winding->points[movefacepoints[i]]);
01255
01256 for (j = 0; j < 3; j++)
01257 {
01258 VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
01259 }
01260 Face_MakePlane(movefaces[i]);
01261 }
01262 result = false;
01263 }
01264
01265 for (i = 0; i < nummovefaces; i++)
01266 {
01267 Face_SetColor(b, movefaces[i], 1.0);
01268 for (j = 0; j < movefaces[i]->face_winding->numpoints; j++)
01269 EmitTextureCoordinates(movefaces[i]->face_winding->points[j], movefaces[i]->d_texture, movefaces[i]);
01270 }
01271
01272
01273 lastface = NULL;
01274 for (face = b->brush_faces; face; face = nextface)
01275 {
01276 nextface = face->next;
01277 if (!face->original)
01278 {
01279 lastface = face;
01280 continue;
01281 }
01282 if (!Plane_Equal(&face->plane, &face->original->plane, false))
01283 {
01284 lastface = face;
01285 continue;
01286 }
01287 w = Winding_TryMerge(face->face_winding, face->original->face_winding, face->plane.normal, true);
01288 if (!w)
01289 {
01290 lastface = face;
01291 continue;
01292 }
01293 Winding_Free(face->original->face_winding);
01294 face->original->face_winding = w;
01295
01296 Face_SetColor(b, face->original, 1.0);
01297 for (j = 0; j < face->original->face_winding->numpoints; j++)
01298 EmitTextureCoordinates(face->original->face_winding->points[j], face->original->d_texture, face->original);
01299
01300 if (lastface) lastface->next = face->next;
01301 else b->brush_faces = face->next;
01302 Face_Free(face);
01303 }
01304 return result;
01305 }
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318 #define MAX_MOVE_FACES 64
01319
01320 int Brush_MoveVertex(brush_t *b, vec3_t vertex, vec3_t delta, vec3_t end, bool bSnap)
01321 {
01322 face_t *f, *face, *newface, *lastface, *nextface;
01323 face_t *movefaces[MAX_MOVE_FACES];
01324 int movefacepoints[MAX_MOVE_FACES];
01325 winding_t *w, tmpw;
01326 vec3_t start, mid;
01327 plane_t plane;
01328 int i, j, k, nummovefaces, result, done;
01329 float dot, front, back, frac, smallestfrac;
01330
01331 result = true;
01332
01333 tmpw.numpoints = 3;
01334 tmpw.maxpoints = 3;
01335 VectorCopy(vertex, start);
01336 VectorAdd(vertex, delta, end);
01337
01338 if (bSnap)
01339 for (i = 0; i < 3; i++)
01340 end[i] = floor(end[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
01341
01342 VectorCopy(end, mid);
01343
01344 if (Point_Equal(start, end, 0.3)) return false;
01345
01346 for (face = b->brush_faces; face; face = face->next)
01347 {
01348 w = face->face_winding;
01349 if (!w) continue;
01350 for (i = 0; i < w->numpoints; i++)
01351 {
01352 if (Point_Equal(w->points[i], end, 0.3))
01353 {
01354 VectorCopy(vertex, end);
01355 return false;
01356 }
01357 }
01358 }
01359
01360 done = false;
01361 while(!done)
01362 {
01363
01364
01365 nummovefaces = 0;
01366 for (face = b->brush_faces; face; face = face->next)
01367 {
01368 w = face->face_winding;
01369 if (!w) continue;
01370 for (i = 0; i < w->numpoints; i++)
01371 {
01372 if (Point_Equal(w->points[i], start, 0.2))
01373 {
01374 if (face->face_winding->numpoints <= 3)
01375 {
01376 movefacepoints[nummovefaces] = i;
01377 movefaces[nummovefaces++] = face;
01378 break;
01379 }
01380 dot = DotProduct(end, face->plane.normal) - face->plane.dist;
01381
01382 if (dot > 0.1)
01383 {
01384
01385 for (k = i; k < i + w->numpoints-3; k++)
01386 {
01387 VectorCopy(w->points[i], tmpw.points[0]);
01388 VectorCopy(w->points[(k+1) % w->numpoints], tmpw.points[1]);
01389 VectorCopy(w->points[(k+2) % w->numpoints], tmpw.points[2]);
01390
01391 newface = Face_Clone(face);
01392
01393 for (f = face; f->original; f = f->original) ;
01394 newface->original = f;
01395
01396 if (newface->face_winding) Winding_Free(newface->face_winding);
01397 newface->face_winding = Winding_Clone(&tmpw);
01398
01399 newface->d_texture = Texture_ForName( newface->texdef.name );
01400
01401 newface->next = b->brush_faces;
01402 b->brush_faces = newface;
01403
01404 movefacepoints[nummovefaces] = 0;
01405 movefaces[nummovefaces++] = newface;
01406 }
01407
01408 VectorCopy(w->points[(i-2+w->numpoints) % w->numpoints], tmpw.points[0]);
01409 VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[1]);
01410 VectorCopy(w->points[i], tmpw.points[2]);
01411 Winding_Free(face->face_winding);
01412 face->face_winding = Winding_Clone(&tmpw);
01413
01414 movefacepoints[nummovefaces] = 2;
01415 movefaces[nummovefaces++] = face;
01416 }
01417 else
01418 {
01419
01420 VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[0]);
01421 VectorCopy(w->points[i], tmpw.points[1]);
01422 VectorCopy(w->points[(i+1) % w->numpoints], tmpw.points[2]);
01423
01424 Winding_RemovePoint(w, i);
01425
01426 Face_SetColor(b, face, 1.0);
01427 for (j = 0; j < w->numpoints; j++)
01428 EmitTextureCoordinates(w->points[j], face->d_texture, face);
01429
01430 newface = Face_Clone(face);
01431
01432 for (f = face; f->original; f = f->original) ;
01433 newface->original = f;
01434
01435 if (newface->face_winding) Winding_Free(newface->face_winding);
01436 newface->face_winding = Winding_Clone(&tmpw);
01437
01438 newface->d_texture = Texture_ForName( newface->texdef.name );
01439
01440 newface->next = b->brush_faces;
01441 b->brush_faces = newface;
01442
01443 movefacepoints[nummovefaces] = 1;
01444 movefaces[nummovefaces++] = newface;
01445 }
01446 break;
01447 }
01448 }
01449 }
01450
01451
01452
01453 done = true;
01454 VectorCopy(end, mid);
01455 smallestfrac = 1;
01456 for (face = b->brush_faces; face; face = face->next)
01457 {
01458
01459 for (i = 0; i < nummovefaces; i++)
01460 {
01461 if (movefaces[i]->original == face) break;
01462 }
01463 if (i >= nummovefaces) continue;
01464
01465 for (j = 0; j < nummovefaces; j++)
01466 {
01467 if (face == movefaces[j]) break;
01468 }
01469
01470 if (j >= nummovefaces)
01471 {
01472 memcpy(&plane, &movefaces[i]->original->plane, sizeof(plane_t));
01473 }
01474 else
01475 {
01476 k = movefacepoints[j];
01477 w = movefaces[j]->face_winding;
01478 VectorCopy(w->points[(k+1)%w->numpoints], tmpw.points[0]);
01479 VectorCopy(w->points[(k+2)%w->numpoints], tmpw.points[1]);
01480
01481 k = movefacepoints[i];
01482 w = movefaces[i]->face_winding;
01483 VectorCopy(w->points[(k+1)%w->numpoints], tmpw.points[2]);
01484 if (!Plane_FromPoints(tmpw.points[0], tmpw.points[1], tmpw.points[2], &plane))
01485 {
01486 VectorCopy(w->points[(k+2)%w->numpoints], tmpw.points[2]);
01487 if (!Plane_FromPoints(tmpw.points[0], tmpw.points[1], tmpw.points[2], &plane))
01488
01489 continue;
01490 }
01491 }
01492
01493 front = DotProduct(start, plane.normal) - plane.dist;
01494 back = DotProduct(end, plane.normal) - plane.dist;
01495
01496 if (front < 0.01 && back < 0.01) continue;
01497 if (front > -0.01 && back > -0.01) continue;
01498
01499 if (fabs(front-back) < 0.001) continue;
01500
01501 frac = front/(front-back);
01502 if (frac < smallestfrac)
01503 {
01504 mid[0] = start[0] + (end[0] - start[0]) * frac;
01505 mid[1] = start[1] + (end[1] - start[1]) * frac;
01506 mid[2] = start[2] + (end[2] - start[2]) * frac;
01507 smallestfrac = frac;
01508 }
01509
01510 done = false;
01511 }
01512
01513
01514 for (i = 0; i < nummovefaces; i++)
01515 {
01516
01517 VectorCopy(mid, movefaces[i]->face_winding->points[movefacepoints[i]]);
01518
01519 for (j = 0; j < 3; j++)
01520 {
01521 VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
01522 }
01523 Face_MakePlane(movefaces[i]);
01524 if (VectorLength(movefaces[i]->plane.normal) < 0.1)
01525 result = false;
01526 }
01527
01528 if (!result || !Brush_Convex(b))
01529 {
01530 for (i = 0; i < nummovefaces; i++)
01531 {
01532
01533 VectorCopy(start, movefaces[i]->face_winding->points[movefacepoints[i]]);
01534
01535 for (j = 0; j < 3; j++)
01536 {
01537 VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
01538 }
01539 Face_MakePlane(movefaces[i]);
01540 }
01541 result = false;
01542 VectorCopy(start, end);
01543 done = true;
01544 }
01545 else
01546 {
01547 VectorCopy(mid, start);
01548 }
01549
01550 for (i = 0; i < nummovefaces; i++)
01551 {
01552 Face_SetColor(b, movefaces[i], 1.0);
01553 for (j = 0; j < movefaces[i]->face_winding->numpoints; j++)
01554 EmitTextureCoordinates(movefaces[i]->face_winding->points[j], movefaces[i]->d_texture, movefaces[i]);
01555 }
01556
01557
01558 lastface = NULL;
01559 for (face = b->brush_faces; face; face = nextface)
01560 {
01561 nextface = face->next;
01562 if (!face->original)
01563 {
01564 lastface = face;
01565 continue;
01566 }
01567 if (!Plane_Equal(&face->plane, &face->original->plane, false))
01568 {
01569 lastface = face;
01570 continue;
01571 }
01572 w = Winding_TryMerge(face->face_winding, face->original->face_winding, face->plane.normal, true);
01573 if (!w)
01574 {
01575 lastface = face;
01576 continue;
01577 }
01578 Winding_Free(face->original->face_winding);
01579 face->original->face_winding = w;
01580
01581 Face_SetColor(b, face->original, 1.0);
01582 for (j = 0; j < face->original->face_winding->numpoints; j++)
01583 EmitTextureCoordinates(face->original->face_winding->points[j], face->original->d_texture, face->original);
01584
01585 if (lastface) lastface->next = face->next;
01586 else b->brush_faces = face->next;
01587 Face_Free(face);
01588 }
01589 }
01590 return result;
01591 }
01592
01593
01594
01595
01596
01597
01598 int Brush_InsertVertexBetween(brush_t *b, vec3_t p1, vec3_t p2)
01599 {
01600 face_t *face;
01601 winding_t *w, *neww;
01602 vec3_t point;
01603 int i, insert;
01604
01605 if (Point_Equal(p1, p2, 0.4))
01606 return false;
01607 VectorAdd(p1, p2, point);
01608 VectorScale(point, 0.5, point);
01609 insert = false;
01610
01611 for (face = b->brush_faces; face; face = face->next)
01612 {
01613 w = face->face_winding;
01614 if (!w) continue;
01615 neww = NULL;
01616 for (i = 0; i < w->numpoints; i++)
01617 {
01618 if (!Point_Equal(w->points[i], p1, 0.1))
01619 continue;
01620 if (Point_Equal(w->points[(i+1) % w->numpoints], p2, 0.1))
01621 {
01622 neww = Winding_InsertPoint(w, point, (i+1) % w->numpoints);
01623 break;
01624 }
01625 else if (Point_Equal(w->points[(i-1+w->numpoints) % w->numpoints], p2, 0.3))
01626 {
01627 neww = Winding_InsertPoint(w, point, i);
01628 break;
01629 }
01630 }
01631 if (neww)
01632 {
01633 Winding_Free(face->face_winding);
01634 face->face_winding = neww;
01635 insert = true;
01636 }
01637 }
01638 return insert;
01639 }
01640
01641
01642
01643
01644
01645
01646
01647 void Brush_ResetFaceOriginals(brush_t *b)
01648 {
01649 face_t *face;
01650
01651 for (face = b->brush_faces; face; face = face->next)
01652 {
01653 face->original = NULL;
01654 }
01655 }
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666 brush_t *Brush_Parse (void)
01667 {
01668 brush_t *b;
01669 face_t *f;
01670 int i,j;
01671
01672 g_qeglobals.d_parsed_brushes++;
01673 b = Brush_Alloc();
01674
01675 do
01676 {
01677 if (!GetToken (true))
01678 break;
01679 if (!strcmp (token, "}") )
01680 break;
01681
01682
01683 if (strcmpi(token, "brushDef") == 0)
01684 {
01685
01686 g_qeglobals.bPrimitBrushes=true;
01687
01688 if (g_qeglobals.m_bBrushPrimitMode)
01689 {
01690 if (g_qeglobals.bOldBrushes)
01691 Sys_Printf("Warning : old brushes and brush primitive in the same file are not allowed ( Brush_Parse )\n");
01692 }
01693
01694 else
01695 Sys_Printf("Warning : conversion code from brush primitive not done ( Brush_Parse )\n");
01696
01697 BrushPrimit_Parse(b);
01698 if (b == NULL)
01699 {
01700 Warning ("parsing brush primitive");
01701 return NULL;
01702 }
01703 else
01704 {
01705 continue;
01706 }
01707 }
01708 if ( strcmpi( token, "terrainDef" ) == 0 )
01709 {
01710 free (b);
01711
01712 b = Terrain_Parse();
01713 if (b == NULL)
01714 {
01715 Warning ("parsing terrain/brush");
01716 return NULL;
01717 }
01718 else
01719 {
01720 continue;
01721 }
01722 }
01723 if (strcmpi(token, "patchDef2") == 0 || strcmpi(token, "patchDef3") == 0)
01724 {
01725 free (b);
01726
01727
01728 b = Patch_Parse(strcmpi(token, "patchDef2") == 0);
01729 if (b == NULL)
01730 {
01731 Warning ("parsing patch/brush");
01732 return NULL;
01733 }
01734 else
01735 {
01736 continue;
01737 }
01738
01739 }
01740 else
01741 {
01742
01743 g_qeglobals.bOldBrushes=true;
01744 if (g_qeglobals.m_bBrushPrimitMode)
01745 {
01746
01747 if (g_qeglobals.bPrimitBrushes)
01748 Sys_Printf("Warning : old brushes and brush primitive in the same file are not allowed ( Brush_Parse )\n");
01749
01750 g_qeglobals.bNeedConvert=true;
01751 }
01752
01753 f = Face_Alloc();
01754
01755
01756
01757
01758 f->next = NULL;
01759 if (!b->brush_faces)
01760 {
01761 b->brush_faces = f;
01762 }
01763 else
01764 {
01765 face_t *scan;
01766 for (scan=b->brush_faces ; scan->next ; scan=scan->next)
01767 ;
01768 scan->next = f;
01769 }
01770
01771
01772 for (i=0 ; i<3 ; i++)
01773 {
01774 if (i != 0)
01775 GetToken (true);
01776 if (strcmp (token, "(") )
01777 {
01778 Warning ("parsing brush");
01779 return NULL;
01780 }
01781
01782 for (j=0 ; j<3 ; j++)
01783 {
01784 GetToken (false);
01785 f->planepts[i][j] = atof(token);
01786 }
01787
01788 GetToken (false);
01789 if (strcmp (token, ")") )
01790 {
01791 Warning ("parsing brush");
01792 return NULL;
01793 }
01794 }
01795 }
01796
01797
01798
01799 if (g_qeglobals.bSurfacePropertiesPlugin)
01800 {
01801 GETPLUGINTEXDEF(f)->ParseTexdef();
01802 }
01803 else
01804 {
01805
01806
01807 GetToken (false);
01808 f->texdef.SetName(token);
01809 if (token[0] == '(')
01810 {
01811 int i = 32;
01812 }
01813 GetToken (false);
01814 f->texdef.shift[0] = atoi(token);
01815 GetToken (false);
01816 f->texdef.shift[1] = atoi(token);
01817 GetToken (false);
01818 f->texdef.rotate = atoi(token);
01819 GetToken (false);
01820 f->texdef.scale[0] = atof(token);
01821 GetToken (false);
01822 f->texdef.scale[1] = atof(token);
01823
01824
01825 f->d_texture = Texture_ForName( f->texdef.name );
01826 f->texdef.flags = f->d_texture->flags;
01827 f->texdef.value = f->d_texture->value;
01828 f->texdef.contents = f->d_texture->contents;
01829
01830 if (TokenAvailable ())
01831 {
01832 GetToken (false);
01833 f->texdef.contents = atoi(token);
01834 GetToken (false);
01835 f->texdef.flags = atoi(token);
01836 GetToken (false);
01837 f->texdef.value = atoi(token);
01838 }
01839
01840 }
01841 } while (1);
01842
01843 return b;
01844 }
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854 FILE * g_File;
01855 void WINAPI QERApp_MapPrintf_FILE( char *text, ... )
01856 {
01857 va_list argptr;
01858 char buf[32768];
01859
01860 va_start (argptr,text);
01861 vsprintf (buf, text,argptr);
01862 va_end (argptr);
01863
01864 fprintf( g_File, buf );
01865 }
01866
01867
01868
01869
01870
01871
01872
01873
01874 void Brush_SetEpair(brush_t *b, const char *pKey, const char *pValue)
01875 {
01876 if (g_qeglobals.m_bBrushPrimitMode)
01877 {
01878 if (b->patchBrush)
01879 {
01880 Patch_SetEpair(b->pPatch, pKey, pValue);
01881 }
01882 else if (b->terrainBrush)
01883 {
01884 Terrain_SetEpair(b->pTerrain, pKey, pValue);
01885 }
01886 else
01887 {
01888 SetKeyValue(b->epairs, pKey, pValue);
01889 }
01890 }
01891 else
01892 {
01893 Sys_Printf("Can only set key/values in Brush primitive mode\n");
01894 }
01895 }
01896
01897
01898
01899
01900
01901
01902 const char* Brush_GetKeyValue(brush_t *b, const char *pKey)
01903 {
01904 if (g_qeglobals.m_bBrushPrimitMode)
01905 {
01906 if (b->patchBrush)
01907 {
01908 return Patch_GetKeyValue(b->pPatch, pKey);
01909 }
01910 else if (b->terrainBrush)
01911 {
01912 return Terrain_GetKeyValue(b->pTerrain, pKey);
01913 }
01914 else
01915 {
01916 return ValueForKey(b->epairs, pKey);
01917 }
01918 }
01919 else
01920 {
01921 Sys_Printf("Can only set brush/patch key/values in Brush primitive mode\n");
01922 }
01923 return "";
01924 }
01925
01926
01927
01928
01929
01930
01931
01932 void Brush_Write (brush_t *b, FILE *f)
01933 {
01934 epair_t *ep;
01935 face_t *fa;
01936 char *pname;
01937 int i;
01938
01939 if (b->patchBrush)
01940 {
01941 Patch_Write(b->pPatch, f);
01942 return;
01943 }
01944 if ( b->pTerrain )
01945 {
01946 Terrain_Write(b->pTerrain, f);
01947 return;
01948 }
01949 if (g_qeglobals.m_bBrushPrimitMode)
01950 {
01951
01952 fprintf (f, "{\nbrushDef\n{\n");
01953
01954 if (b->epairs)
01955 for (ep = b->epairs ; ep ; ep=ep->next)
01956 fprintf (f, "\"%s\" \"%s\"\n", ep->key, ep->value);
01957 for (fa=b->brush_faces ; fa ; fa=fa->next)
01958 {
01959
01960 for (i=0 ; i<3 ; i++)
01961 {
01962 fprintf(f, "( ");
01963 for (int j = 0; j < 3; j++)
01964 if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j]))
01965 fprintf(f, "%i ", static_cast<int>(fa->planepts[i][j]));
01966 else
01967 fprintf(f, "%f ", fa->planepts[i][j]);
01968 fprintf(f, ") ");
01969 }
01970
01971 fprintf(f,"( ( ");
01972 for (i=0 ; i<3 ; i++)
01973 if (fa->brushprimit_texdef.coords[0][i] == static_cast<int>(fa->brushprimit_texdef.coords[0][i]))
01974 fprintf(f,"%i ",static_cast<int>(fa->brushprimit_texdef.coords[0][i]));
01975 else
01976 fprintf(f,"%f ",fa->brushprimit_texdef.coords[0][i]);
01977 fprintf(f,") ( ");
01978 for (i=0 ; i<3 ; i++)
01979 if (fa->brushprimit_texdef.coords[1][i] == static_cast<int>(fa->brushprimit_texdef.coords[1][i]))
01980 fprintf(f,"%i ",static_cast<int>(fa->brushprimit_texdef.coords[1][i]));
01981 else
01982 fprintf(f,"%f ",fa->brushprimit_texdef.coords[1][i]);
01983 fprintf(f,") ) ");
01984
01985
01986 if (g_qeglobals.bSurfacePropertiesPlugin)
01987 Sys_Printf("WARNING: surface properties plugin not supported with brush primitives (yet)\n");
01988
01989 char *pName = strlen(fa->texdef.name) > 0 ? fa->texdef.name : "unnamed";
01990 fprintf(f, "%s ", pName );
01991 fprintf(f, "%i %i %i\n", fa->texdef.contents, fa->texdef.flags, fa->texdef.value);
01992 }
01993 fprintf (f, "}\n}\n");
01994 }
01995 else
01996 {
01997 fprintf (f, "{\n");
01998 for (fa=b->brush_faces ; fa ; fa=fa->next)
01999 {
02000 for (i=0 ; i<3 ; i++)
02001 {
02002 fprintf(f, "( ");
02003 for (int j = 0; j < 3; j++)
02004 {
02005 if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j]))
02006 fprintf(f, "%i ", static_cast<int>(fa->planepts[i][j]));
02007 else
02008 fprintf(f, "%f ", fa->planepts[i][j]);
02009 }
02010 fprintf(f, ") ");
02011 }
02012
02013 if (g_qeglobals.bSurfacePropertiesPlugin)
02014 {
02015 g_File = f;
02016 #ifdef _DEBUG
02017 if (!fa->pData)
02018 Sys_Printf("ERROR: unexpected IPluginTexdef* is NULL in Brush_Write\n");
02019 else
02020 #endif
02021 GETPLUGINTEXDEF(fa)->WriteTexdef( QERApp_MapPrintf_FILE );
02022 }
02023 else
02024 {
02025 pname = fa->texdef.name;
02026 if (pname[0] == 0)
02027 pname = "unnamed";
02028
02029 fprintf (f, "%s %i %i %i ", pname,
02030 (int)fa->texdef.shift[0], (int)fa->texdef.shift[1],
02031 (int)fa->texdef.rotate);
02032
02033 if (fa->texdef.scale[0] == (int)fa->texdef.scale[0])
02034 fprintf (f, "%i ", (int)fa->texdef.scale[0]);
02035 else
02036 fprintf (f, "%f ", (float)fa->texdef.scale[0]);
02037 if (fa->texdef.scale[1] == (int)fa->texdef.scale[1])
02038 fprintf (f, "%i", (int)fa->texdef.scale[1]);
02039 else
02040 fprintf (f, "%f", (float)fa->texdef.scale[1]);
02041
02042 fprintf (f, " %i %i %i", fa->texdef.contents, fa->texdef.flags, fa->texdef.value);
02043 }
02044 fprintf (f, "\n");
02045 }
02046 fprintf (f, "}\n");
02047 }
02048 }
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058 CMemFile * g_pMemFile;
02059 void WINAPI QERApp_MapPrintf_MEMFILE( char *text, ... )
02060 {
02061 va_list argptr;
02062 char buf[32768];
02063
02064 va_start (argptr,text);
02065 vsprintf (buf, text,argptr);
02066 va_end (argptr);
02067
02068 MemFile_fprintf( g_pMemFile, buf );
02069 }
02070
02071
02072
02073
02074
02075
02076
02077 void Brush_Write (brush_t *b, CMemFile *pMemFile)
02078 {
02079 epair_t *ep;
02080 face_t *fa;
02081 char *pname;
02082 int i;
02083
02084 if (b->patchBrush)
02085 {
02086 Patch_Write(b->pPatch, pMemFile);
02087 return;
02088 }
02089 if (b->terrainBrush)
02090 {
02091 Terrain_Write(b->pTerrain, pMemFile);
02092 return;
02093 }
02094
02095
02096 if (g_qeglobals.bSurfacePropertiesPlugin)
02097 {
02098 Sys_Printf("WARNING: Brush_Write to a CMemFile and Surface Properties plugin not done\n");
02099 }
02100 if (g_qeglobals.m_bBrushPrimitMode)
02101 {
02102
02103 MemFile_fprintf (pMemFile, "{\nBrushDef\n{\n");
02104
02105 if (b->epairs)
02106 for( ep = b->epairs ; ep ; ep=ep->next )
02107 MemFile_fprintf (pMemFile, "\"%s\" \"%s\"\n", ep->key, ep->value );
02108 for (fa=b->brush_faces ; fa ; fa=fa->next)
02109 {
02110
02111 for (i=0 ; i<3 ; i++)
02112 {
02113 MemFile_fprintf(pMemFile, "( ");
02114 for (int j = 0; j < 3; j++)
02115 if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j]))
02116 MemFile_fprintf(pMemFile, "%i ", static_cast<int>(fa->planepts[i][j]));
02117 else
02118 MemFile_fprintf(pMemFile, "%f ", fa->planepts[i][j]);
02119 MemFile_fprintf(pMemFile, ") ");
02120 }
02121
02122 MemFile_fprintf(pMemFile,"( ( ");
02123 for (i=0 ; i<3 ; i++)
02124 if (fa->brushprimit_texdef.coords[0][i] == static_cast<int>(fa->brushprimit_texdef.coords[0][i]))
02125 MemFile_fprintf(pMemFile,"%i ",static_cast<int>(fa->brushprimit_texdef.coords[0][i]));
02126 else
02127 MemFile_fprintf(pMemFile,"%f ",fa->brushprimit_texdef.coords[0][i]);
02128 MemFile_fprintf(pMemFile,") ( ");
02129 for (i=0 ; i<3 ; i++)
02130 if (fa->brushprimit_texdef.coords[1][i] == static_cast<int>(fa->brushprimit_texdef.coords[1][i]))
02131 MemFile_fprintf(pMemFile,"%i ",static_cast<int>(fa->brushprimit_texdef.coords[1][i]));
02132 else
02133 MemFile_fprintf(pMemFile,"%f ",fa->brushprimit_texdef.coords[1][i]);
02134 MemFile_fprintf(pMemFile,") ) ");
02135
02136 char *pName = strlen(fa->texdef.name) > 0 ? fa->texdef.name : "unnamed";
02137 MemFile_fprintf(pMemFile, "%s ", pName);
02138 MemFile_fprintf(pMemFile, "%i %i %i\n", fa->texdef.contents, fa->texdef.flags, fa->texdef.value);
02139 }
02140 MemFile_fprintf (pMemFile, "}\n}\n");
02141 }
02142 else
02143 {
02144
02145
02146 MemFile_fprintf (pMemFile, "{\n");
02147 for (fa=b->brush_faces ; fa ; fa=fa->next)
02148 {
02149 for (i=0 ; i<3 ; i++)
02150 {
02151 MemFile_fprintf(pMemFile, "( ");
02152 for (int j = 0; j < 3; j++)
02153 {
02154 if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j]))
02155 MemFile_fprintf(pMemFile, "%i ", static_cast<int>(fa->planepts[i][j]));
02156 else
02157 MemFile_fprintf(pMemFile, "%f ", fa->planepts[i][j]);
02158 }
02159 MemFile_fprintf(pMemFile, ") ");
02160 }
02161
02162 if (g_qeglobals.bSurfacePropertiesPlugin)
02163 {
02164 g_pMemFile = pMemFile;
02165 #ifdef _DEBUG
02166 if (!fa->pData)
02167 Sys_Printf("ERROR: unexpected IPluginTexdef* is NULL in Brush_Write\n");
02168 else
02169 #endif
02170 GETPLUGINTEXDEF(fa)->WriteTexdef( QERApp_MapPrintf_MEMFILE );
02171 }
02172 else
02173 {
02174 pname = fa->texdef.name;
02175 if (pname[0] == 0)
02176 pname = "unnamed";
02177
02178 MemFile_fprintf (pMemFile, "%s %i %i %i ", pname,
02179 (int)fa->texdef.shift[0], (int)fa->texdef.shift[1],
02180 (int)fa->texdef.rotate);
02181
02182 if (fa->texdef.scale[0] == (int)fa->texdef.scale[0])
02183 MemFile_fprintf (pMemFile, "%i ", (int)fa->texdef.scale[0]);
02184 else
02185 MemFile_fprintf (pMemFile, "%f ", (float)fa->texdef.scale[0]);
02186 if (fa->texdef.scale[1] == (int)fa->texdef.scale[1])
02187 MemFile_fprintf (pMemFile, "%i", (int)fa->texdef.scale[1]);
02188 else
02189 MemFile_fprintf (pMemFile, "%f", (float)fa->texdef.scale[1]);
02190
02191 MemFile_fprintf (pMemFile, " %i %i %i", fa->texdef.contents, fa->texdef.flags, fa->texdef.value);
02192 }
02193 MemFile_fprintf (pMemFile, "\n");
02194 }
02195 MemFile_fprintf (pMemFile, "}\n");
02196 }
02197
02198
02199 }
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210 brush_t *Brush_Create (vec3_t mins, vec3_t maxs, texdef_t *texdef)
02211 {
02212 int i, j;
02213 vec3_t pts[4][2];
02214 face_t *f;
02215 brush_t *b;
02216
02217
02218
02219 if (g_qeglobals.m_bBrushPrimitMode)
02220 {
02221
02222 if (texdef->shift[0]!=0 || texdef->shift[1]!=0 || texdef->scale[0]!=0 || texdef->scale[1]!=0 || texdef->rotate!=0)
02223 Sys_Printf("Warning : non-zero texdef detected in Brush_Create .. need brush primitive conversion\n");
02224 }
02225
02226 for (i=0 ; i<3 ; i++)
02227 {
02228 if (maxs[i] < mins[i])
02229 Error ("Brush_InitSolid: backwards");
02230 }
02231
02232 b = Brush_Alloc();
02233
02234 pts[0][0][0] = mins[0];
02235 pts[0][0][1] = mins[1];
02236
02237 pts[1][0][0] = mins[0];
02238 pts[1][0][1] = maxs[1];
02239
02240 pts[2][0][0] = maxs[0];
02241 pts[2][0][1] = maxs[1];
02242
02243 pts[3][0][0] = maxs[0];
02244 pts[3][0][1] = mins[1];
02245
02246 for (i=0 ; i<4 ; i++)
02247 {
02248 pts[i][0][2] = mins[2];
02249 pts[i][1][0] = pts[i][0][0];
02250 pts[i][1][1] = pts[i][0][1];
02251 pts[i][1][2] = maxs[2];
02252 }
02253
02254 for (i=0 ; i<4 ; i++)
02255 {
02256 f = Face_Alloc();
02257 f->texdef = *texdef;
02258 f->texdef.flags &= ~SURF_KEEP;
02259 f->texdef.contents &= ~CONTENTS_KEEP;
02260 f->next = b->brush_faces;
02261 b->brush_faces = f;
02262 j = (i+1)%4;
02263
02264 VectorCopy (pts[j][1], f->planepts[0]);
02265 VectorCopy (pts[i][1], f->planepts[1]);
02266 VectorCopy (pts[i][0], f->planepts[2]);
02267 }
02268
02269 f = Face_Alloc();
02270 f->texdef = *texdef;
02271 f->texdef.flags &= ~SURF_KEEP;
02272 f->texdef.contents &= ~CONTENTS_KEEP;
02273 f->next = b->brush_faces;
02274 b->brush_faces = f;
02275
02276 VectorCopy (pts[0][1], f->planepts[0]);
02277 VectorCopy (pts[1][1], f->planepts[1]);
02278 VectorCopy (pts[2][1], f->planepts[2]);
02279
02280 f = Face_Alloc();
02281 f->texdef = *texdef;
02282 f->texdef.flags &= ~SURF_KEEP;
02283 f->texdef.contents &= ~CONTENTS_KEEP;
02284 f->next = b->brush_faces;
02285 b->brush_faces = f;
02286
02287 VectorCopy (pts[2][0], f->planepts[0]);
02288 VectorCopy (pts[1][0], f->planepts[1]);
02289 VectorCopy (pts[0][0], f->planepts[2]);
02290
02291 return b;
02292 }
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302 brush_t *Brush_CreatePyramid (vec3_t mins, vec3_t maxs, texdef_t *texdef)
02303 {
02304
02305 return Brush_Create(mins, maxs, texdef);
02306
02307 for (int i=0 ; i<3 ; i++)
02308 if (maxs[i] < mins[i])
02309 Error ("Brush_InitSolid: backwards");
02310
02311 brush_t* b = Brush_Alloc();
02312
02313 vec3_t corners[4];
02314
02315 float fMid = Q_rint(mins[2] + (Q_rint((maxs[2] - mins[2]) / 2)));
02316
02317 corners[0][0] = mins[0];
02318 corners[0][1] = mins[1];
02319 corners[0][2] = fMid;
02320
02321 corners[1][0] = mins[0];
02322 corners[1][1] = maxs[1];
02323 corners[1][2] = fMid;
02324
02325 corners[2][0] = maxs[0];
02326 corners[2][1] = maxs[1];
02327 corners[2][2] = fMid;
02328
02329 corners[3][0] = maxs[0];
02330 corners[3][1] = mins[1];
02331 corners[3][2] = fMid;
02332
02333 vec3_t top, bottom;
02334
02335 top[0] = Q_rint(mins[0] + ((maxs[0] - mins[0]) / 2));
02336 top[1] = Q_rint(mins[1] + ((maxs[1] - mins[1]) / 2));
02337 top[2] = Q_rint(maxs[2]);
02338
02339 VectorCopy(top, bottom);
02340 bottom[2] = mins[2];
02341
02342
02343 for (i = 0; i < 4; i++)
02344 {
02345 face_t* f = Face_Alloc();
02346 f->texdef = *texdef;
02347 f->texdef.flags &= ~SURF_KEEP;
02348 f->texdef.contents &= ~CONTENTS_KEEP;
02349 f->next = b->brush_faces;
02350 b->brush_faces = f;
02351 int j = (i+1)%4;
02352
02353 VectorCopy (top, f->planepts[0]);
02354 VectorCopy (corners[i], f->planepts[1]);
02355 VectorCopy(corners[j], f->planepts[2]);
02356
02357 f = Face_Alloc();
02358 f->texdef = *texdef;
02359 f->texdef.flags &= ~SURF_KEEP;
02360 f->texdef.contents &= ~CONTENTS_KEEP;
02361 f->next = b->brush_faces;
02362 b->brush_faces = f;
02363
02364 VectorCopy (bottom, f->planepts[2]);
02365 VectorCopy (corners[i], f->planepts[1]);
02366 VectorCopy(corners[j], f->planepts[0]);
02367 }
02368
02369 return b;
02370 }
02371
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382 void Brush_MakeSided (int sides)
02383 {
02384 int i, axis;
02385 vec3_t mins, maxs;
02386 brush_t *b;
02387 texdef_t *texdef;
02388 face_t *f;
02389 vec3_t mid;
02390 float width;
02391 float sv, cv;
02392
02393 if (sides < 3)
02394 {
02395 Sys_Status ("Bad sides number", 0);
02396 return;
02397 }
02398
02399 if (sides >= MAX_POINTS_ON_WINDING-4)
02400 {
02401 Sys_Printf("too many sides.\n");
02402 return;
02403 }
02404
02405 if (!QE_SingleBrush ())
02406 {
02407 Sys_Status ("Must have a single brush selected", 0 );
02408 return;
02409 }
02410
02411 b = selected_brushes.next;
02412 VectorCopy (b->mins, mins);
02413 VectorCopy (b->maxs, maxs);
02414 texdef = &g_qeglobals.d_texturewin.texdef;
02415
02416 Brush_Free (b);
02417
02418 if (g_pParentWnd->ActiveXY())
02419 {
02420 switch(g_pParentWnd->ActiveXY()->GetViewType())
02421 {
02422 case XY: axis = 2; break;
02423 case XZ: axis = 1; break;
02424 case YZ: axis = 0; break;
02425 }
02426 }
02427 else
02428 {
02429 axis = 2;
02430 }
02431
02432
02433 width = 8;
02434 for (i = 0; i < 3; i++)
02435 {
02436 mid[i] = (maxs[i] + mins[i]) * 0.5;
02437 if (i == axis) continue;
02438 if ((maxs[i] - mins[i]) * 0.5 > width)
02439 width = (maxs[i] - mins[i]) * 0.5;
02440 }
02441
02442 b = Brush_Alloc();
02443
02444
02445 f = Face_Alloc();
02446 f->texdef = *texdef;
02447 f->next = b->brush_faces;
02448 b->brush_faces = f;
02449
02450 f->planepts[2][(axis+1)%3] = mins[(axis+1)%3]; f->planepts[2][(axis+2)%3] = mins[(axis+2)%3]; f->planepts[2][axis] = maxs[axis];
02451 f->planepts[1][(axis+1)%3] = maxs[(axis+1)%3]; f->planepts[1][(axis+2)%3] = mins[(axis+2)%3]; f->planepts[1][axis] = maxs[axis];
02452 f->planepts[0][(axis+1)%3] = maxs[(axis+1)%3]; f->planepts[0][(axis+2)%3] = maxs[(axis+2)%3]; f->planepts[0][axis] = maxs[axis];
02453
02454
02455 f = Face_Alloc();
02456 f->texdef = *texdef;
02457 f->next = b->brush_faces;
02458 b->brush_faces = f;
02459
02460 f->planepts[0][(axis+1)%3] = mins[(axis+1)%3]; f->planepts[0][(axis+2)%3] = mins[(axis+2)%3]; f->planepts[0][axis] = mins[axis];
02461 f->planepts[1][(axis+1)%3] = maxs[(axis+1)%3]; f->planepts[1][(axis+2)%3] = mins[(axis+2)%3]; f->planepts[1][axis] = mins[axis];
02462 f->planepts[2][(axis+1)%3] = maxs[(axis+1)%3]; f->planepts[2][(axis+2)%3] = maxs[(axis+2)%3]; f->planepts[2][axis] = mins[axis];
02463
02464 for (i=0 ; i<sides ; i++)
02465 {
02466 f = Face_Alloc();
02467 f->texdef = *texdef;
02468 f->next = b->brush_faces;
02469 b->brush_faces = f;
02470
02471 sv = sin (i*3.14159265*2/sides);
02472 cv = cos (i*3.14159265*2/sides);
02473
02474 f->planepts[0][(axis+1)%3] = floor(mid[(axis+1)%3]+width*cv+0.5);
02475 f->planepts[0][(axis+2)%3] = floor(mid[(axis+2)%3]+width*sv+0.5);
02476 f->planepts[0][axis] = mins[axis];
02477
02478 f->planepts[1][(axis+1)%3] = f->planepts[0][(axis+1)%3];
02479 f->planepts[1][(axis+2)%3] = f->planepts[0][(axis+2)%3];
02480 f->planepts[1][axis] = maxs[axis];
02481
02482 f->planepts[2][(axis+1)%3] = floor(f->planepts[0][(axis+1)%3] - width*sv + 0.5);
02483 f->planepts[2][(axis+2)%3] = floor(f->planepts[0][(axis+2)%3] + width*cv + 0.5);
02484 f->planepts[2][axis] = maxs[axis];
02485 }
02486
02487 Brush_AddToList (b, &selected_brushes);
02488
02489 Entity_LinkBrush (world_entity, b);
02490
02491 Brush_Build( b );
02492
02493 Sys_UpdateWindows (W_ALL);
02494 }
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510 void Brush_Free (brush_t *b, bool bRemoveNode)
02511 {
02512 face_t *f, *next;
02513 epair_t *ep, *enext;
02514
02515
02516 if (bRemoveNode)
02517 Group_RemoveBrush(b);
02518
02519
02520 if (b->patchBrush)
02521 {
02522 Patch_Delete(b->pPatch);
02523 }
02524
02525 if( b->terrainBrush )
02526 {
02527 Terrain_Delete( b->pTerrain );
02528 }
02529
02530
02531 for (f=b->brush_faces ; f ; f=next)
02532 {
02533 next = f->next;
02534 Face_Free( f );
02535 }
02536
02537
02538 for (ep = b->epairs ; ep ; ep=enext )
02539 {
02540 enext = ep->next;
02541 free (ep->key);
02542 free (ep->value);
02543 free (ep);
02544 }
02545
02546
02547 if (b->next)
02548 Brush_RemoveFromList (b);
02549
02550
02551 if (b->onext)
02552 Entity_UnlinkBrush (b);
02553
02554 free (b);
02555 }
02556
02557
02558
02559
02560
02561
02562 int Face_MemorySize(face_t *f )
02563 {
02564 int size = 0;
02565
02566 if (f->face_winding)
02567 {
02568 size += _msize(f->face_winding);
02569 }
02570
02571 size += _msize(f);
02572 return size;
02573 }
02574
02575
02576
02577
02578
02579
02580 int Brush_MemorySize(brush_t *b)
02581 {
02582 face_t *f;
02583 epair_t *ep;
02584 int size = 0;
02585
02586
02587 if (b->patchBrush)
02588 {
02589 size += Patch_MemorySize(b->pPatch);
02590 }
02591 if (b->terrainBrush)
02592 {
02593 size += Terrain_MemorySize(b->pTerrain);
02594 }
02595
02596 for (f = b->brush_faces; f; f = f->next)
02597 {
02598 size += Face_MemorySize(f);
02599 }
02600
02601 for (ep = b->epairs; ep; ep = ep->next )
02602 {
02603 size += _msize(ep->key);
02604 size += _msize(ep->value);
02605 size += _msize(ep);
02606 }
02607 size += _msize(b);
02608 return size;
02609 }
02610
02611
02612
02613
02614
02615
02616
02617
02618
02619 brush_t *Brush_Clone (brush_t *b)
02620 {
02621 brush_t *n = NULL;
02622 face_t *f, *nf;
02623
02624 if (b->patchBrush)
02625 {
02626 patchMesh_t *p = Patch_Duplicate(b->pPatch);
02627 Brush_RemoveFromList(p->pSymbiot);
02628 Entity_UnlinkBrush(p->pSymbiot);
02629 n = p->pSymbiot;
02630 }
02631 else if (b->terrainBrush)
02632 {
02633 terrainMesh_t *p = Terrain_Duplicate(b->pTerrain);
02634 Brush_RemoveFromList(p->pSymbiot);
02635 Entity_UnlinkBrush(p->pSymbiot);
02636 n = p->pSymbiot;
02637 }
02638 else
02639 {
02640 n = Brush_Alloc();
02641 n->numberId = g_nBrushId++;
02642 n->owner = b->owner;
02643 for (f=b->brush_faces ; f ; f=f->next)
02644 {
02645 nf = Face_Clone( f );
02646 nf->next = n->brush_faces;
02647 n->brush_faces = nf;
02648 }
02649 }
02650
02651 return n;
02652 }
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663 brush_t *Brush_FullClone(brush_t *b)
02664 {
02665 brush_t *n = NULL;
02666 face_t *f, *nf, *f2, *nf2;
02667 int j;
02668
02669 if (b->patchBrush)
02670 {
02671 patchMesh_t *p = Patch_Duplicate(b->pPatch);
02672 Brush_RemoveFromList(p->pSymbiot);
02673 Entity_UnlinkBrush(p->pSymbiot);
02674 n = p->pSymbiot;
02675 n->owner = b->owner;
02676 Brush_Build(n);
02677 }
02678 else if (b->terrainBrush)
02679 {
02680 terrainMesh_t *p = Terrain_Duplicate(b->pTerrain);
02681 Brush_RemoveFromList(p->pSymbiot);
02682 Entity_UnlinkBrush(p->pSymbiot);
02683 n = p->pSymbiot;
02684 n->owner = b->owner;
02685 Brush_Build(n);
02686 }
02687 else
02688 {
02689 n = Brush_Alloc();
02690 n->numberId = g_nBrushId++;
02691 n->owner = b->owner;
02692 VectorCopy(b->mins, n->mins);
02693 VectorCopy(b->maxs, n->maxs);
02694
02695 for (f = b->brush_faces; f; f = f->next)
02696 {
02697 if (f->original) continue;
02698 nf = Face_FullClone(f);
02699 nf->next = n->brush_faces;
02700 n->brush_faces = nf;
02701
02702 for (f2 = b->brush_faces; f2; f2 = f2->next)
02703 {
02704 if (f2->original == f)
02705 {
02706 nf2 = Face_FullClone(f2);
02707 nf2->next = n->brush_faces;
02708 n->brush_faces = nf2;
02709
02710 nf2->original = nf;
02711 }
02712 }
02713 }
02714 for (nf = n->brush_faces; nf; nf = nf->next)
02715 {
02716 Face_SetColor(n, nf, 1.0);
02717 if (nf->face_winding)
02718 {
02719 if (g_qeglobals.m_bBrushPrimitMode)
02720 EmitBrushPrimitTextureCoordinates(nf,nf->face_winding);
02721 else
02722 {
02723 for (j = 0; j < nf->face_winding->numpoints; j++)
02724 EmitTextureCoordinates(nf->face_winding->points[j], nf->d_texture, nf);
02725 }
02726 }
02727 }
02728 }
02729 return n;
02730 }
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741 face_t *Brush_Ray (vec3_t origin, vec3_t dir, brush_t *b, float *dist)
02742 {
02743 face_t *f, *firstface;
02744 vec3_t p1, p2;
02745 float frac, d1, d2;
02746 int i;
02747
02748 VectorCopy (origin, p1);
02749 for (i=0 ; i<3 ; i++)
02750 p2[i] = p1[i] + dir[i]*16384;
02751
02752 for (f=b->brush_faces ; f ; f=f->next)
02753 {
02754 d1 = DotProduct (p1, f->plane.normal) - f->plane.dist;
02755 d2 = DotProduct (p2, f->plane.normal) - f->plane.dist;
02756 if (d1 >= 0 && d2 >= 0)
02757 {
02758 *dist = 0;
02759 return NULL;
02760 }
02761 if (d1 <=0 && d2 <= 0)
02762 continue;
02763
02764 frac = d1 / (d1 - d2);
02765 if (d1 > 0)
02766 {
02767 firstface = f;
02768 for (i=0 ; i<3 ; i++)
02769 p1[i] = p1[i] + frac *(p2[i] - p1[i]);
02770 }
02771 else
02772 {
02773 for (i=0 ; i<3 ; i++)
02774 p2[i] = p1[i] + frac *(p2[i] - p1[i]);
02775 }
02776 }
02777
02778
02779 VectorSubtract (p1, origin, p1);
02780 d1 = DotProduct (p1, dir);
02781
02782 *dist = d1;
02783
02784 return firstface;
02785 }
02786
02787
02788 face_t *Brush_Point (vec3_t origin, brush_t *b)
02789 {
02790 face_t *f;
02791 float d1;
02792
02793 for (f=b->brush_faces ; f ; f=f->next)
02794 {
02795 d1 = DotProduct (origin, f->plane.normal) - f->plane.dist;
02796 if (d1 > 0)
02797 {
02798 return NULL;
02799 }
02800 }
02801
02802 return b->brush_faces;
02803 }
02804
02805
02806
02807 void Brush_AddToList (brush_t *b, brush_t *list)
02808 {
02809 if (b->next || b->prev)
02810 Error ("Brush_AddToList: allready linked");
02811
02812 if (list == &selected_brushes || list == &active_brushes)
02813 {
02814 if (b->patchBrush && list == &selected_brushes)
02815 {
02816 Patch_Select(b->pPatch);
02817 }
02818 if (b->terrainBrush && list == &selected_brushes) {
02819 Terrain_Select(b->pTerrain);
02820 }
02821 }
02822 b->next = list->next;
02823 list->next->prev = b;
02824 list->next = b;
02825 b->prev = list;
02826
02827
02828 DispatchRadiantMsg( RADIANT_SELECTION );
02829 }
02830
02831 void Brush_RemoveFromList (brush_t *b)
02832 {
02833 if (!b->next || !b->prev)
02834 Error ("Brush_RemoveFromList: not linked");
02835
02836 if (b->patchBrush)
02837 {
02838 Patch_Deselect(b->pPatch);
02839
02840 }
02841 if (b->terrainBrush)
02842 {
02843 Terrain_Deselect(b->pTerrain);
02844 }
02845
02846 b->next->prev = b->prev;
02847 b->prev->next = b->next;
02848 b->next = b->prev = NULL;
02849 }
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867 void SetFaceTexdef (brush_t *b, face_t *f, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, IPluginTexdef* pPlugTexdef) {
02868 int oldFlags;
02869 int oldContents;
02870 face_t *tf;
02871
02872 oldFlags = f->texdef.flags;
02873 oldContents = f->texdef.contents;
02874 if (g_qeglobals.m_bBrushPrimitMode)
02875 {
02876 f->texdef = *texdef;
02877 ConvertTexMatWithQTexture( brushprimit_texdef, NULL, &f->brushprimit_texdef, Texture_ForName( f->texdef.name ) );
02878 }
02879 else
02880 if (bFitScale)
02881 {
02882 f->texdef = *texdef;
02883
02884 vec3_t p1,p2,p3;
02885
02886 ComputeAbsolute(f,p1,p2,p3);
02887
02888 vec3_t vx,vy;
02889 VectorSubtract(p2,p1,vx);
02890 VectorNormalize(vx);
02891 VectorSubtract(p3,p1,vy);
02892 VectorNormalize(vy);
02893
02894 VectorScale(vx,texdef->scale[0],vx);
02895 VectorScale(vy,texdef->scale[1],vy);
02896 VectorAdd(p1,vx,p2);
02897 VectorAdd(p1,vy,p3);
02898
02899 AbsoluteToLocal(f->plane,f,p1,p2,p3);
02900 }
02901 else
02902 f->texdef = *texdef;
02903 f->texdef.flags = (f->texdef.flags & ~SURF_KEEP) | (oldFlags & SURF_KEEP);
02904 f->texdef.contents = (f->texdef.contents & ~CONTENTS_KEEP) | (oldContents & CONTENTS_KEEP);
02905
02906
02907 if (g_qeglobals.bSurfacePropertiesPlugin)
02908 {
02909 #ifdef _DEBUG
02910 if (!f->pData)
02911 Sys_Printf("ERROR: unexpected IPluginTexdef* is NULL in SetFaceTexdef\n");
02912 else
02913 #endif
02914 GETPLUGINTEXDEF(f)->DecRef();
02915 IPluginTexdef *pTexdef = NULL;
02916 if ( pPlugTexdef )
02917 {
02918 pTexdef = pPlugTexdef->Copy();
02919 pTexdef->Hook( f );
02920 }
02921 else
02922 pTexdef = g_SurfaceTable.m_pfnTexdefAlloc( f );
02923 f->pData = pTexdef;
02924 }
02925
02926
02927 if (f->texdef.flags & SURF_CURVE)
02928 {
02929 for (tf = b->brush_faces ; tf ; tf = tf->next)
02930 {
02931 if (tf->texdef.flags & SURF_CURVE)
02932 tf->texdef = f->texdef;
02933 }
02934 }
02935 }
02936
02937
02938 void Brush_SetTexture (brush_t *b, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, IPluginTexdef* pTexdef)
02939 {
02940 for (face_t* f = b->brush_faces ; f ; f = f->next)
02941 {
02942 SetFaceTexdef (b, f, texdef, brushprimit_texdef, bFitScale, pTexdef);
02943 }
02944 Brush_Build( b );
02945 if (b->patchBrush)
02946 {
02947
02948
02949 Patch_SetTexture(b->pPatch, texdef, pTexdef );
02950 }
02951 if (b->terrainBrush)
02952 {
02953 Terrain_SetTexture(b->pTerrain, texdef);
02954 }
02955
02956 }
02957
02958
02959 qboolean ClipLineToFace (vec3_t p1, vec3_t p2, face_t *f)
02960 {
02961 float d1, d2, fr;
02962 int i;
02963 float *v;
02964
02965 d1 = DotProduct (p1, f->plane.normal) - f->plane.dist;
02966 d2 = DotProduct (p2, f->plane.normal) - f->plane.dist;
02967
02968 if (d1 >= 0 && d2 >= 0)
02969 return false;
02970 if (d1 <= 0 && d2 <= 0)
02971 return true;
02972
02973 fr = d1 / (d1 - d2);
02974
02975 if (d1 > 0)
02976 v = p1;
02977 else
02978 v = p2;
02979
02980 for (i=0 ; i<3 ; i++)
02981 v[i] = p1[i] + fr*(p2[i] - p1[i]);
02982
02983 return true;
02984 }
02985
02986
02987 int AddPlanept (float *f)
02988 {
02989 int i;
02990
02991 for (i=0 ; i<g_qeglobals.d_num_move_points ; i++)
02992 if (g_qeglobals.d_move_points[i] == f)
02993 return 0;
02994 g_qeglobals.d_move_points[g_qeglobals.d_num_move_points++] = f;
02995 return 1;
02996 }
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006 void Brush_SelectFaceForDragging (brush_t *b, face_t *f, qboolean shear)
03007 {
03008 int i;
03009 face_t *f2;
03010 winding_t *w;
03011 float d;
03012 brush_t *b2;
03013 int c;
03014
03015 if (b->owner->eclass->fixedsize)
03016 return;
03017
03018 c = 0;
03019 for (i=0 ; i<3 ; i++)
03020 c += AddPlanept (f->planepts[i]);
03021 if (c == 0)
03022 return;
03023
03024
03025 for (b2=selected_brushes.next ; b2 != &selected_brushes ; b2 = b2->next)
03026 {
03027 if (b2 == b)
03028 continue;
03029 for (f2=b2->brush_faces ; f2 ; f2=f2->next)
03030 {
03031 for (i=0 ; i<3 ; i++)
03032 if (fabs(DotProduct(f2->planepts[i], f->plane.normal)
03033 -f->plane.dist) > ON_EPSILON)
03034 break;
03035 if (i==3)
03036 {
03037 Brush_SelectFaceForDragging (b2, f2, shear);
03038 break;
03039 }
03040 }
03041 }
03042
03043
03044
03045
03046
03047 if (!shear)
03048 return;
03049
03050 for (f2=b->brush_faces ; f2 ; f2=f2->next)
03051 {
03052 if (f2 == f)
03053 continue;
03054 w = Brush_MakeFaceWinding (b, f2);
03055 if (!w)
03056 continue;
03057
03058
03059 for (i=0 ; i<w->numpoints ; i++)
03060 {
03061 d = DotProduct (w->points[i], f->plane.normal)
03062 - f->plane.dist;
03063 if (d > -ON_EPSILON && d < ON_EPSILON)
03064 break;
03065 }
03066
03067
03068
03069
03070
03071 if (i != w->numpoints)
03072 {
03073 if (i == 0)
03074 {
03075
03076 d = DotProduct (w->points[w->numpoints-1]
03077 , f->plane.normal) - f->plane.dist;
03078 if (d > -ON_EPSILON && d < ON_EPSILON)
03079 i = w->numpoints - 1;
03080 }
03081
03082 AddPlanept (f2->planepts[0]);
03083
03084 VectorCopy (w->points[i], f2->planepts[0]);
03085 if (++i == w->numpoints)
03086 i = 0;
03087
03088
03089 d = DotProduct (w->points[i]
03090 , f->plane.normal) - f->plane.dist;
03091 if (d > -ON_EPSILON && d < ON_EPSILON)
03092 AddPlanept (f2->planepts[1]);
03093
03094 VectorCopy (w->points[i], f2->planepts[1]);
03095 if (++i == w->numpoints)
03096 i = 0;
03097
03098
03099
03100 VectorCopy (w->points[i], f2->planepts[2]);
03101 }
03102
03103 free(w);
03104 }
03105 }
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115 void Brush_SideSelect (brush_t *b, vec3_t origin, vec3_t dir
03116 , qboolean shear)
03117 {
03118 face_t *f, *f2;
03119 vec3_t p1, p2;
03120
03121
03122
03123
03124 for (f=b->brush_faces ; f ; f=f->next)
03125 {
03126 VectorCopy (origin, p1);
03127 VectorMA (origin, 16384, dir, p2);
03128
03129 for (f2=b->brush_faces ; f2 ; f2=f2->next)
03130 {
03131 if (f2 == f)
03132 continue;
03133 ClipLineToFace (p1, p2, f2);
03134 }
03135
03136 if (f2)
03137 continue;
03138
03139 if (VectorCompare (p1, origin))
03140 continue;
03141 if (ClipLineToFace (p1, p2, f))
03142 continue;
03143
03144 Brush_SelectFaceForDragging (b, f, shear);
03145 }
03146
03147
03148 }
03149
03150 void Brush_BuildWindings( brush_t *b, bool bSnap )
03151 {
03152 winding_t *w;
03153 face_t *face;
03154 vec_t v;
03155
03156 if (bSnap)
03157 Brush_SnapPlanepts( b );
03158
03159
03160 b->mins[0] = b->mins[1] = b->mins[2] = 99999;
03161 b->maxs[0] = b->maxs[1] = b->maxs[2] = -99999;
03162
03163 Brush_MakeFacePlanes (b);
03164
03165 face = b->brush_faces;
03166
03167 float fCurveColor = 1.0;
03168
03169 for ( ; face ; face=face->next)
03170 {
03171 int i, j;
03172 free(face->face_winding);
03173 w = face->face_winding = Brush_MakeFaceWinding (b, face);
03174 face->d_texture = Texture_ForName( face->texdef.name );
03175
03176 if (!w)
03177 continue;
03178
03179 for (i=0 ; i<w->numpoints ; i++)
03180 {
03181
03182 for (j=0 ; j<3 ; j++)
03183 {
03184 v = w->points[i][j];
03185 if (v > b->maxs[j])
03186 b->maxs[j] = v;
03187 if (v < b->mins[j])
03188 b->mins[j] = v;
03189 }
03190 }
03191
03192
03193
03194 Face_SetColor (b, face, fCurveColor);
03195
03196
03197 fCurveColor -= .10;
03198 if (fCurveColor <= 0)
03199 fCurveColor = 1.0;
03200
03201
03202 if (g_qeglobals.m_bBrushPrimitMode)
03203 {
03204 if (g_qeglobals.bNeedConvert)
03205 {
03206
03207
03208 FaceToBrushPrimitFace(face);
03209 #ifdef _DEBUG
03210
03211 for (i=0 ; i<w->numpoints ; i++)
03212 EmitTextureCoordinates( w->points[i], face->d_texture, face);
03213 #endif
03214 }
03215
03216
03217 EmitBrushPrimitTextureCoordinates(face,w);
03218 }
03219 else
03220 {
03221 for (i=0 ; i<w->numpoints ; i++)
03222 EmitTextureCoordinates( w->points[i], face->d_texture, face);
03223 }
03224 }
03225 }
03226
03227
03228
03229
03230
03231
03232
03233
03234 void Brush_RemoveEmptyFaces ( brush_t *b )
03235 {
03236 face_t *f, *next;
03237
03238 f = b->brush_faces;
03239 b->brush_faces = NULL;
03240
03241 for ( ; f ; f=next)
03242 {
03243 next = f->next;
03244 if (!f->face_winding)
03245 Face_Free (f);
03246 else
03247 {
03248 f->next = b->brush_faces;
03249 b->brush_faces = f;
03250 }
03251
03252 }
03253 }
03254
03255 void Brush_SnapToGrid(brush_t *pb)
03256 {
03257 for (face_t *f = pb->brush_faces ; f; f = f->next)
03258 {
03259 for (int i = 0 ;i < 3 ;i++)
03260 {
03261 for (int j = 0 ;j < 3 ; j++)
03262 {
03263 f->planepts[i][j] = floor (f->planepts[i][j] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
03264 }
03265 }
03266 }
03267 Brush_Build(pb);
03268 }
03269
03270 void Brush_Rotate(brush_t *b, vec3_t vAngle, vec3_t vOrigin, bool bBuild)
03271 {
03272 for (face_t* f=b->brush_faces ; f ; f=f->next)
03273 {
03274 for (int i=0 ; i<3 ; i++)
03275 {
03276 VectorRotate(f->planepts[i], vAngle, vOrigin, f->planepts[i]);
03277 }
03278 }
03279 if (bBuild)
03280 {
03281 Brush_Build(b, false, false);
03282 }
03283 }
03284
03285 void Brush_Center(brush_t *b, vec3_t vNewCenter)
03286 {
03287 vec3_t vMid;
03288
03289 for (int j = 0; j < 3; j++)
03290 {
03291 vMid[j] = b->mins[j] + abs((b->maxs[j] - b->mins[j]) * 0.5);
03292 }
03293
03294 VectorSubtract(vNewCenter, vMid, vMid);
03295 Brush_Move(b, vMid, true);
03296
03297 }
03298
03299
03300 void Brush_Resize(brush_t *b, vec3_t vMin, vec3_t vMax)
03301 {
03302 brush_t *b2 = Brush_Create(vMin, vMax, &b->brush_faces->texdef);
03303
03304 face_t *next;
03305 for (face_t *f=b->brush_faces ; f ; f=next)
03306 {
03307 next = f->next;
03308 Face_Free( f );
03309 }
03310
03311 b->brush_faces = b2->brush_faces;
03312
03313
03314 if (b2->next)
03315 Brush_RemoveFromList (b2);
03316 free(b2);
03317 Brush_Build(b, true);
03318 }
03319
03320
03321 eclass_t* HasModel(brush_t *b)
03322 {
03323 vec3_t vMin, vMax;
03324 vMin[0] = vMin[1] = vMin[2] = 9999;
03325 vMax[0] = vMax[1] = vMax[2] = -9999;
03326
03327 if (b->owner->md3Class != NULL)
03328 {
03329 return b->owner->md3Class;
03330 }
03331
03332 if (Eclass_hasModel(b->owner->eclass, vMin, vMax))
03333 {
03334 return b->owner->eclass;
03335 }
03336
03337 eclass_t *e = NULL;
03338
03339 if (b->owner->eclass->nShowFlags & ECLASS_MISCMODEL)
03340 {
03341 char *pModel = ValueForKey(b->owner, "model");
03342 if (pModel != NULL && strlen(pModel) > 0)
03343 {
03344 e = GetCachedModel(b->owner, pModel, vMin, vMax);
03345 if (e != NULL)
03346 {
03347
03348
03349
03350 VectorAdd (vMin, b->owner->origin, vMin);
03351 VectorAdd (vMax, b->owner->origin, vMax);
03352
03353 Brush_Resize(b, vMin, vMax);
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364
03365
03366
03367
03368
03369
03370
03371
03372
03373
03374
03375
03376
03377
03378
03379
03380
03381
03382
03383
03384
03385
03386
03387
03388
03389
03390
03391
03392
03393
03394
03395
03396
03397
03398
03399
03400
03401
03402
03403
03404
03405
03406
03407
03408
03409
03410 b->bModelFailed = false;
03411 }
03412 else
03413 {
03414 b->bModelFailed = true;
03415 }
03416 }
03417 }
03418 return e;
03419 }
03420
03421 static bool g_bInPaintedModel = false;
03422 static bool g_bDoIt = false;
03423 bool PaintedModel(brush_t *b, bool bOkToTexture)
03424 {
03425 if (g_bInPaintedModel)
03426 {
03427 return true;
03428 }
03429
03430 if (g_PrefsDlg.m_nEntityShowState == ENTITY_BOX || b->bModelFailed)
03431 {
03432 return false;
03433 }
03434 else if (!IsBrushSelected(b) && (g_PrefsDlg.m_nEntityShowState & ENTITY_SELECTED_ONLY))
03435 {
03436 return false;
03437 }
03438
03439 g_bInPaintedModel = true;
03440 bool bReturn = false;
03441
03442 eclass_t *pEclass = HasModel(b);
03443
03444 if (pEclass)
03445 {
03446 qglPushAttrib(GL_ALL_ATTRIB_BITS);
03447 entitymodel *model = pEclass->model;
03448
03449
03450 float a = FloatForKey (b->owner, "angle");
03451 while (model != NULL)
03452 {
03453 if (bOkToTexture == false || g_PrefsDlg.m_nEntityShowState & ENTITY_WIREFRAME || model->nTextureBind == -1)
03454 {
03455 qglDisable( GL_CULL_FACE );
03456 qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
03457 qglDisable(GL_TEXTURE_2D);
03458 qglColor3fv(pEclass->color);
03459 }
03460 else
03461 {
03462 qglColor3f(1, 1, 1);
03463 qglEnable(GL_TEXTURE_2D);
03464 qglBindTexture( GL_TEXTURE_2D, model->nTextureBind );
03465 }
03466 vec3_t v;
03467
03468 int i,j;
03469 VectorAdd(b->maxs, b->mins, v);
03470 VectorScale(v, 0.5, v);
03471 VectorCopy(b->owner->origin, v);
03472
03473
03474
03475
03476
03477
03478
03479
03480
03481
03482
03483
03484 float s, c;
03485 if (a)
03486 {
03487 s = sin (a/180*Q_PI);
03488 c = cos (a/180*Q_PI);
03489 }
03490
03491 vec3_t vSin;
03492 vec3_t vCos;
03493 VectorClear(vSin);
03494 VectorClear(vCos);
03495 for ( j = 0; j < 3; j++)
03496 {
03497 if (b->owner->vRotation[j])
03498 {
03499 vSin[j] = sin(b->owner->vRotation[j]/180*Q_PI);
03500 vCos[j] = cos(b->owner->vRotation[j]/180*Q_PI);
03501 }
03502 }
03503
03504
03505 qglBegin (GL_TRIANGLES);
03506
03507 vec5_t vTest[3];
03508 for (i = 0; i < model->nTriCount; i++)
03509 {
03510 for (j = 0; j < 3; j++)
03511 {
03512 #if 1
03513 float x = model->pTriList[i].v[j][0] + v[0];
03514 float y = model->pTriList[i].v[j][1] + v[1];
03515 if (a)
03516 {
03517 float x2 = (((x - v[0]) * c) - ((y - v[1]) * s)) + v[0];
03518 float y2 = (((x - v[0]) * s) + ((y - v[1]) * c)) + v[1];
03519 x = x2;
03520 y = y2;
03521 }
03522
03523 qglTexCoord2f (model->pTriList[i].st[j][0], model->pTriList[i].st[j][1]);
03524 qglVertex3f(x, y, model->pTriList[i].v[j][2] + v[2]);
03525 #else
03526 float x = model->pTriList[i].v[j][0] + v[0];
03527 float y = model->pTriList[i].v[j][1] + v[1];
03528 float z = model->pTriList[i].v[j][2] + v[2];
03529
03530 if (b->owner->vRotation[0])
03531 {
03532 float y2 = (((y - v[1]) * vCos[0]) - ((z - v[2]) * vSin[0])) + v[1];
03533 float z2 = (((y - v[1]) * vSin[0]) + ((z - v[2]) * vCos[0])) + v[2];
03534 y = y2;
03535 z = z2;
03536 }
03537 if (b->owner->vRotation[1])
03538 {
03539 float z2 = (((z - v[2]) * vCos[1]) - ((x - v[0]) * vSin[1])) + v[2];
03540 float x2 = (((z - v[2]) * vSin[1]) + ((x - v[0]) * vCos[1])) + v[0];
03541 x = x2;
03542 z = z2;
03543 }
03544 if (b->owner->vRotation[2])
03545 {
03546 float x2 = (((x - v[0]) * vCos[2]) - ((y - v[1]) * vSin[2])) + v[0];
03547 float y2 = (((x - v[0]) * vSin[2]) + ((y - v[1]) * vCos[2])) + v[1];
03548 x = x2;
03549 y = y2;
03550 }
03551 qglTexCoord2f (model->pTriList[i].st[j][0], model->pTriList[i].st[j][1]);
03552 qglVertex3f(x, y, z);
03553 #endif
03554 if (g_bDoIt)
03555 {
03556 vTest[j][0] = x;
03557 vTest[j][1] = y;
03558 vTest[j][2] = model->pTriList[i].v[j][2] + v[2];
03559 vTest[j][3] = model->pTriList[i].st[j][0];
03560 vTest[j][4] = model->pTriList[i].st[j][1];
03561 }
03562
03563 }
03564 if (g_bDoIt)
03565 {
03566 Patch_FromTriangle(vTest[0], vTest[1], vTest[2]);
03567 }
03568 }
03569 qglEnd();
03570 if (g_PrefsDlg.m_nEntityShowState & ENTITY_WIREFRAME)
03571 {
03572 qglEnable(GL_CULL_FACE );
03573 qglEnable(GL_TEXTURE_2D);
03574 qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
03575 }
03576 else
03577 {
03578 qglDisable(GL_TEXTURE_2D);
03579 }
03580 model = model->pNext;
03581 }
03582
03583 if (g_bDoIt)
03584 {
03585 g_bDoIt = false;
03586 }
03587
03588 vec3_t vColor;
03589 VectorScale(pEclass->color, 0.50, vColor);
03590
03591 vec3_t vCenter, vMin, vMax;
03592 VectorCopy(b->owner->origin, vCenter);
03593
03594 qglColor3fv(vColor);
03595 qglPointSize(4);
03596
03597 qglBegin(GL_POINTS);
03598 qglVertex3fv(b->owner->origin);
03599 qglEnd();
03600
03601 qglBegin(GL_LINES);
03602 vCenter[0] -= 8;
03603 qglVertex3fv(vCenter);
03604 vCenter[0] += 16;
03605 qglVertex3fv(vCenter);
03606 vCenter[0] -= 8;
03607 vCenter[1] -= 8;
03608 qglVertex3fv(vCenter);
03609 vCenter[1] += 16;
03610 qglVertex3fv(vCenter);
03611 vCenter[1] -= 8;
03612 vCenter[2] -= 8;
03613 qglVertex3fv(vCenter);
03614 vCenter[2] += 16;
03615 qglVertex3fv(vCenter);
03616 vCenter[2] -= 8;
03617 qglEnd();
03618
03619 VectorCopy(vCenter, vMin);
03620 VectorCopy(vCenter, vMax);
03621 vMin[0] -= 4;
03622 vMin[1] -= 4;
03623 vMin[2] -= 4;
03624 vMax[0] += 4;
03625 vMax[1] += 4;
03626 vMax[2] += 4;
03627
03628 qglBegin(GL_LINE_LOOP);
03629 qglVertex3f(vMin[0],vMin[1],vMin[2]);
03630 qglVertex3f(vMax[0],vMin[1],vMin[2]);
03631 qglVertex3f(vMax[0],vMax[1],vMin[2]);
03632 qglVertex3f(vMin[0],vMax[1],vMin[2]);
03633 qglEnd();
03634
03635 qglBegin(GL_LINE_LOOP);
03636 qglVertex3f(vMin[0],vMin[1],vMax[2]);
03637 qglVertex3f(vMax[0],vMin[1],vMax[2]);
03638 qglVertex3f(vMax[0],vMax[1],vMax[2]);
03639 qglVertex3f(vMin[0],vMax[1],vMax[2]);
03640 qglEnd();
03641
03642 qglBegin(GL_LINES);
03643 qglVertex3f(vMin[0],vMin[1],vMin[2]);
03644 qglVertex3f(vMin[0],vMin[1],vMax[2]);
03645 qglVertex3f(vMin[0],vMax[1],vMax[2]);
03646 qglVertex3f(vMin[0],vMax[1],vMin[2]);
03647 qglVertex3f(vMax[0],vMin[1],vMin[2]);
03648 qglVertex3f(vMax[0],vMin[1],vMax[2]);
03649 qglVertex3f(vMax[0],vMax[1],vMax[2]);
03650 qglVertex3f(vMax[0],vMax[1],vMin[2]);
03651 qglEnd();
03652
03653
03654 if (g_PrefsDlg.m_nEntityShowState & ENTITY_BOXED)
03655 {
03656 qglColor3fv(pEclass->color);
03657
03658 vec3_t mins, maxs;
03659 VectorCopy(b->mins, mins);
03660 VectorCopy(b->maxs, maxs);
03661
03662
03663
03664
03665
03666
03667
03668
03669
03670
03671 qglBegin(GL_LINE_LOOP);
03672 qglVertex3f(mins[0],mins[1],mins[2]);
03673 qglVertex3f(maxs[0],mins[1],mins[2]);
03674 qglVertex3f(maxs[0],maxs[1],mins[2]);
03675 qglVertex3f(mins[0],maxs[1],mins[2]);
03676 qglEnd();
03677
03678 qglBegin(GL_LINE_LOOP);
03679 qglVertex3f(mins[0],mins[1],maxs[2]);
03680 qglVertex3f(maxs[0],mins[1],maxs[2]);
03681 qglVertex3f(maxs[0],maxs[1],maxs[2]);
03682 qglVertex3f(mins[0],maxs[1],maxs[2]);
03683 qglEnd();
03684
03685 qglBegin(GL_LINES);
03686 qglVertex3f(mins[0],mins[1],mins[2]);
03687 qglVertex3f(mins[0],mins[1],maxs[2]);
03688 qglVertex3f(mins[0],maxs[1],maxs[2]);
03689 qglVertex3f(mins[0],maxs[1],mins[2]);
03690 qglVertex3f(maxs[0],mins[1],mins[2]);
03691 qglVertex3f(maxs[0],mins[1],maxs[2]);
03692 qglVertex3f(maxs[0],maxs[1],maxs[2]);
03693 qglVertex3f(maxs[0],maxs[1],mins[2]);
03694 qglEnd();
03695 }
03696 qglPopAttrib();
03697 bReturn = true;
03698 }
03699 else
03700 {
03701 b->bModelFailed = true;
03702 }
03703
03704 g_bInPaintedModel = false;
03705 return bReturn;
03706 }
03707
03708
03709
03710
03711
03712
03713
03714
03715
03716
03717
03718
03719
03720
03721
03722
03723
03724
03725
03726
03727
03728
03729
03730
03731
03732
03733
03734
03735
03736
03737
03738
03739
03740
03741
03742
03743
03744
03745
03746 void FacingVectors (entity_t *e, vec3_t forward, vec3_t right, vec3_t up)
03747 {
03748 int angleVal;
03749 vec3_t angles;
03750
03751 angleVal = IntForKey(e, "angle");
03752 if (angleVal == -1)
03753 {
03754 VectorSet(angles, 270, 0, 0);
03755 }
03756 else if(angleVal == -2)
03757 {
03758 VectorSet(angles, 90, 0, 0);
03759 }
03760 else
03761 {
03762 VectorSet(angles, 0, angleVal, 0);
03763 }
03764
03765 AngleVectors(angles, forward, right, up);
03766 }
03767
03768 void Brush_DrawFacingAngle (brush_t *b, entity_t *e)
03769 {
03770 vec3_t forward, right, up;
03771 vec3_t endpoint, tip1, tip2;
03772 vec3_t start;
03773 float dist;
03774
03775 VectorAdd(e->brushes.onext->mins, e->brushes.onext->maxs, start);
03776 VectorScale(start, 0.5, start);
03777 dist = (b->maxs[0] - start[0]) * 2.5;
03778
03779 FacingVectors (e, forward, right, up);
03780 VectorMA (start, dist, forward, endpoint);
03781
03782 dist = (b->maxs[0] - start[0]) * 0.5;
03783 VectorMA (endpoint, -dist, forward, tip1);
03784 VectorMA (tip1, -dist, up, tip1);
03785 VectorMA (tip1, 2*dist, up, tip2);
03786
03787 qglColor4f (1, 1, 1, 1);
03788 qglLineWidth (4);
03789 qglBegin (GL_LINES);
03790 qglVertex3fv (start);
03791 qglVertex3fv (endpoint);
03792 qglVertex3fv (endpoint);
03793 qglVertex3fv (tip1);
03794 qglVertex3fv (endpoint);
03795 qglVertex3fv (tip2);
03796 qglEnd ();
03797 qglLineWidth (1);
03798 }
03799
03800 void DrawLight(brush_t *b)
03801 {
03802 vec3_t vTriColor;
03803 bool bTriPaint = false;
03804
03805 vTriColor[0] = vTriColor[2] = 1.0;
03806 vTriColor[1] = 1.0;
03807 bTriPaint = true;
03808 CString strColor = ValueForKey(b->owner, "_color");
03809 if (strColor.GetLength() > 0)
03810 {
03811 float fR, fG, fB;
03812 int n = sscanf(strColor,"%f %f %f", &fR, &fG, &fB);
03813 if (n == 3)
03814 {
03815 vTriColor[0] = fR;
03816 vTriColor[1] = fG;
03817 vTriColor[2] = fB;
03818 }
03819 }
03820 qglColor3f(vTriColor[0], vTriColor[1], vTriColor[2]);
03821
03822 vec3_t vCorners[4];
03823 float fMid = b->mins[2] + (b->maxs[2] - b->mins[2]) / 2;
03824
03825 vCorners[0][0] = b->mins[0];
03826 vCorners[0][1] = b->mins[1];
03827 vCorners[0][2] = fMid;
03828
03829 vCorners[1][0] = b->mins[0];
03830 vCorners[1][1] = b->maxs[1];
03831 vCorners[1][2] = fMid;
03832
03833 vCorners[2][0] = b->maxs[0];
03834 vCorners[2][1] = b->maxs[1];
03835 vCorners[2][2] = fMid;
03836
03837 vCorners[3][0] = b->maxs[0];
03838 vCorners[3][1] = b->mins[1];
03839 vCorners[3][2] = fMid;
03840
03841 vec3_t vTop, vBottom;
03842
03843 vTop[0] = b->mins[0] + ((b->maxs[0] - b->mins[0]) / 2);
03844 vTop[1] = b->mins[1] + ((b->maxs[1] - b->mins[1]) / 2);
03845 vTop[2] = b->maxs[2];
03846
03847 VectorCopy(vTop, vBottom);
03848 vBottom[2] = b->mins[2];
03849
03850 vec3_t vSave;
03851 VectorCopy(vTriColor, vSave);
03852
03853 qglBegin(GL_TRIANGLE_FAN);
03854 qglVertex3fv(vTop);
03855 for (int i = 0; i <= 3; i++)
03856 {
03857 vTriColor[0] *= 0.95;
03858 vTriColor[1] *= 0.95;
03859 vTriColor[2] *= 0.95;
03860 qglColor3f(vTriColor[0], vTriColor[1], vTriColor[2]);
03861 qglVertex3fv(vCorners[i]);
03862 }
03863 qglVertex3fv(vCorners[0]);
03864 qglEnd();
03865
03866 VectorCopy(vSave, vTriColor);
03867 vTriColor[0] *= 0.95;
03868 vTriColor[1] *= 0.95;
03869 vTriColor[2] *= 0.95;
03870
03871 qglBegin(GL_TRIANGLE_FAN);
03872 qglVertex3fv(vBottom);
03873 qglVertex3fv(vCorners[0]);
03874 for (i = 3; i >= 0; i--)
03875 {
03876 vTriColor[0] *= 0.95;
03877 vTriColor[1] *= 0.95;
03878 vTriColor[2] *= 0.95;
03879 qglColor3f(vTriColor[0], vTriColor[1], vTriColor[2]);
03880 qglVertex3fv(vCorners[i]);
03881 }
03882 qglEnd();
03883
03884
03885 CString str = ValueForKey(b->owner, "light_right");
03886 if (str.GetLength() > 0) {
03887 vec3_t vRight, vUp, vTarget, vTemp;
03888 GetVectorForKey (b->owner, "light_right", vRight);
03889 GetVectorForKey (b->owner, "light_up", vUp);
03890 GetVectorForKey (b->owner, "light_target", vTarget);
03891
03892 qglColor3f(0, 1, 0);
03893 qglBegin(GL_LINE_LOOP);
03894 VectorAdd(vTarget, b->owner->origin, vTemp);
03895 VectorAdd(vTemp, vRight, vTemp);
03896 VectorAdd(vTemp, vUp, vTemp);
03897 qglVertex3fv(b->owner->origin);
03898 qglVertex3fv(vTemp);
03899 VectorAdd(vTarget, b->owner->origin, vTemp);
03900 VectorAdd(vTemp, vUp, vTemp);
03901 VectorSubtract(vTemp, vRight, vTemp);
03902 qglVertex3fv(b->owner->origin);
03903 qglVertex3fv(vTemp);
03904 VectorAdd(vTarget, b->owner->origin, vTemp);
03905 VectorAdd(vTemp, vRight, vTemp);
03906 VectorSubtract(vTemp, vUp, vTemp);
03907 qglVertex3fv(b->owner->origin);
03908 qglVertex3fv(vTemp);
03909 VectorAdd(vTarget, b->owner->origin, vTemp);
03910 VectorSubtract(vTemp, vUp, vTemp);
03911 VectorSubtract(vTemp, vRight, vTemp);
03912 qglVertex3fv(b->owner->origin);
03913 qglVertex3fv(vTemp);
03914 qglEnd();
03915
03916 }
03917
03918 }
03919
03920 void Brush_Draw( brush_t *b )
03921 {
03922 face_t *face;
03923 int i, order;
03924 qtexture_t *prev = 0;
03925 winding_t *w;
03926
03927 if ( b->owner && ( b->owner->eclass->nShowFlags & ECLASS_PLUGINENTITY ) )
03928 {
03929 b->owner->pPlugEnt->CamRender();
03930 return;
03931 }
03932
03933
03934 if (b->hiddenBrush)
03935 {
03936 return;
03937 }
03938
03939 if (b->patchBrush)
03940 {
03941
03942 Patch_DrawCam(b->pPatch);
03943
03944 return;
03945 }
03946
03947 if (b->terrainBrush)
03948 {
03949 Terrain_DrawCam(b->pTerrain);
03950 return;
03951 }
03952
03953 int nDrawMode = g_pParentWnd->GetCamera()->Camera().draw_mode;
03954
03955 if (b->owner->eclass->fixedsize)
03956 {
03957
03958 if (!(g_qeglobals.d_savedinfo.exclude & EXCLUDE_ANGLES) && (b->owner->eclass->nShowFlags & ECLASS_ANGLE))
03959 {
03960 Brush_DrawFacingAngle(b, b->owner);
03961 }
03962
03963 if (g_PrefsDlg.m_bNewLightDraw && (b->owner->eclass->nShowFlags & ECLASS_LIGHT))
03964 {
03965 DrawLight(b);
03966 return;
03967 }
03968 if (nDrawMode == cd_texture || nDrawMode == cd_light)
03969 qglDisable (GL_TEXTURE_2D);
03970
03971
03972 bool bp = (b->bModelFailed) ? false : PaintedModel(b, true);
03973
03974 if (nDrawMode == cd_texture || nDrawMode == cd_light)
03975 qglEnable (GL_TEXTURE_2D);
03976
03977 if (bp)
03978 return;
03979 }
03980
03981
03982 prev = NULL;
03983 for (face = b->brush_faces,order = 0 ; face ; face=face->next, order++)
03984 {
03985 w = face->face_winding;
03986 if (!w)
03987 {
03988 continue;
03989 }
03990
03991 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK)
03992 {
03993 if (strstr(face->texdef.name, "caulk"))
03994 {
03995 continue;
03996 }
03997 }
03998
03999 #if 0
04000 if (b->alphaBrush)
04001 {
04002 if (!(face->texdef.flags & SURF_ALPHA))
04003 continue;
04004
04005 qglDisable(GL_CULL_FACE);
04006
04007
04008
04009
04010
04011 }
04012 #endif
04013
04014 if ((nDrawMode == cd_texture || nDrawMode == cd_light) && face->d_texture != prev)
04015 {
04016
04017 prev = face->d_texture;
04018 qglBindTexture( GL_TEXTURE_2D, face->d_texture->texture_number );
04019 }
04020
04021
04022
04023 if (!b->patchBrush)
04024 {
04025 if (face->texdef.flags & SURF_TRANS33)
04026 qglColor4f ( face->d_color[0], face->d_color[1], face->d_color[2], 0.33 );
04027 else if ( face->texdef.flags & SURF_TRANS66)
04028 qglColor4f ( face->d_color[0], face->d_color[1], face->d_color[2], 0.66 );
04029 else
04030 qglColor3fv( face->d_color );
04031 }
04032 else
04033 {
04034 qglColor4f ( face->d_color[0], face->d_color[1], face->d_color[2], 0.13 );
04035 }
04036
04037
04038 if (face->d_texture->bFromShader)
04039 {
04040
04041 qglColor4f ( face->d_color[0], face->d_color[1], face->d_color[2], face->d_texture->fTrans );
04042
04043 }
04044
04045
04046
04047
04048
04049 if (g_PrefsDlg.m_bGLLighting)
04050 {
04051 qglNormal3fv(face->plane.normal);
04052 }
04053
04054
04055 qglBegin(GL_POLYGON);
04056
04057
04058 for (i=0 ; i<w->numpoints ; i++)
04059 {
04060 if (nDrawMode == cd_texture || nDrawMode == cd_light)
04061 qglTexCoord2fv( &w->points[i][3] );
04062 qglVertex3fv(w->points[i]);
04063 }
04064 qglEnd();
04065 }
04066
04067 #if 0
04068 if (b->alphaBrush)
04069 {
04070
04071 qglEnable(GL_CULL_FACE);
04072
04073
04074 }
04075 #endif
04076
04077 if (b->owner->eclass->fixedsize && (nDrawMode == cd_texture || nDrawMode == cd_light))
04078 qglEnable (GL_TEXTURE_2D);
04079
04080 qglBindTexture( GL_TEXTURE_2D, 0 );
04081 }
04082
04083
04084
04085 void Face_Draw( face_t *f )
04086 {
04087 int i;
04088
04089 if ( f->face_winding == 0 )
04090 return;
04091 qglBegin( GL_POLYGON );
04092 for ( i = 0 ; i < f->face_winding->numpoints; i++)
04093 qglVertex3fv( f->face_winding->points[i] );
04094 qglEnd();
04095 }
04096
04097 void Brush_DrawXY(brush_t *b, int nViewType)
04098 {
04099 face_t *face;
04100 int order;
04101 winding_t *w;
04102 int i;
04103
04104 if (b->hiddenBrush)
04105 {
04106 return;
04107 }
04108
04109 if (b->patchBrush)
04110 {
04111
04112 Patch_DrawXY(b->pPatch);
04113 if (!g_bPatchShowBounds)
04114 return;
04115 }
04116
04117 if (b->terrainBrush)
04118 {
04119 Terrain_DrawXY(b->pTerrain, b->owner);
04120 }
04121
04122
04123 if (b->owner->eclass->fixedsize)
04124 {
04125 if (g_PrefsDlg.m_bNewLightDraw && (b->owner->eclass->nShowFlags & ECLASS_LIGHT))
04126 {
04127 vec3_t vCorners[4];
04128 float fMid = b->mins[2] + (b->maxs[2] - b->mins[2]) / 2;
04129
04130 vCorners[0][0] = b->mins[0];
04131 vCorners[0][1] = b->mins[1];
04132 vCorners[0][2] = fMid;
04133
04134 vCorners[1][0] = b->mins[0];
04135 vCorners[1][1] = b->maxs[1];
04136 vCorners[1][2] = fMid;
04137
04138 vCorners[2][0] = b->maxs[0];
04139 vCorners[2][1] = b->maxs[1];
04140 vCorners[2][2] = fMid;
04141
04142 vCorners[3][0] = b->maxs[0];
04143 vCorners[3][1] = b->mins[1];
04144 vCorners[3][2] = fMid;
04145
04146 vec3_t vTop, vBottom;
04147
04148 vTop[0] = b->mins[0] + ((b->maxs[0] - b->mins[0]) / 2);
04149 vTop[1] = b->mins[1] + ((b->maxs[1] - b->mins[1]) / 2);
04150 vTop[2] = b->maxs[2];
04151
04152 VectorCopy(vTop, vBottom);
04153 vBottom[2] = b->mins[2];
04154
04155 qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
04156 qglBegin(GL_TRIANGLE_FAN);
04157 qglVertex3fv(vTop);
04158 qglVertex3fv(vCorners[0]);
04159 qglVertex3fv(vCorners[1]);
04160 qglVertex3fv(vCorners[2]);
04161 qglVertex3fv(vCorners[3]);
04162 qglVertex3fv(vCorners[0]);
04163 qglEnd();
04164 qglBegin(GL_TRIANGLE_FAN);
04165 qglVertex3fv(vBottom);
04166 qglVertex3fv(vCorners[0]);
04167 qglVertex3fv(vCorners[3]);
04168 qglVertex3fv(vCorners[2]);
04169 qglVertex3fv(vCorners[1]);
04170 qglVertex3fv(vCorners[0]);
04171 qglEnd();
04172 DrawBrushEntityName (b);
04173 return;
04174 }
04175 else if (b->owner->eclass->nShowFlags & ECLASS_MISCMODEL)
04176 {
04177 if (PaintedModel(b, false))
04178 return;
04179 }
04180 }
04181
04182 for (face = b->brush_faces,order = 0 ; face ; face=face->next, order++)
04183 {
04184
04185 if (nViewType == XY)
04186 {
04187 if (face->plane.normal[2] <= 0)
04188 continue;
04189 }
04190 else
04191 {
04192 if (nViewType == XZ)
04193 {
04194 if (face->plane.normal[1] <= 0)
04195 continue;
04196 }
04197 else
04198 {
04199 if (face->plane.normal[0] <= 0)
04200 continue;
04201 }
04202 }
04203
04204 w = face->face_winding;
04205 if (!w)
04206 continue;
04207
04208
04209
04210
04211
04212 qglBegin(GL_LINE_LOOP);
04213 for (i=0 ; i<w->numpoints ; i++)
04214 qglVertex3fv(w->points[i]);
04215 qglEnd();
04216 }
04217
04218 DrawBrushEntityName (b);
04219
04220 }
04221
04222
04223
04224
04225
04226
04227 void Brush_Move (brush_t *b, const vec3_t move, bool bSnap)
04228 {
04229 int i;
04230 face_t *f;
04231
04232 for (f=b->brush_faces ; f ; f=f->next)
04233 {
04234 vec3_t vTemp;
04235 VectorCopy(move, vTemp);
04236
04237 if (g_PrefsDlg.m_bTextureLock)
04238 Face_MoveTexture(f, vTemp);
04239
04240 for (i=0 ; i<3 ; i++)
04241 VectorAdd (f->planepts[i], move, f->planepts[i]);
04242 }
04243 Brush_Build( b, bSnap );
04244
04245
04246 if (b->patchBrush)
04247 {
04248
04249 Patch_Move(b->pPatch, move);
04250 }
04251
04252 if (b->terrainBrush)
04253 {
04254 Terrain_Move(b->pTerrain, move);
04255 }
04256
04257
04258
04259 if(b->owner->eclass->fixedsize)
04260 {
04261 VectorAdd(b->owner->origin, move, b->owner->origin);
04262
04263
04264 }
04265 }
04266
04267
04268
04269 void Brush_Print(brush_t* b)
04270 {
04271 int nFace = 0;
04272 for (face_t* f = b->brush_faces ; f ; f=f->next)
04273 {
04274 Sys_Printf("Face %i\n", nFace++);
04275 Sys_Printf("%f %f %f\n", f->planepts[0][0], f->planepts[0][1], f->planepts[0][2]);
04276 Sys_Printf("%f %f %f\n", f->planepts[1][0], f->planepts[1][1], f->planepts[1][2]);
04277 Sys_Printf("%f %f %f\n", f->planepts[2][0], f->planepts[2][1], f->planepts[2][2]);
04278 }
04279 }
04280
04281
04282
04283
04284
04285
04286
04287
04288
04289
04290 void Brush_MakeSidedCone(int sides)
04291 {
04292 int i;
04293 vec3_t mins, maxs;
04294 brush_t *b;
04295 texdef_t *texdef;
04296 face_t *f;
04297 vec3_t mid;
04298 float width;
04299 float sv, cv;
04300
04301 if (sides < 3)
04302 {
04303 Sys_Status ("Bad sides number", 0);
04304 return;
04305 }
04306
04307 if (!QE_SingleBrush ())
04308 {
04309 Sys_Status ("Must have a single brush selected", 0 );
04310 return;
04311 }
04312
04313 b = selected_brushes.next;
04314 VectorCopy (b->mins, mins);
04315 VectorCopy (b->maxs, maxs);
04316 texdef = &g_qeglobals.d_texturewin.texdef;
04317
04318 Brush_Free (b);
04319
04320
04321 width = 8;
04322 for (i=0 ; i<2 ; i++)
04323 {
04324 mid[i] = (maxs[i] + mins[i])*0.5;
04325 if (maxs[i] - mins[i] > width)
04326 width = maxs[i] - mins[i];
04327 }
04328 width /= 2;
04329
04330 b = Brush_Alloc();
04331
04332
04333 f = Face_Alloc();
04334 f->texdef = *texdef;
04335 f->next = b->brush_faces;
04336 b->brush_faces = f;
04337
04338 f->planepts[0][0] = mins[0];f->planepts[0][1] = mins[1];f->planepts[0][2] = mins[2];
04339 f->planepts[1][0] = maxs[0];f->planepts[1][1] = mins[1];f->planepts[1][2] = mins[2];
04340 f->planepts[2][0] = maxs[0];f->planepts[2][1] = maxs[1];f->planepts[2][2] = mins[2];
04341
04342 for (i=0 ; i<sides ; i++)
04343 {
04344 f = Face_Alloc();
04345 f->texdef = *texdef;
04346 f->next = b->brush_faces;
04347 b->brush_faces = f;
04348
04349 sv = sin (i*3.14159265*2/sides);
04350 cv = cos (i*3.14159265*2/sides);
04351
04352
04353 f->planepts[0][0] = floor(mid[0]+width*cv+0.5);
04354 f->planepts[0][1] = floor(mid[1]+width*sv+0.5);
04355 f->planepts[0][2] = mins[2];
04356
04357 f->planepts[1][0] = mid[0];
04358 f->planepts[1][1] = mid[1];
04359 f->planepts[1][2] = maxs[2];
04360
04361 f->planepts[2][0] = floor(f->planepts[0][0] - width * sv + 0.5);
04362 f->planepts[2][1] = floor(f->planepts[0][1] + width * cv + 0.5);
04363 f->planepts[2][2] = maxs[2];
04364
04365 }
04366
04367 Brush_AddToList (b, &selected_brushes);
04368
04369 Entity_LinkBrush (world_entity, b);
04370
04371 Brush_Build( b );
04372
04373 Sys_UpdateWindows (W_ALL);
04374 }
04375
04376
04377
04378
04379
04380
04381
04382
04383
04384 void Brush_MakeSidedSphere(int sides)
04385 {
04386 int i,j;
04387 vec3_t mins, maxs;
04388 brush_t *b;
04389 texdef_t *texdef;
04390 face_t *f;
04391 vec3_t mid;
04392
04393 if (sides < 4)
04394 {
04395 Sys_Status ("Bad sides number", 0);
04396 return;
04397 }
04398
04399 if (!QE_SingleBrush ())
04400 {
04401 Sys_Status ("Must have a single brush selected", 0 );
04402 return;
04403 }
04404
04405 b = selected_brushes.next;
04406 VectorCopy (b->mins, mins);
04407 VectorCopy (b->maxs, maxs);
04408 texdef = &g_qeglobals.d_texturewin.texdef;
04409
04410 Brush_Free (b);
04411
04412
04413 float radius = 8;
04414 for (i=0 ; i<2 ; i++)
04415 {
04416 mid[i] = (maxs[i] + mins[i])*0.5;
04417 if (maxs[i] - mins[i] > radius)
04418 radius = maxs[i] - mins[i];
04419 }
04420 radius /= 2;
04421
04422 b = Brush_Alloc();
04423
04424 float dt = float(2 * Q_PI / sides);
04425 float dp = float(Q_PI / sides);
04426 float t,p;
04427 for(i=0; i <= sides-1; i++)
04428 {
04429 for(j=0;j <= sides-2; j++)
04430 {
04431 t = i * dt;
04432 p = float(j * dp - Q_PI / 2);
04433
04434 f = Face_Alloc();
04435 f->texdef = *texdef;
04436 f->next = b->brush_faces;
04437 b->brush_faces = f;
04438
04439 VectorPolar(f->planepts[0], radius, t, p);
04440 VectorPolar(f->planepts[1], radius, t, p + dp);
04441 VectorPolar(f->planepts[2], radius, t + dt, p + dp);
04442
04443 for (int k = 0; k < 3; k++)
04444 VectorAdd(f->planepts[k], mid, f->planepts[k]);
04445 }
04446 }
04447
04448 p = float((sides - 1) * dp - Q_PI / 2);
04449 for(i = 0; i <= sides-1; i++)
04450 {
04451 t = i * dt;
04452
04453 f = Face_Alloc();
04454 f->texdef = *texdef;
04455 f->next = b->brush_faces;
04456 b->brush_faces = f;
04457
04458 VectorPolar(f->planepts[0], radius, t, p);
04459 VectorPolar(f->planepts[1], radius, t + dt, p + dp);
04460 VectorPolar(f->planepts[2], radius, t + dt, p);
04461
04462 for (int k = 0; k < 3; k++)
04463 VectorAdd(f->planepts[k], mid, f->planepts[k]);
04464 }
04465
04466 Brush_AddToList (b, &selected_brushes);
04467
04468 Entity_LinkBrush (world_entity, b);
04469
04470 Brush_Build( b );
04471
04472 Sys_UpdateWindows (W_ALL);
04473 }
04474
04475 void Face_FitTexture( face_t * face, int nHeight, int nWidth )
04476 {
04477 winding_t *w;
04478 vec3_t mins,maxs;
04479 int i;
04480 float width, height, temp;
04481 float rot_width, rot_height;
04482 float cosv,sinv,ang;
04483 float min_t, min_s, max_t, max_s;
04484 float s,t;
04485 vec3_t vecs[2];
04486 vec3_t coords[4];
04487 texdef_t *td;
04488
04489 if (nHeight < 1)
04490 {
04491 nHeight = 1;
04492 }
04493 if (nWidth < 1)
04494 {
04495 nWidth = 1;
04496 }
04497
04498 ClearBounds (mins, maxs);
04499
04500 td = &face->texdef;
04501 w = face->face_winding;
04502 if (!w)
04503 {
04504 return;
04505 }
04506 for (i=0 ; i<w->numpoints ; i++)
04507 {
04508 AddPointToBounds( w->points[i], mins, maxs );
04509 }
04510
04511
04512
04513 ang = td->rotate / 180 * Q_PI;
04514 sinv = sin(ang);
04515 cosv = cos(ang);
04516
04517
04518 TextureAxisFromPlane(&face->plane, vecs[0], vecs[1]);
04519
04520 min_s = DotProduct( mins, vecs[0] );
04521 min_t = DotProduct( mins, vecs[1] );
04522 max_s = DotProduct( maxs, vecs[0] );
04523 max_t = DotProduct( maxs, vecs[1] );
04524 width = max_s - min_s;
04525 height = max_t - min_t;
04526 coords[0][0] = min_s;
04527 coords[0][1] = min_t;
04528 coords[1][0] = max_s;
04529 coords[1][1] = min_t;
04530 coords[2][0] = min_s;
04531 coords[2][1] = max_t;
04532 coords[3][0] = max_s;
04533 coords[3][1] = max_t;
04534 min_s = min_t = 99999;
04535 max_s = max_t = -99999;
04536 for (i=0; i<4; i++)
04537 {
04538 s = cosv * coords[i][0] - sinv * coords[i][1];
04539 t = sinv * coords[i][0] + cosv * coords[i][1];
04540 if (i&1)
04541 {
04542 if (s > max_s)
04543 {
04544 max_s = s;
04545 }
04546 }
04547 else
04548 {
04549 if (s < min_s)
04550 {
04551 min_s = s;
04552 }
04553 if (i<2)
04554 {
04555 if (t < min_t)
04556 {
04557 min_t = t;
04558 }
04559 }
04560 else
04561 {
04562 if (t > max_t)
04563 {
04564 max_t = t;
04565 }
04566 }
04567 }
04568 }
04569 rot_width = (max_s - min_s);
04570 rot_height = (max_t - min_t);
04571 td->scale[0] = -(rot_width/((float)(face->d_texture->width*nWidth)));
04572 td->scale[1] = -(rot_height/((float)(face->d_texture->height*nHeight)));
04573
04574 td->shift[0] = min_s/td->scale[0];
04575 temp = (int)(td->shift[0] / (face->d_texture->width*nWidth));
04576 temp = (temp+1)*face->d_texture->width*nWidth;
04577 td->shift[0] = (int)(temp - td->shift[0])%(face->d_texture->width*nWidth);
04578
04579 td->shift[1] = min_t/td->scale[1];
04580 temp = (int)(td->shift[1] / (face->d_texture->height*nHeight));
04581 temp = (temp+1)*(face->d_texture->height*nHeight);
04582 td->shift[1] = (int)(temp - td->shift[1])%(face->d_texture->height*nHeight);
04583 }
04584
04585 void Brush_FitTexture( brush_t *b, int nHeight, int nWidth )
04586 {
04587 face_t *face;
04588
04589 for (face = b->brush_faces ; face ; face=face->next)
04590 {
04591 Face_FitTexture( face, nHeight, nWidth );
04592 }
04593 }
04594
04595