mirror of
https://github.com/dhewm/dhewm3.git
synced 2024-11-27 22:52:44 +00:00
79ad905e05
Excluding 3rd party files.
387 lines
7.8 KiB
C++
387 lines
7.8 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 "../../../idlib/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 ) );
|
|
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 ) );
|
|
*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 );
|
|
VectorCopy( tri->v[0].xyz, w[0] );
|
|
VectorCopy( tri->v[1].xyz, w[1] );
|
|
VectorCopy( tri->v[2].xyz, w[2] );
|
|
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 );
|
|
VectorCopy( tri->v[0].xyz, (*w)[0] );
|
|
VectorCopy( tri->v[1].xyz, (*w)[1] );
|
|
VectorCopy( tri->v[2].xyz, (*w)[2] );
|
|
|
|
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].st[0] = a * original->v[0].st[0]
|
|
+ b * original->v[1].st[0] + c * original->v[2].st[0];
|
|
tri->v[i].st[1] = a * original->v[0].st[1]
|
|
+ b * original->v[1].st[1] + c * original->v[2].st[1];
|
|
|
|
for ( j = 0 ; j < 3 ; j++ ) {
|
|
tri->v[i].normal[j] = a * original->v[0].normal[j]
|
|
+ b * original->v[1].normal[j] + c * original->v[2].normal[j];
|
|
}
|
|
tri->v[i].normal.Normalize();
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
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();
|
|
}
|
|
|
|
VectorCopy( *vec, tri->v[j].xyz );
|
|
}
|
|
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 );
|
|
}
|