mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-01 07:02:05 +00:00
429 lines
7.9 KiB
C++
429 lines
7.9 KiB
C++
|
/*
|
||
|
===========================================================================
|
||
|
|
||
|
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 "precompiled.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include "dmap.h"
|
||
|
|
||
|
/*
|
||
|
|
||
|
All triangle list functions should behave reasonably with NULL lists.
|
||
|
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
AllocTri
|
||
|
===============
|
||
|
*/
|
||
|
mapTri_t* AllocTri( void )
|
||
|
{
|
||
|
mapTri_t* tri;
|
||
|
|
||
|
tri = ( mapTri_t* )Mem_Alloc( sizeof( *tri ), TAG_TOOLS );
|
||
|
memset( tri, 0, sizeof( *tri ) );
|
||
|
return tri;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
FreeTri
|
||
|
===============
|
||
|
*/
|
||
|
void FreeTri( mapTri_t* tri )
|
||
|
{
|
||
|
Mem_Free( tri );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
MergeTriLists
|
||
|
|
||
|
This does not copy any tris, it just relinks them
|
||
|
===============
|
||
|
*/
|
||
|
mapTri_t* MergeTriLists( mapTri_t* a, mapTri_t* b )
|
||
|
{
|
||
|
mapTri_t** prev;
|
||
|
|
||
|
prev = &a;
|
||
|
while( *prev )
|
||
|
{
|
||
|
prev = &( *prev )->next;
|
||
|
}
|
||
|
|
||
|
*prev = b;
|
||
|
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
FreeTriList
|
||
|
===============
|
||
|
*/
|
||
|
void FreeTriList( mapTri_t* a )
|
||
|
{
|
||
|
mapTri_t* next;
|
||
|
|
||
|
for( ; a ; a = next )
|
||
|
{
|
||
|
next = a->next;
|
||
|
Mem_Free( a );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
CopyTriList
|
||
|
===============
|
||
|
*/
|
||
|
mapTri_t* CopyTriList( const mapTri_t* a )
|
||
|
{
|
||
|
mapTri_t* testList;
|
||
|
const mapTri_t* tri;
|
||
|
|
||
|
testList = NULL;
|
||
|
for( tri = a ; tri ; tri = tri->next )
|
||
|
{
|
||
|
mapTri_t* copy;
|
||
|
|
||
|
copy = CopyMapTri( tri );
|
||
|
copy ->next = testList;
|
||
|
testList = copy;
|
||
|
}
|
||
|
|
||
|
return testList;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
=============
|
||
|
CountTriList
|
||
|
=============
|
||
|
*/
|
||
|
int CountTriList( const mapTri_t* tri )
|
||
|
{
|
||
|
int c;
|
||
|
|
||
|
c = 0;
|
||
|
while( tri )
|
||
|
{
|
||
|
c++;
|
||
|
tri = tri->next;
|
||
|
}
|
||
|
|
||
|
return c;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
CopyMapTri
|
||
|
===============
|
||
|
*/
|
||
|
mapTri_t* CopyMapTri( const mapTri_t* tri )
|
||
|
{
|
||
|
mapTri_t* t;
|
||
|
|
||
|
t = ( mapTri_t* )Mem_Alloc( sizeof( *t ), TAG_TOOLS );
|
||
|
*t = *tri;
|
||
|
|
||
|
return t;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
MapTriArea
|
||
|
===============
|
||
|
*/
|
||
|
float MapTriArea( const mapTri_t* tri )
|
||
|
{
|
||
|
return idWinding::TriangleArea( tri->v[0].xyz, tri->v[1].xyz, tri->v[2].xyz );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
RemoveBadTris
|
||
|
|
||
|
Return a new list with any zero or negative area triangles removed
|
||
|
===============
|
||
|
*/
|
||
|
mapTri_t* RemoveBadTris( const mapTri_t* list )
|
||
|
{
|
||
|
mapTri_t* newList;
|
||
|
mapTri_t* copy;
|
||
|
const mapTri_t* tri;
|
||
|
|
||
|
newList = NULL;
|
||
|
|
||
|
for( tri = list ; tri ; tri = tri->next )
|
||
|
{
|
||
|
if( MapTriArea( tri ) > 0 )
|
||
|
{
|
||
|
copy = CopyMapTri( tri );
|
||
|
copy->next = newList;
|
||
|
newList = copy;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return newList;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
BoundTriList
|
||
|
================
|
||
|
*/
|
||
|
void BoundTriList( const mapTri_t* list, idBounds& b )
|
||
|
{
|
||
|
b.Clear();
|
||
|
for( ; list ; list = list->next )
|
||
|
{
|
||
|
b.AddPoint( list->v[0].xyz );
|
||
|
b.AddPoint( list->v[1].xyz );
|
||
|
b.AddPoint( list->v[2].xyz );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
DrawTri
|
||
|
================
|
||
|
*/
|
||
|
void DrawTri( const mapTri_t* tri )
|
||
|
{
|
||
|
idWinding w;
|
||
|
|
||
|
w.SetNumPoints( 3 );
|
||
|
w[0] = tri->v[0].xyz;
|
||
|
w[1] = tri->v[1].xyz;
|
||
|
w[2] = tri->v[2].xyz;
|
||
|
DrawWinding( &w );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
FlipTriList
|
||
|
|
||
|
Swaps the vertex order
|
||
|
================
|
||
|
*/
|
||
|
void FlipTriList( mapTri_t* tris )
|
||
|
{
|
||
|
mapTri_t* tri;
|
||
|
|
||
|
for( tri = tris ; tri ; tri = tri->next )
|
||
|
{
|
||
|
idDrawVert v;
|
||
|
const struct hashVert_s* hv;
|
||
|
struct optVertex_s* ov;
|
||
|
|
||
|
v = tri->v[0];
|
||
|
tri->v[0] = tri->v[2];
|
||
|
tri->v[2] = v;
|
||
|
|
||
|
hv = tri->hashVert[0];
|
||
|
tri->hashVert[0] = tri->hashVert[2];
|
||
|
tri->hashVert[2] = hv;
|
||
|
|
||
|
ov = tri->optVert[0];
|
||
|
tri->optVert[0] = tri->optVert[2];
|
||
|
tri->optVert[2] = ov;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
WindingForTri
|
||
|
================
|
||
|
*/
|
||
|
idWinding* WindingForTri( const mapTri_t* tri )
|
||
|
{
|
||
|
idWinding* w;
|
||
|
|
||
|
w = new idWinding( 3 );
|
||
|
w->SetNumPoints( 3 );
|
||
|
( *w )[0] = tri->v[0].xyz;
|
||
|
( *w )[1] = tri->v[1].xyz;
|
||
|
( *w )[2] = tri->v[2].xyz;
|
||
|
return w;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
TriVertsFromOriginal
|
||
|
|
||
|
Regenerate the texcoords and colors on a fragmented tri from the plane equations
|
||
|
================
|
||
|
*/
|
||
|
void TriVertsFromOriginal( mapTri_t* tri, const mapTri_t* original )
|
||
|
{
|
||
|
int i, j;
|
||
|
float denom;
|
||
|
|
||
|
denom = idWinding::TriangleArea( original->v[0].xyz, original->v[1].xyz, original->v[2].xyz );
|
||
|
if( denom == 0 )
|
||
|
{
|
||
|
return; // original was degenerate, so it doesn't matter
|
||
|
}
|
||
|
|
||
|
for( i = 0 ; i < 3 ; i++ )
|
||
|
{
|
||
|
float a, b, c;
|
||
|
|
||
|
// find the barycentric coordinates
|
||
|
a = idWinding::TriangleArea( tri->v[i].xyz, original->v[1].xyz, original->v[2].xyz ) / denom;
|
||
|
b = idWinding::TriangleArea( tri->v[i].xyz, original->v[2].xyz, original->v[0].xyz ) / denom;
|
||
|
c = idWinding::TriangleArea( tri->v[i].xyz, original->v[0].xyz, original->v[1].xyz ) / denom;
|
||
|
|
||
|
// regenerate the interpolated values
|
||
|
tri->v[i].SetTexCoordS( a * original->v[0].GetTexCoordS()
|
||
|
+ b * original->v[1].GetTexCoordS() + c * original->v[2].GetTexCoordS() );
|
||
|
tri->v[i].SetTexCoordT( a * original->v[0].GetTexCoordT()
|
||
|
+ b * original->v[1].GetTexCoordT() + c * original->v[2].GetTexCoordT() );
|
||
|
|
||
|
idVec3 normal = tri->v[i].GetNormal();
|
||
|
for( j = 0 ; j < 3 ; j++ )
|
||
|
{
|
||
|
normal[j] = a * original->v[0].GetNormal()[j]
|
||
|
+ b * original->v[1].GetNormal()[j] + c * original->v[2].GetNormal()[j];
|
||
|
}
|
||
|
normal.Normalize();
|
||
|
tri->v[i].SetNormal( normal );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
WindingToTriList
|
||
|
|
||
|
Generates a new list of triangles with proper texcoords from a winding
|
||
|
created by clipping the originalTri
|
||
|
|
||
|
OriginalTri can be NULL if you don't care about texCoords
|
||
|
================
|
||
|
*/
|
||
|
mapTri_t* WindingToTriList( const idWinding* w, const mapTri_t* originalTri )
|
||
|
{
|
||
|
mapTri_t* tri;
|
||
|
mapTri_t* triList;
|
||
|
int i, j;
|
||
|
const idVec3* vec;
|
||
|
|
||
|
if( !w )
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
triList = NULL;
|
||
|
for( i = 2 ; i < w->GetNumPoints() ; i++ )
|
||
|
{
|
||
|
tri = AllocTri();
|
||
|
if( !originalTri )
|
||
|
{
|
||
|
memset( tri, 0, sizeof( *tri ) );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*tri = *originalTri;
|
||
|
}
|
||
|
tri->next = triList;
|
||
|
triList = tri;
|
||
|
|
||
|
for( j = 0 ; j < 3 ; j++ )
|
||
|
{
|
||
|
if( j == 0 )
|
||
|
{
|
||
|
vec = &( ( *w )[0] ).ToVec3();
|
||
|
}
|
||
|
else if( j == 1 )
|
||
|
{
|
||
|
vec = &( ( *w )[i - 1] ).ToVec3();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
vec = &( ( *w )[i] ).ToVec3();
|
||
|
}
|
||
|
tri->v[j].xyz = *vec;
|
||
|
}
|
||
|
if( originalTri )
|
||
|
{
|
||
|
TriVertsFromOriginal( tri, originalTri );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return triList;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
==================
|
||
|
ClipTriList
|
||
|
==================
|
||
|
*/
|
||
|
void ClipTriList( const mapTri_t* list, const idPlane& plane, float epsilon,
|
||
|
mapTri_t** front, mapTri_t** back )
|
||
|
{
|
||
|
const mapTri_t* tri;
|
||
|
mapTri_t* newList;
|
||
|
idWinding* w, *frontW, *backW;
|
||
|
|
||
|
*front = NULL;
|
||
|
*back = NULL;
|
||
|
|
||
|
for( tri = list ; tri ; tri = tri->next )
|
||
|
{
|
||
|
w = WindingForTri( tri );
|
||
|
w->Split( plane, epsilon, &frontW, &backW );
|
||
|
|
||
|
newList = WindingToTriList( frontW, tri );
|
||
|
*front = MergeTriLists( *front, newList );
|
||
|
|
||
|
newList = WindingToTriList( backW, tri );
|
||
|
*back = MergeTriLists( *back, newList );
|
||
|
|
||
|
delete w;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
==================
|
||
|
PlaneForTri
|
||
|
==================
|
||
|
*/
|
||
|
void PlaneForTri( const mapTri_t* tri, idPlane& plane )
|
||
|
{
|
||
|
plane.FromPoints( tri->v[0].xyz, tri->v[1].xyz, tri->v[2].xyz );
|
||
|
}
|