mirror of
https://github.com/id-Software/DOOM-3.git
synced 2026-03-20 08:59:56 +01:00
hello world
This commit is contained in:
340
neo/tools/radiant/autocaulk.cpp
Normal file
340
neo/tools/radiant/autocaulk.cpp
Normal file
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "../../idlib/precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "qe3.h"
|
||||
#include "Radiant.h"
|
||||
#include "autocaulk.h"
|
||||
|
||||
// Note: the code in here looks pretty goofy in places, and probably doesn't use the new Q4 class stuff fully,
|
||||
// but I just got it in and compiling from the JK2/SOF2 Radiants via some ugly code replaces, and it works, so there.
|
||||
// Also, a bunch of Radiant fields no longer exist in this codebase, likewise the whole point of passing in the bool
|
||||
// to this code, but I've just left it as-is. A designer tested it and pronounced it fine.
|
||||
|
||||
//#pragma warning( disable : 4786)
|
||||
//#include <list>
|
||||
//using namespace std;
|
||||
//#pragma warning( disable : 4786)
|
||||
|
||||
#undef strnicmp
|
||||
#define strnicmp idStr::Icmpn
|
||||
|
||||
#if 1
|
||||
|
||||
|
||||
//extern void ClearBounds (idVec3 mins, idVec3 maxs);
|
||||
//extern void AddPointToBounds (const idVec3 v, idVec3 mins, idVec3 maxs);
|
||||
void ClearBounds (idVec3 &mins, idVec3 &maxs)
|
||||
{
|
||||
mins[0] = mins[1] = mins[2] = 99999;
|
||||
maxs[0] = maxs[1] = maxs[2] = -99999;
|
||||
}
|
||||
|
||||
void AddPointToBounds( const idVec3 &v, idVec3 &mins, idVec3 &maxs )
|
||||
{
|
||||
int i;
|
||||
float val;
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
val = v[i];
|
||||
if (val < mins[i])
|
||||
mins[i] = val;
|
||||
if (val > maxs[i])
|
||||
maxs[i] = val;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void FloorBounds(idVec3 &mins, idVec3 &maxs)
|
||||
{
|
||||
for (int i=0 ; i<3 ; i++)
|
||||
{
|
||||
mins[i] = floor(mins[i] + 0.5);
|
||||
maxs[i] = floor(maxs[i] + 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static LPCSTR vtos(idVec3 &v3)
|
||||
{
|
||||
return va("%.3ff,%.3f,%.3f",v3[0],v3[1],v3[2]);
|
||||
}
|
||||
struct PairBrushFace_t
|
||||
{
|
||||
face_t* pFace;
|
||||
brush_t* pBrush;
|
||||
};
|
||||
idList < PairBrushFace_t > FacesToCaulk;
|
||||
void Select_AutoCaulk()
|
||||
{
|
||||
/*Sys_Printf*/common->Printf("Caulking...\n");
|
||||
|
||||
FacesToCaulk.Clear();
|
||||
|
||||
int iSystemBrushesSkipped = 0;
|
||||
face_t *pSelectedFace;
|
||||
|
||||
brush_t *next;
|
||||
for (brush_t *pSelectedBrush = selected_brushes.next ; pSelectedBrush != &selected_brushes ; pSelectedBrush = next)
|
||||
{
|
||||
next = pSelectedBrush->next;
|
||||
|
||||
if (pSelectedBrush->owner->eclass->fixedsize)
|
||||
continue; // apparently this means it's a model, so skip it...
|
||||
|
||||
// new check, we can't caulk a brush that has any "system/" faces...
|
||||
//
|
||||
bool bSystemFacePresent = false;
|
||||
for ( pSelectedFace = pSelectedBrush->brush_faces; pSelectedFace; pSelectedFace = pSelectedFace->next)
|
||||
{
|
||||
if (!strnicmp(pSelectedFace->d_texture->GetName(),"system/",7))
|
||||
{
|
||||
bSystemFacePresent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bSystemFacePresent)
|
||||
{
|
||||
iSystemBrushesSkipped++;
|
||||
continue; // verboten to caulk this.
|
||||
}
|
||||
|
||||
for (int iBrushListToScan = 0; iBrushListToScan<2; iBrushListToScan++)
|
||||
{
|
||||
brush_t *snext;
|
||||
for (brush_t *pScannedBrush = (iBrushListToScan?active_brushes.next:selected_brushes.next); pScannedBrush != (iBrushListToScan?&active_brushes:&selected_brushes) ; pScannedBrush = snext)
|
||||
{
|
||||
snext = pScannedBrush->next;
|
||||
|
||||
if ( pScannedBrush == pSelectedBrush)
|
||||
continue;
|
||||
|
||||
if (pScannedBrush->owner->eclass->fixedsize || pScannedBrush->pPatch || pScannedBrush->hiddenBrush)
|
||||
continue;
|
||||
|
||||
if (FilterBrush(pScannedBrush))
|
||||
continue;
|
||||
|
||||
// idMaterial stuff no longer support this, not sure what else to do.
|
||||
// Searching for other occurences of QER_NOCARVE just shows people REMing the code and ignoring ths issue...
|
||||
//
|
||||
// if (pScannedBrush->brush_faces->d_texture->bFromShader && (pScannedBrush->brush_faces->d_texture->TestMaterialFlag(QER_NOCARVE)))
|
||||
// continue;
|
||||
|
||||
// basic-reject first to see if brushes can even possibly touch (coplanar counts as touching)
|
||||
//
|
||||
int i;
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
if (pSelectedBrush->mins[i] > pScannedBrush->maxs[i] ||
|
||||
pSelectedBrush->maxs[i] < pScannedBrush->mins[i])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i != 3)
|
||||
continue; // can't be touching
|
||||
|
||||
// ok, now for the clever stuff, we need to detect only those faces that are both coplanar and smaller
|
||||
// or equal to the face they're coplanar with...
|
||||
//
|
||||
for (pSelectedFace = pSelectedBrush->brush_faces; pSelectedFace; pSelectedFace = pSelectedFace->next)
|
||||
{
|
||||
idWinding *pSelectedWinding = pSelectedFace->face_winding;
|
||||
|
||||
if (!pSelectedWinding)
|
||||
continue; // freed face, probably won't happen here, but who knows with this program?
|
||||
|
||||
// SquaredFace_t SelectedSquaredFace;
|
||||
// WindingToSquaredFace( &SelectedSquaredFace, pSelectedWinding);
|
||||
|
||||
for (face_t *pScannedFace = pScannedBrush->brush_faces; pScannedFace; pScannedFace = pScannedFace->next)
|
||||
{
|
||||
// don't even try caulking against a system face, because these are often transparent and will leave holes
|
||||
//
|
||||
if (!strnicmp(pScannedFace->d_texture->GetName(),"system/",7))
|
||||
continue;
|
||||
|
||||
// and don't try caulking against something inherently transparent...
|
||||
//
|
||||
if (pScannedFace->d_texture->TestMaterialFlag(QER_TRANS))
|
||||
continue;
|
||||
|
||||
idWinding *pScannedWinding = pScannedFace->face_winding;
|
||||
|
||||
if (!pScannedWinding)
|
||||
continue; // freed face, probably won't happen here, but who knows with this program?
|
||||
|
||||
// SquaredFace_t ScannedSquaredFace;
|
||||
// WindingToSquaredFace( &ScannedSquaredFace, pScannedWinding);
|
||||
|
||||
/* if (VectorCompare(ScannedSquaredFace.v3NormalisedRotationVector, SelectedSquaredFace.v3NormalisedRotationVector)
|
||||
&&
|
||||
VectorCompare(ScannedSquaredFace.v3NormalisedElevationVector, SelectedSquaredFace.v3NormalisedElevationVector)
|
||||
)
|
||||
*/
|
||||
{
|
||||
// brush faces are in parallel planes to each other, so check that their normals
|
||||
// are opposite, by adding them together and testing for zero...
|
||||
// (if normals are opposite, then faces can be against/touching each other?)
|
||||
//
|
||||
idVec3 v3ZeroTest;
|
||||
idVec3 v3Zero;v3Zero.Zero(); //static idVec3 v3Zero={0,0,0};
|
||||
|
||||
VectorAdd(pSelectedFace->plane.Normal(),pScannedFace->plane.Normal(),v3ZeroTest);
|
||||
if (v3ZeroTest == v3Zero)
|
||||
{
|
||||
// planes are facing each other...
|
||||
//
|
||||
// coplanar? (this is some maths of Gil's, which I don't even pretend to understand)
|
||||
//
|
||||
float fTotalDist = 0;
|
||||
for (int _i=0; _i<3; _i++)
|
||||
{
|
||||
fTotalDist += fabs( DotProduct(pSelectedFace->plane.Normal(),(*pSelectedWinding)[0])
|
||||
-
|
||||
DotProduct(pSelectedFace->plane.Normal(),(*pScannedWinding)[i])
|
||||
);
|
||||
}
|
||||
//OutputDebugString(va("Dist = %g\n",fTotalDist));
|
||||
|
||||
if (fTotalDist > 0.01)
|
||||
continue;
|
||||
|
||||
// every point in the selected face must be within (or equal to) the bounds of the
|
||||
// scanned face...
|
||||
//
|
||||
// work out the bounds first...
|
||||
//
|
||||
idVec3 v3ScannedBoundsMins, v3ScannedBoundsMaxs;
|
||||
ClearBounds (v3ScannedBoundsMins, v3ScannedBoundsMaxs);
|
||||
int iPoint;
|
||||
for (iPoint=0; iPoint<pScannedWinding->GetNumPoints(); iPoint++)
|
||||
{
|
||||
AddPointToBounds( (*pScannedWinding)[iPoint].ToVec3(), v3ScannedBoundsMins, v3ScannedBoundsMaxs);
|
||||
}
|
||||
// floor 'em... (or .001 differences mess things up...
|
||||
//
|
||||
FloorBounds(v3ScannedBoundsMins, v3ScannedBoundsMaxs);
|
||||
|
||||
|
||||
// now check points from selected face...
|
||||
//
|
||||
bool bWithin = true;
|
||||
for (iPoint=0; iPoint < pSelectedWinding->GetNumPoints(); iPoint++)
|
||||
{
|
||||
for (int iXYZ=0; iXYZ<3; iXYZ++)
|
||||
{
|
||||
float f = floor((*pSelectedWinding)[iPoint][iXYZ] + 0.5);
|
||||
if (!
|
||||
(
|
||||
f >= v3ScannedBoundsMins[iXYZ]
|
||||
&&
|
||||
f <= v3ScannedBoundsMaxs[iXYZ]
|
||||
)
|
||||
)
|
||||
{
|
||||
bWithin = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bWithin)
|
||||
{
|
||||
PairBrushFace_t PairBrushFace;
|
||||
PairBrushFace.pFace = pSelectedFace;
|
||||
PairBrushFace.pBrush= pSelectedBrush;
|
||||
FacesToCaulk.Append(PairBrushFace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// apply caulk...
|
||||
//
|
||||
int iFacesCaulked = 0;
|
||||
if (FacesToCaulk.Num())
|
||||
{
|
||||
LPCSTR psCaulkName = "textures/common/caulk";
|
||||
const idMaterial *pCaulk = Texture_ForName(psCaulkName);
|
||||
|
||||
if (pCaulk)
|
||||
{
|
||||
//
|
||||
// and call some other junk that Radiant wants so so we can use it later...
|
||||
//
|
||||
texdef_t tex;
|
||||
memset (&tex, 0, sizeof(tex));
|
||||
tex.scale[0] = 1;
|
||||
tex.scale[1] = 1;
|
||||
//tex.flags = pCaulk->flags; // field missing in Q4
|
||||
//tex.value = pCaulk->value; // ditto
|
||||
//tex.contents = pCaulk->contents; // ditto
|
||||
tex.SetName( pCaulk->GetName() );
|
||||
|
||||
//Texture_SetTexture (&tex);
|
||||
|
||||
for (int iListEntry = 0; iListEntry < FacesToCaulk.Num(); iListEntry++)
|
||||
{
|
||||
PairBrushFace_t &PairBrushFace = FacesToCaulk[iListEntry];
|
||||
face_t *pFace = PairBrushFace.pFace;
|
||||
brush_t*pBrush= PairBrushFace.pBrush;
|
||||
|
||||
pFace->d_texture = pCaulk;
|
||||
pFace->texdef = tex;
|
||||
|
||||
Face_FitTexture(pFace, 1, 1); // this doesn't work here for some reason... duh.
|
||||
Brush_Build(pBrush);
|
||||
|
||||
iFacesCaulked++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*Sys_Printf*/common->Printf(" Unable to locate caulk texture at: \"%s\"!\n",psCaulkName);
|
||||
}
|
||||
}
|
||||
|
||||
/*Sys_Printf*/common->Printf("( %d faces caulked )\n",iFacesCaulked);
|
||||
|
||||
if (iSystemBrushesSkipped)
|
||||
{
|
||||
/*Sys_Printf*/common->Printf("( %d system-faced brushes skipped )\n",iSystemBrushesSkipped);
|
||||
}
|
||||
|
||||
Sys_UpdateWindows (W_ALL);
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user