doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
autocaulk.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #include "../../idlib/precompiled.h"
30 #pragma hdrstop
31 
32 #include "qe3.h"
33 #include "Radiant.h"
34 #include "autocaulk.h"
35 
36 // Note: the code in here looks pretty goofy in places, and probably doesn't use the new Q4 class stuff fully,
37 // but I just got it in and compiling from the JK2/SOF2 Radiants via some ugly code replaces, and it works, so there.
38 // Also, a bunch of Radiant fields no longer exist in this codebase, likewise the whole point of passing in the bool
39 // to this code, but I've just left it as-is. A designer tested it and pronounced it fine.
40 
41 //#pragma warning( disable : 4786)
42 //#include <list>
43 //using namespace std;
44 //#pragma warning( disable : 4786)
45 
46 #undef strnicmp
47 #define strnicmp idStr::Icmpn
48 
49 #if 1
50 
51 
52 //extern void ClearBounds (idVec3 mins, idVec3 maxs);
53 //extern void AddPointToBounds (const idVec3 v, idVec3 mins, idVec3 maxs);
54 void ClearBounds (idVec3 &mins, idVec3 &maxs)
55 {
56  mins[0] = mins[1] = mins[2] = 99999;
57  maxs[0] = maxs[1] = maxs[2] = -99999;
58 }
59 
60 void AddPointToBounds( const idVec3 &v, idVec3 &mins, idVec3 &maxs )
61 {
62  int i;
63  float val;
64 
65  for (i=0 ; i<3 ; i++)
66  {
67  val = v[i];
68  if (val < mins[i])
69  mins[i] = val;
70  if (val > maxs[i])
71  maxs[i] = val;
72  }
73 }
74 
75 
76 static void FloorBounds(idVec3 &mins, idVec3 &maxs)
77 {
78  for (int i=0 ; i<3 ; i++)
79  {
80  mins[i] = floor(mins[i] + 0.5);
81  maxs[i] = floor(maxs[i] + 0.5);
82  }
83 }
84 
85 
86 static LPCSTR vtos(idVec3 &v3)
87 {
88  return va("%.3ff,%.3f,%.3f",v3[0],v3[1],v3[2]);
89 }
91 {
92  face_t* pFace;
93  brush_t* pBrush;
94 };
97 {
98  /*Sys_Printf*/common->Printf("Caulking...\n");
99 
100  FacesToCaulk.Clear();
101 
102  int iSystemBrushesSkipped = 0;
103  face_t *pSelectedFace;
104 
105  brush_t *next;
106  for (brush_t *pSelectedBrush = selected_brushes.next ; pSelectedBrush != &selected_brushes ; pSelectedBrush = next)
107  {
108  next = pSelectedBrush->next;
109 
110  if (pSelectedBrush->owner->eclass->fixedsize)
111  continue; // apparently this means it's a model, so skip it...
112 
113  // new check, we can't caulk a brush that has any "system/" faces...
114  //
115  bool bSystemFacePresent = false;
116  for ( pSelectedFace = pSelectedBrush->brush_faces; pSelectedFace; pSelectedFace = pSelectedFace->next)
117  {
118  if (!strnicmp(pSelectedFace->d_texture->GetName(),"system/",7))
119  {
120  bSystemFacePresent = true;
121  break;
122  }
123  }
124  if (bSystemFacePresent)
125  {
126  iSystemBrushesSkipped++;
127  continue; // verboten to caulk this.
128  }
129 
130  for (int iBrushListToScan = 0; iBrushListToScan<2; iBrushListToScan++)
131  {
132  brush_t *snext;
133  for (brush_t *pScannedBrush = (iBrushListToScan?active_brushes.next:selected_brushes.next); pScannedBrush != (iBrushListToScan?&active_brushes:&selected_brushes) ; pScannedBrush = snext)
134  {
135  snext = pScannedBrush->next;
136 
137  if ( pScannedBrush == pSelectedBrush)
138  continue;
139 
140  if (pScannedBrush->owner->eclass->fixedsize || pScannedBrush->pPatch || pScannedBrush->hiddenBrush)
141  continue;
142 
143  if (FilterBrush(pScannedBrush))
144  continue;
145 
146 // idMaterial stuff no longer support this, not sure what else to do.
147 // Searching for other occurences of QER_NOCARVE just shows people REMing the code and ignoring ths issue...
148 //
149 // if (pScannedBrush->brush_faces->d_texture->bFromShader && (pScannedBrush->brush_faces->d_texture->TestMaterialFlag(QER_NOCARVE)))
150 // continue;
151 
152  // basic-reject first to see if brushes can even possibly touch (coplanar counts as touching)
153  //
154  int i;
155  for (i=0 ; i<3 ; i++)
156  {
157  if (pSelectedBrush->mins[i] > pScannedBrush->maxs[i] ||
158  pSelectedBrush->maxs[i] < pScannedBrush->mins[i])
159  {
160  break;
161  }
162  }
163  if (i != 3)
164  continue; // can't be touching
165 
166  // ok, now for the clever stuff, we need to detect only those faces that are both coplanar and smaller
167  // or equal to the face they're coplanar with...
168  //
169  for (pSelectedFace = pSelectedBrush->brush_faces; pSelectedFace; pSelectedFace = pSelectedFace->next)
170  {
171  idWinding *pSelectedWinding = pSelectedFace->face_winding;
172 
173  if (!pSelectedWinding)
174  continue; // freed face, probably won't happen here, but who knows with this program?
175 
176  // SquaredFace_t SelectedSquaredFace;
177  // WindingToSquaredFace( &SelectedSquaredFace, pSelectedWinding);
178 
179  for (face_t *pScannedFace = pScannedBrush->brush_faces; pScannedFace; pScannedFace = pScannedFace->next)
180  {
181  // don't even try caulking against a system face, because these are often transparent and will leave holes
182  //
183  if (!strnicmp(pScannedFace->d_texture->GetName(),"system/",7))
184  continue;
185 
186  // and don't try caulking against something inherently transparent...
187  //
188  if (pScannedFace->d_texture->TestMaterialFlag(QER_TRANS))
189  continue;
190 
191  idWinding *pScannedWinding = pScannedFace->face_winding;
192 
193  if (!pScannedWinding)
194  continue; // freed face, probably won't happen here, but who knows with this program?
195 
196  // SquaredFace_t ScannedSquaredFace;
197  // WindingToSquaredFace( &ScannedSquaredFace, pScannedWinding);
198 
199  /* if (VectorCompare(ScannedSquaredFace.v3NormalisedRotationVector, SelectedSquaredFace.v3NormalisedRotationVector)
200  &&
201  VectorCompare(ScannedSquaredFace.v3NormalisedElevationVector, SelectedSquaredFace.v3NormalisedElevationVector)
202  )
203  */
204  {
205  // brush faces are in parallel planes to each other, so check that their normals
206  // are opposite, by adding them together and testing for zero...
207  // (if normals are opposite, then faces can be against/touching each other?)
208  //
209  idVec3 v3ZeroTest;
210  idVec3 v3Zero;v3Zero.Zero(); //static idVec3 v3Zero={0,0,0};
211 
212  VectorAdd(pSelectedFace->plane.Normal(),pScannedFace->plane.Normal(),v3ZeroTest);
213  if (v3ZeroTest == v3Zero)
214  {
215  // planes are facing each other...
216  //
217  // coplanar? (this is some maths of Gil's, which I don't even pretend to understand)
218  //
219  float fTotalDist = 0;
220  for (int _i=0; _i<3; _i++)
221  {
222  fTotalDist += fabs( DotProduct(pSelectedFace->plane.Normal(),(*pSelectedWinding)[0])
223  -
224  DotProduct(pSelectedFace->plane.Normal(),(*pScannedWinding)[i])
225  );
226  }
227  //OutputDebugString(va("Dist = %g\n",fTotalDist));
228 
229  if (fTotalDist > 0.01)
230  continue;
231 
232  // every point in the selected face must be within (or equal to) the bounds of the
233  // scanned face...
234  //
235  // work out the bounds first...
236  //
237  idVec3 v3ScannedBoundsMins, v3ScannedBoundsMaxs;
238  ClearBounds (v3ScannedBoundsMins, v3ScannedBoundsMaxs);
239  int iPoint;
240  for (iPoint=0; iPoint<pScannedWinding->GetNumPoints(); iPoint++)
241  {
242  AddPointToBounds( (*pScannedWinding)[iPoint].ToVec3(), v3ScannedBoundsMins, v3ScannedBoundsMaxs);
243  }
244  // floor 'em... (or .001 differences mess things up...
245  //
246  FloorBounds(v3ScannedBoundsMins, v3ScannedBoundsMaxs);
247 
248 
249  // now check points from selected face...
250  //
251  bool bWithin = true;
252  for (iPoint=0; iPoint < pSelectedWinding->GetNumPoints(); iPoint++)
253  {
254  for (int iXYZ=0; iXYZ<3; iXYZ++)
255  {
256  float f = floor((*pSelectedWinding)[iPoint][iXYZ] + 0.5);
257  if (!
258  (
259  f >= v3ScannedBoundsMins[iXYZ]
260  &&
261  f <= v3ScannedBoundsMaxs[iXYZ]
262  )
263  )
264  {
265  bWithin = false;
266  }
267  }
268  }
269 
270  if (bWithin)
271  {
272  PairBrushFace_t PairBrushFace;
273  PairBrushFace.pFace = pSelectedFace;
274  PairBrushFace.pBrush= pSelectedBrush;
275  FacesToCaulk.Append(PairBrushFace);
276  }
277  }
278  }
279  }
280  }
281  }
282  }
283  }
284 
285 
286  // apply caulk...
287  //
288  int iFacesCaulked = 0;
289  if (FacesToCaulk.Num())
290  {
291  LPCSTR psCaulkName = "textures/common/caulk";
292  const idMaterial *pCaulk = Texture_ForName(psCaulkName);
293 
294  if (pCaulk)
295  {
296  //
297  // and call some other junk that Radiant wants so so we can use it later...
298  //
299  texdef_t tex;
300  memset (&tex, 0, sizeof(tex));
301  tex.scale[0] = 1;
302  tex.scale[1] = 1;
303  //tex.flags = pCaulk->flags; // field missing in Q4
304  //tex.value = pCaulk->value; // ditto
305  //tex.contents = pCaulk->contents; // ditto
306  tex.SetName( pCaulk->GetName() );
307 
308  //Texture_SetTexture (&tex);
309 
310  for (int iListEntry = 0; iListEntry < FacesToCaulk.Num(); iListEntry++)
311  {
312  PairBrushFace_t &PairBrushFace = FacesToCaulk[iListEntry];
313  face_t *pFace = PairBrushFace.pFace;
314  brush_t*pBrush= PairBrushFace.pBrush;
315 
316  pFace->d_texture = pCaulk;
317  pFace->texdef = tex;
318 
319  Face_FitTexture(pFace, 1, 1); // this doesn't work here for some reason... duh.
320  Brush_Build(pBrush);
321 
322  iFacesCaulked++;
323  }
324  }
325  else
326  {
327  /*Sys_Printf*/common->Printf(" Unable to locate caulk texture at: \"%s\"!\n",psCaulkName);
328  }
329  }
330 
331  /*Sys_Printf*/common->Printf("( %d faces caulked )\n",iFacesCaulked);
332 
333  if (iSystemBrushesSkipped)
334  {
335  /*Sys_Printf*/common->Printf("( %d system-faced brushes skipped )\n",iSystemBrushesSkipped);
336  }
337 
338  Sys_UpdateWindows (W_ALL);
339 }
340 #endif
bool FilterBrush(brush_t *pb)
Definition: XYWnd.cpp:3167
void Face_FitTexture(face_t *face, float nHeight, float nWidth)
void WINAPI Sys_UpdateWindows(int nBits)
Definition: MainFrm.cpp:3974
void ClearBounds(idVec3 &mins, idVec3 &maxs)
Definition: autocaulk.cpp:54
brush_t selected_brushes
Definition: EditorMap.cpp:40
brush_t active_brushes
Definition: EditorMap.cpp:39
const GLdouble * v
Definition: glext.h:2936
const char * GetName(void) const
Definition: DeclManager.h:140
Definition: Vector.h:316
#define VectorAdd(a, b, c)
Definition: Vector.h:1996
int i
Definition: process.py:33
void Brush_Build(brush_t *b, bool bSnap, bool bMarkMap, bool bConvert, bool updateLights)
int GetNumPoints(void) const
Definition: Winding.h:238
const idMaterial * Texture_ForName(const char *name)
Definition: NewTexWnd.cpp:700
void Select_AutoCaulk()
Definition: autocaulk.cpp:96
idCommon * common
Definition: Common.cpp:206
brush_t * pBrush
Definition: autocaulk.cpp:93
virtual void Printf(const char *fmt,...) id_attribute((format(printf
face_t * pFace
Definition: autocaulk.cpp:92
#define strnicmp
Definition: autocaulk.cpp:47
GLfloat GLfloat GLfloat GLfloat v3
Definition: glext.h:3609
int Append(const type &obj)
Definition: List.h:646
tuple f
Definition: idal.py:89
int Num(void) const
Definition: List.h:265
#define DotProduct(a, b)
Definition: Vector.h:1994
char * va(const char *fmt,...)
Definition: Str.cpp:1568
Definition: List.h:84
void Zero(void)
Definition: Vector.h:415
void AddPointToBounds(const idVec3 &v, idVec3 &mins, idVec3 &maxs)
Definition: autocaulk.cpp:60
idList< PairBrushFace_t > FacesToCaulk
Definition: autocaulk.cpp:95
void Clear(void)
Definition: List.h:184