doom3-bfg/neo/tools/compilers/dmap/tritools.cpp
2014-08-02 15:09:25 +02:00

432 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()
{
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
// RB begin
const idVec2 aST = original->v[0].GetTexCoord();
const idVec2 bST = original->v[1].GetTexCoord();
const idVec2 cST = original->v[2].GetTexCoord();
tri->v[i].SetTexCoord( a * aST.x + b * bST.x + c * cST.x,
a * aST.y + b * bST.y + c * cST.y );
idVec3 tempNormal;
for( j = 0 ; j < 3 ; j++ )
{
tempNormal[j] = a * original->v[0].GetNormal()[j] + b * original->v[1].GetNormal()[j] + c * original->v[2].GetNormal()[j];
}
tempNormal.Normalize();
tri->v[i].SetNormal( tempNormal );
// RB end
}
}
/*
================
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 );
}