mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-15 07:00:58 +00:00
New Blender style mesh .map primitive type
This commit is contained in:
parent
a60f92b81b
commit
61f568550e
2 changed files with 700 additions and 2 deletions
|
@ -3,6 +3,7 @@
|
|||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2015 Robert Beckebans
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
|
@ -627,6 +628,9 @@ idMapEntity* idMapEntity::Parse( idLexer& src, bool worldSpawn, float version )
|
|||
idMapEntity* mapEnt;
|
||||
idMapPatch* mapPatch;
|
||||
idMapBrush* mapBrush;
|
||||
// RB begin
|
||||
MapPolygonMesh* mapMesh;
|
||||
// RB end
|
||||
bool worldent;
|
||||
idVec3 origin;
|
||||
double v1, v2, v3;
|
||||
|
@ -697,6 +701,17 @@ idMapEntity* idMapEntity::Parse( idLexer& src, bool worldSpawn, float version )
|
|||
}
|
||||
mapEnt->AddPrimitive( mapPatch );
|
||||
}
|
||||
// RB: new mesh primitive with ngons
|
||||
else if( token.Icmpn( "mesh", 4 ) == 0 )
|
||||
{
|
||||
mapMesh = MapPolygonMesh::Parse( src, origin, version );
|
||||
if( !mapMesh )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
mapEnt->AddPrimitive( mapMesh );
|
||||
}
|
||||
// RB end
|
||||
// assume it's a brush in Q3 or older style
|
||||
else
|
||||
{
|
||||
|
@ -779,6 +794,11 @@ bool idMapEntity::Write( idFile* fp, int entityNum ) const
|
|||
case idMapPrimitive::TYPE_PATCH:
|
||||
static_cast<idMapPatch*>( mapPrim )->Write( fp, i, origin );
|
||||
break;
|
||||
// RB begin
|
||||
case idMapPrimitive::TYPE_MESH:
|
||||
static_cast<MapPolygonMesh*>( mapPrim )->Write( fp, i, origin );
|
||||
break;
|
||||
// RB end
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -821,6 +841,12 @@ unsigned int idMapEntity::GetGeometryCRC() const
|
|||
case idMapPrimitive::TYPE_PATCH:
|
||||
crc ^= static_cast<idMapPatch*>( mapPrim )->GetGeometryCRC();
|
||||
break;
|
||||
|
||||
// RB begin
|
||||
case idMapPrimitive::TYPE_MESH:
|
||||
crc ^= static_cast<MapPolygonMesh*>( mapPrim )->GetGeometryCRC();
|
||||
break;
|
||||
// RB end
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1123,3 +1149,529 @@ bool idMapFile::NeedsReload()
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// RB begin
|
||||
MapPolygonMesh::MapPolygonMesh()
|
||||
{
|
||||
type = TYPE_MESH;
|
||||
polygons.Resize( 8, 4 );
|
||||
|
||||
contents = CONTENTS_SOLID;
|
||||
opaque = true;
|
||||
}
|
||||
|
||||
void MapPolygonMesh::ConvertFromBrush( const idMapBrush* mapBrush, int entityNum, int primitiveNum )
|
||||
{
|
||||
// fix degenerate planes
|
||||
idPlane* planes = ( idPlane* ) _alloca16( mapBrush->GetNumSides() * sizeof( planes[0] ) );
|
||||
for( int i = 0; i < mapBrush->GetNumSides(); i++ )
|
||||
{
|
||||
planes[i] = mapBrush->GetSide( i )->GetPlane();
|
||||
planes[i].FixDegeneracies( DEGENERATE_DIST_EPSILON );
|
||||
}
|
||||
|
||||
idList<idFixedWinding> planeWindings;
|
||||
idBounds bounds;
|
||||
bounds.Clear();
|
||||
|
||||
int numVerts = 0;
|
||||
int numIndexes = 0;
|
||||
|
||||
bool badBrush = false;
|
||||
|
||||
for( int i = 0; i < mapBrush->GetNumSides(); i++ )
|
||||
{
|
||||
idMapBrushSide* mapSide = mapBrush->GetSide( i );
|
||||
|
||||
const idMaterial* material = declManager->FindMaterial( mapSide->GetMaterial() );
|
||||
//contents |= ( material->GetContentFlags() & CONTENTS_REMOVE_UTIL );
|
||||
//materials.AddUnique( material );
|
||||
|
||||
// chop base plane by other brush sides
|
||||
idFixedWinding& w = planeWindings.Alloc();
|
||||
w.BaseForPlane( -planes[i] );
|
||||
|
||||
if( !w.GetNumPoints() )
|
||||
{
|
||||
common->Printf( "Entity %i, Brush %i: base winding has no points\n", entityNum, primitiveNum );
|
||||
badBrush = true;
|
||||
break;
|
||||
}
|
||||
|
||||
for( int j = 0; j < mapBrush->GetNumSides() && w.GetNumPoints(); j++ )
|
||||
{
|
||||
if( i == j )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !w.ClipInPlace( -planes[j], 0 ) )
|
||||
{
|
||||
// no intersection
|
||||
//badBrush = true;
|
||||
common->Printf( "Entity %i, Brush %i: no intersection with other brush plane\n", entityNum, primitiveNum );
|
||||
//break;
|
||||
}
|
||||
}
|
||||
|
||||
if( w.GetNumPoints() <= 2 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// only used for debugging
|
||||
for( int j = 0; j < w.GetNumPoints(); j++ )
|
||||
{
|
||||
const idVec3& v = w[j].ToVec3();
|
||||
bounds.AddPoint( v );
|
||||
}
|
||||
}
|
||||
|
||||
if( badBrush )
|
||||
{
|
||||
//common->Error( "" )
|
||||
return;
|
||||
}
|
||||
|
||||
// copy the data from the windings and build polygons
|
||||
for( int i = 0; i < mapBrush->GetNumSides(); i++ )
|
||||
{
|
||||
idMapBrushSide* mapSide = mapBrush->GetSide( i );
|
||||
|
||||
idFixedWinding& w = planeWindings[i];
|
||||
if( !w.GetNumPoints() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
MapPolygon* polygon = new MapPolygon();
|
||||
polygon->SetMaterial( mapSide->GetMaterial() );
|
||||
|
||||
|
||||
//for( int j = 0; j < w.GetNumPoints(); j++ )
|
||||
|
||||
// reverse order, so normal does not point inwards
|
||||
for( int j = w.GetNumPoints() - 1; j >= 0; j-- )
|
||||
{
|
||||
polygon->AddIndex( verts.Num() + j );
|
||||
}
|
||||
|
||||
polygons.Append( polygon );
|
||||
|
||||
for( int j = 0; j < w.GetNumPoints(); j++ )
|
||||
{
|
||||
idDrawVert& dv = verts.Alloc();
|
||||
|
||||
const idVec3& xyz = w[j].ToVec3();
|
||||
|
||||
dv.xyz = xyz;
|
||||
|
||||
// calculate texture s/t from brush primitive texture matrix
|
||||
idVec4 texVec[2];
|
||||
mapSide->GetTextureVectors( texVec );
|
||||
|
||||
idVec2 st;
|
||||
st.x = ( xyz * texVec[0].ToVec3() ) + texVec[0][3];
|
||||
st.y = ( xyz * texVec[1].ToVec3() ) + texVec[1][3];
|
||||
|
||||
// flip y
|
||||
//st.y = 1.0f - st.y;
|
||||
|
||||
dv.SetTexCoord( st );
|
||||
|
||||
// copy normal
|
||||
dv.SetNormal( mapSide->GetPlane().Normal() );
|
||||
|
||||
//if( dv->GetNormal().Length() < 0.9 || dv->GetNormal().Length() > 1.1 )
|
||||
//{
|
||||
// common->Error( "Bad normal in TriListForSide" );
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
SetContents();
|
||||
}
|
||||
|
||||
void MapPolygonMesh::ConvertFromPatch( const idMapPatch* patch, int entityNum, int primitiveNum )
|
||||
{
|
||||
idSurface_Patch* cp = new idSurface_Patch( *patch );
|
||||
|
||||
if( patch->GetExplicitlySubdivided() )
|
||||
{
|
||||
cp->SubdivideExplicit( patch->GetHorzSubdivisions(), patch->GetVertSubdivisions(), true );
|
||||
}
|
||||
else
|
||||
{
|
||||
cp->Subdivide( DEFAULT_CURVE_MAX_ERROR, DEFAULT_CURVE_MAX_ERROR, DEFAULT_CURVE_MAX_LENGTH, true );
|
||||
}
|
||||
|
||||
for( int i = 0; i < cp->GetNumIndexes(); i += 3 )
|
||||
{
|
||||
MapPolygon* polygon = new MapPolygon;
|
||||
polygon->SetMaterial( patch->GetMaterial() );
|
||||
|
||||
idDrawVert& dv0 = verts.Alloc();
|
||||
idDrawVert& dv1 = verts.Alloc();
|
||||
idDrawVert& dv2 = verts.Alloc();
|
||||
|
||||
dv0 = ( *cp )[cp->GetIndexes()[i + 1]];
|
||||
dv1 = ( *cp )[cp->GetIndexes()[i + 2]];
|
||||
dv2 = ( *cp )[cp->GetIndexes()[i + 0]];
|
||||
|
||||
polygon->AddIndex( i + 0 );
|
||||
polygon->AddIndex( i + 1 );
|
||||
polygon->AddIndex( i + 2 );
|
||||
|
||||
polygons.Append( polygon );
|
||||
}
|
||||
|
||||
delete cp;
|
||||
|
||||
SetContents();
|
||||
}
|
||||
|
||||
bool MapPolygonMesh::Write( idFile* fp, int primitiveNum, const idVec3& origin ) const
|
||||
{
|
||||
fp->WriteFloatString( "// primitive %d\n{\n meshDef\n {\n", primitiveNum );
|
||||
//fp->WriteFloatString( " \"%s\"\n ( %d %d 0 0 0 )\n", GetMaterial(), GetWidth(), GetHeight() );
|
||||
|
||||
fp->WriteFloatString( " ( %d %d 0 0 0 )\n", verts.Num(), polygons.Num() );
|
||||
|
||||
fp->WriteFloatString( " (\n" );
|
||||
idVec2 st;
|
||||
idVec3 n;
|
||||
for( int i = 0; i < verts.Num(); i++ )
|
||||
{
|
||||
const idDrawVert* v = &verts[ i ];
|
||||
st = v->GetTexCoord();
|
||||
n = v->GetNormalRaw();
|
||||
|
||||
//fp->WriteFloatString( " ( %f %f %f %f %f %f %f %f )\n", v->xyz[0] + origin[0], v->xyz[1] + origin[1], v->xyz[2] + origin[2], st[0], st[1], n[0], n[1], n[2] );
|
||||
fp->WriteFloatString( " ( %f %f %f %f %f %f %f %f )\n", v->xyz[0], v->xyz[1], v->xyz[2], st[0], st[1], n[0], n[1], n[2] );
|
||||
}
|
||||
fp->WriteFloatString( " )\n" );
|
||||
|
||||
fp->WriteFloatString( " (\n" );
|
||||
for( int i = 0; i < polygons.Num(); i++ )
|
||||
{
|
||||
MapPolygon* poly = polygons[ i ];
|
||||
|
||||
fp->WriteFloatString( " \"%s\" %d = ", poly->GetMaterial(), poly->indexes.Num() );
|
||||
|
||||
for( int j = 0; j < poly->indexes.Num(); j++ )
|
||||
{
|
||||
fp->WriteFloatString( "%d ", poly->indexes[j] );
|
||||
}
|
||||
fp->WriteFloatString( "\n" );
|
||||
}
|
||||
fp->WriteFloatString( " )\n" );
|
||||
|
||||
fp->WriteFloatString( " }\n}\n" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MapPolygonMesh* MapPolygonMesh::Parse( idLexer& src, const idVec3& origin, float version )
|
||||
{
|
||||
float info[7];
|
||||
idToken token;
|
||||
int i;
|
||||
|
||||
if( !src.ExpectTokenString( "{" ) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Parse it
|
||||
if( !src.Parse1DMatrix( 5, info ) )
|
||||
{
|
||||
src.Error( "MapPolygonMesh::Parse: unable to parse meshDef info" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const int numVertices = ( int ) info[0];
|
||||
const int numPolygons = ( int ) info[1];
|
||||
|
||||
MapPolygonMesh* mesh = new MapPolygonMesh();
|
||||
|
||||
// parse vertices
|
||||
if( !src.ExpectTokenString( "(" ) )
|
||||
{
|
||||
src.Error( "MapPolygonMesh::Parse: bad mesh vertex data" );
|
||||
delete mesh;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for( i = 0; i < numVertices; i++ )
|
||||
{
|
||||
float v[8];
|
||||
|
||||
if( !src.Parse1DMatrix( 8, v ) )
|
||||
{
|
||||
src.Error( "MapPolygonMesh::Parse: bad vertex column data" );
|
||||
delete mesh;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO optimize: preallocate vertices
|
||||
//vert = &( ( *patch )[i * patch->GetWidth() + j] );
|
||||
|
||||
idDrawVert vert;
|
||||
|
||||
vert.xyz[0] = v[0];// - origin[0];
|
||||
vert.xyz[1] = v[1];// - origin[1];
|
||||
vert.xyz[2] = v[2];// - origin[2];
|
||||
vert.SetTexCoord( v[3], v[4] );
|
||||
|
||||
idVec3 n( v[5], v[6], v[7] );
|
||||
vert.SetNormal( n );
|
||||
|
||||
mesh->AddVertex( vert );
|
||||
}
|
||||
|
||||
if( !src.ExpectTokenString( ")" ) )
|
||||
{
|
||||
delete mesh;
|
||||
src.Error( "MapPolygonMesh::Parse: unable to parse vertices" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// parse polygons
|
||||
if( !src.ExpectTokenString( "(" ) )
|
||||
{
|
||||
src.Error( "MapPolygonMesh::Parse: bad mesh polygon data" );
|
||||
delete mesh;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for( i = 0; i < numPolygons; i++ )
|
||||
{
|
||||
// get material name
|
||||
MapPolygon* polygon = new MapPolygon();
|
||||
mesh->AddPolygon( polygon );
|
||||
|
||||
src.ReadToken( &token );
|
||||
if( token.type == TT_STRING )
|
||||
{
|
||||
polygon->SetMaterial( token );;
|
||||
}
|
||||
else
|
||||
{
|
||||
src.Error( "MapPolygonMesh::Parse: bad mesh polygon data" );
|
||||
delete mesh;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int numIndexes = src.ParseInt();
|
||||
|
||||
if( !src.ExpectTokenString( "=" ) )
|
||||
{
|
||||
src.Error( "MapPolygonMesh::Parse: bad mesh polygon data" );
|
||||
delete mesh;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//idTempArray<int> indexes( numIndexes );
|
||||
for( int j = 0; j < numIndexes; j++ )
|
||||
{
|
||||
//indexes[j] = src.ParseInt();
|
||||
|
||||
int index = src.ParseInt();
|
||||
polygon->AddIndex( index );
|
||||
}
|
||||
|
||||
//polygon->SetIndexes( indexes );
|
||||
}
|
||||
|
||||
if( !src.ExpectTokenString( ")" ) )
|
||||
{
|
||||
delete mesh;
|
||||
src.Error( "MapPolygonMesh::Parse: unable to parse polygons" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !src.ExpectTokenString( "}" ) )
|
||||
{
|
||||
delete mesh;
|
||||
src.Error( "MapPolygonMesh::Parse: unable to parse mesh primitive end" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !src.ExpectTokenString( "}" ) )
|
||||
{
|
||||
delete mesh;
|
||||
src.Error( "MapPolygonMesh::Parse: unable to parse mesh primitive end" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mesh->SetContents();
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
void MapPolygonMesh::SetContents()
|
||||
{
|
||||
if( polygons.Num() < 1 )
|
||||
{
|
||||
contents = CONTENTS_SOLID;
|
||||
opaque = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int c2;
|
||||
|
||||
MapPolygon* poly = polygons[0];
|
||||
|
||||
const idMaterial* mat = declManager->FindMaterial( poly->GetMaterial() );
|
||||
contents = mat->GetContentFlags();
|
||||
|
||||
//b->contentShader = s->material;
|
||||
bool mixed = false;
|
||||
|
||||
// a brush is only opaque if all sides are opaque
|
||||
opaque = true;
|
||||
|
||||
for( int i = 1 ; i < polygons.Num() ; i++ )
|
||||
{
|
||||
poly = polygons[i];
|
||||
|
||||
const idMaterial* mat2 = declManager->FindMaterial( poly->GetMaterial() );
|
||||
|
||||
c2 = mat2->GetContentFlags();
|
||||
if( c2 != contents )
|
||||
{
|
||||
mixed = true;
|
||||
contents |= c2;
|
||||
}
|
||||
|
||||
if( mat2->Coverage() != MC_OPAQUE )
|
||||
{
|
||||
opaque = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int MapPolygonMesh::GetGeometryCRC() const
|
||||
{
|
||||
int i;
|
||||
MapPolygon* poly;
|
||||
unsigned int crc;
|
||||
|
||||
crc = 0;
|
||||
for( i = 0; i < verts.Num(); i++ )
|
||||
{
|
||||
crc ^= FloatCRC( verts[i].xyz.x );
|
||||
crc ^= FloatCRC( verts[i].xyz.y );
|
||||
crc ^= FloatCRC( verts[i].xyz.z );
|
||||
}
|
||||
|
||||
for( i = 0; i < polygons.Num(); i++ )
|
||||
{
|
||||
poly = polygons[i];
|
||||
|
||||
crc ^= StringCRC( poly->GetMaterial() );
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
bool MapPolygonMesh::IsAreaportal() const
|
||||
{
|
||||
return ( ( contents & CONTENTS_AREAPORTAL ) != 0 );
|
||||
}
|
||||
|
||||
void MapPolygonMesh::GetBounds( idBounds& bounds ) const
|
||||
{
|
||||
if( !verts.Num() )
|
||||
{
|
||||
bounds.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bounds[0] = bounds[1] = verts[0].xyz;
|
||||
for( int i = 1; i < verts.Num(); i++ )
|
||||
{
|
||||
const idVec3& p = verts[i].xyz;
|
||||
|
||||
if( p.x < bounds[0].x )
|
||||
{
|
||||
bounds[0].x = p.x;
|
||||
}
|
||||
else if( p.x > bounds[1].x )
|
||||
{
|
||||
bounds[1].x = p.x;
|
||||
}
|
||||
if( p.y < bounds[0].y )
|
||||
{
|
||||
bounds[0].y = p.y;
|
||||
}
|
||||
else if( p.y > bounds[1].y )
|
||||
{
|
||||
bounds[1].y = p.y;
|
||||
}
|
||||
if( p.z < bounds[0].z )
|
||||
{
|
||||
bounds[0].z = p.z;
|
||||
}
|
||||
else if( p.z > bounds[1].z )
|
||||
{
|
||||
bounds[1].z = p.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool idMapFile::ConvertToPolygonMeshFormat()
|
||||
{
|
||||
int count = GetNumEntities();
|
||||
for( int j = 0; j < count; j++ )
|
||||
{
|
||||
idMapEntity* ent = GetEntity( j );
|
||||
if( ent )
|
||||
{
|
||||
idStr classname = ent->epairs.GetString( "classname" );
|
||||
|
||||
//if( classname == "worldspawn" )
|
||||
{
|
||||
for( int i = 0; i < ent->GetNumPrimitives(); i++ )
|
||||
{
|
||||
idMapPrimitive* mapPrim;
|
||||
|
||||
mapPrim = ent->GetPrimitive( i );
|
||||
if( mapPrim->GetType() == idMapPrimitive::TYPE_BRUSH )
|
||||
{
|
||||
MapPolygonMesh* meshPrim = new MapPolygonMesh();
|
||||
meshPrim->epairs.Copy( mapPrim->epairs );
|
||||
|
||||
meshPrim->ConvertFromBrush( static_cast<idMapBrush*>( mapPrim ), j, i );
|
||||
ent->primitives[ i ] = meshPrim;
|
||||
|
||||
delete mapPrim;
|
||||
|
||||
continue;
|
||||
}
|
||||
#if 0
|
||||
else if( mapPrim->GetType() == idMapPrimitive::TYPE_PATCH )
|
||||
{
|
||||
MapPolygonMesh* meshPrim = new MapPolygonMesh();
|
||||
meshPrim->epairs.Copy( mapPrim->epairs );
|
||||
|
||||
meshPrim->ConvertFromPatch( static_cast<idMapPatch*>( mapPrim ), j, i );
|
||||
ent->primitives[ i ] = meshPrim;
|
||||
|
||||
delete mapPrim;
|
||||
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// RB end
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2015 Robert Beckebans
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
|
@ -44,7 +45,10 @@ If you have questions concerning this license or the applicable additional terms
|
|||
*/
|
||||
|
||||
const int OLD_MAP_VERSION = 1;
|
||||
const int CURRENT_MAP_VERSION = 2;
|
||||
// RB: added new map format
|
||||
const int DOOM3_MAP_VERSION = 2;
|
||||
const int CURRENT_MAP_VERSION = 3;
|
||||
// RB end
|
||||
const int DEFAULT_CURVE_SUBDIVISION = 4;
|
||||
const float DEFAULT_CURVE_MAX_ERROR = 4.0f;
|
||||
const float DEFAULT_CURVE_MAX_ERROR_CD = 24.0f;
|
||||
|
@ -55,7 +59,9 @@ const float DEFAULT_CURVE_MAX_LENGTH_CD = -1.0f;
|
|||
class idMapPrimitive
|
||||
{
|
||||
public:
|
||||
enum { TYPE_INVALID = -1, TYPE_BRUSH, TYPE_PATCH };
|
||||
// RB: new mesh primitive to work with Blender Ngons
|
||||
enum { TYPE_INVALID = -1, TYPE_BRUSH, TYPE_PATCH, TYPE_MESH };
|
||||
// RB end
|
||||
|
||||
idDict epairs;
|
||||
|
||||
|
@ -232,6 +238,141 @@ ID_INLINE idMapPatch::idMapPatch( int maxPatchWidth, int maxPatchHeight )
|
|||
}
|
||||
|
||||
|
||||
// RB begin
|
||||
class MapPolygon
|
||||
{
|
||||
friend class MapPolygonMesh;
|
||||
|
||||
public:
|
||||
MapPolygon();
|
||||
MapPolygon( int numIndexes );
|
||||
~MapPolygon() { }
|
||||
|
||||
const char* GetMaterial() const
|
||||
{
|
||||
return material;
|
||||
}
|
||||
|
||||
void SetMaterial( const char* p )
|
||||
{
|
||||
material = p;
|
||||
}
|
||||
|
||||
void AddIndex( int index )
|
||||
{
|
||||
indexes.Append( index );
|
||||
}
|
||||
|
||||
void SetIndexes( const idTempArray<int>& _indexes )
|
||||
{
|
||||
indexes.Resize( _indexes.Num() );
|
||||
|
||||
for( unsigned int i = 0; i < _indexes.Num(); i++ )
|
||||
{
|
||||
indexes[i] = _indexes[i];
|
||||
}
|
||||
}
|
||||
|
||||
const idList<int>& GetIndexes() const
|
||||
{
|
||||
return indexes;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
idStr material;
|
||||
idList<int> indexes; // [3..n] references to vertices for each face
|
||||
};
|
||||
|
||||
ID_INLINE MapPolygon::MapPolygon()
|
||||
{
|
||||
}
|
||||
|
||||
ID_INLINE MapPolygon::MapPolygon( int numIndexes )
|
||||
{
|
||||
indexes.AssureSize( 3 );
|
||||
}
|
||||
|
||||
|
||||
class MapPolygonMesh : public idMapPrimitive
|
||||
{
|
||||
public:
|
||||
MapPolygonMesh();
|
||||
~MapPolygonMesh()
|
||||
{
|
||||
//verts.DeleteContents();
|
||||
polygons.DeleteContents( true );
|
||||
}
|
||||
|
||||
void ConvertFromBrush( const idMapBrush* brush, int entityNum, int primitiveNum );
|
||||
void ConvertFromPatch( const idMapPatch* patch, int entityNum, int primitiveNum );
|
||||
|
||||
static MapPolygonMesh* Parse( idLexer& src, const idVec3& origin, float version = CURRENT_MAP_VERSION );
|
||||
bool Write( idFile* fp, int primitiveNum, const idVec3& origin ) const;
|
||||
|
||||
|
||||
|
||||
int GetNumVertices() const
|
||||
{
|
||||
return verts.Num();
|
||||
}
|
||||
|
||||
int AddVertex( const idDrawVert& v )
|
||||
{
|
||||
return verts.Append( v );
|
||||
}
|
||||
|
||||
|
||||
int GetNumPolygons() const
|
||||
{
|
||||
return polygons.Num();
|
||||
}
|
||||
|
||||
int AddPolygon( MapPolygon* face )
|
||||
{
|
||||
return polygons.Append( face );
|
||||
}
|
||||
|
||||
MapPolygon* GetFace( int i ) const
|
||||
{
|
||||
return polygons[i];
|
||||
}
|
||||
|
||||
unsigned int GetGeometryCRC() const;
|
||||
|
||||
const idList<idDrawVert>& GetDrawVerts() const
|
||||
{
|
||||
return verts;
|
||||
}
|
||||
|
||||
bool IsOpaque() const
|
||||
{
|
||||
return opaque;
|
||||
}
|
||||
|
||||
bool IsAreaportal() const;
|
||||
|
||||
void GetBounds( idBounds& bounds ) const;
|
||||
|
||||
private:
|
||||
void SetContents();
|
||||
|
||||
protected:
|
||||
|
||||
idList<idDrawVert> verts; // vertices can be shared between polygons
|
||||
idList<MapPolygon*> polygons;
|
||||
|
||||
// derived data after parsing
|
||||
|
||||
// material surface flags
|
||||
int contents;
|
||||
bool opaque;
|
||||
};
|
||||
// RB end
|
||||
|
||||
|
||||
|
||||
|
||||
class idMapEntity
|
||||
{
|
||||
friend class idMapFile;
|
||||
|
@ -285,6 +426,11 @@ public:
|
|||
// load a .map file
|
||||
bool Parse( const char* filename, bool ignoreRegion = false, bool osPath = false );
|
||||
bool Write( const char* fileName, const char* ext, bool fromBasePath = true );
|
||||
|
||||
// RB begin
|
||||
bool ConvertToPolygonMeshFormat();
|
||||
// RB end
|
||||
|
||||
// get the number of entities in the map
|
||||
int GetNumEntities() const
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue