//
//////////////////////////////////////////////////////////////////////
-#include "StdAfx.h"
+#include "DBrush.h"
-#ifdef _WIN32
+#ifdef WIN32
#pragma warning(disable : 4786)
#endif
-#include "DBrush.h"
+#include <list>
+#include "str.h"
+
+#include "DPoint.h"
+#include "DPlane.h"
+#include "DEPair.h"
+#include "DPatch.h"
+#include "DEntity.h"
#include "DWinding.h"
+
#include "dialogs/dialogs-gtk.h"
#include "misc.h"
+#include "iundo.h"
+
+#include "generic/referencecounted.h"
+
+#include "scenelib.h"
+
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
DBrush::DBrush( int ID ){
m_nBrushID = ID;
- bBoundsBuilt = FALSE;
+ bBoundsBuilt = false;
+ QER_entity = NULL;
QER_brush = NULL;
}
// Implementation
//////////////////////////////////////////////////////////////////////
-DPlane* DBrush::AddFace( vec3_t va, vec3_t vb, vec3_t vc, _QERFaceData* texData ){
+DPlane* DBrush::AddFace( const vec3_t va, const vec3_t vb, const vec3_t vc, const _QERFaceData* texData ){
#ifdef _DEBUG
// Sys_Printf("(%f %f %f) (%f %f %f) (%f %f %f)\n", va[0], va[1], va[2], vb[0], vb[1], vb[2], vc[0], vc[1], vc[2]);
#endif
- bBoundsBuilt = FALSE;
+ bBoundsBuilt = false;
DPlane* newFace = new DPlane( va, vb, vc, texData );
faceList.push_back( newFace );
return 0; // with only 3 faces u can't have a bounded soild
}
- for ( list<DPlane *>::const_iterator p1 = faceList.begin(); p1 != faceList.end(); p1++ )
+ for ( std::list<DPlane *>::const_iterator p1 = faceList.begin(); p1 != faceList.end(); p1++ )
{
- list<DPlane *>::const_iterator p2 = p1;
+ std::list<DPlane *>::const_iterator p2 = p1;
for ( p2++; p2 != faceList.end(); p2++ )
{
- list<DPlane *>::const_iterator p3 = p2;
+ std::list<DPlane *>::const_iterator p3 = p2;
for ( p3++; p3 != faceList.end(); p3++ )
{
vec3_t pnt;
int pos = PointPosition( pnt );
if ( pos == POINT_IN_BRUSH ) { // ???? shouldn't happen here
- Sys_Printf( "ERROR:: Build Brush Points: Point IN brush!!!\n" );
+ globalErrorStream() << "ERROR:: Build Brush Points: Point IN brush!!!\n";
}
else if ( pos == POINT_ON_BRUSH ) { // normal point
if ( !HasPoint( pnt ) ) {
// Sys_Printf("%i points on brush\n", pointList.size());
#endif
- return pointList.size();
+ return static_cast<int>( pointList.size() );
}
-void DBrush::LoadFromBrush_t( brush_t* brush, bool textured ){
- ClearFaces();
- ClearPoints();
+void DBrush_addFace( DBrush& brush, const _QERFaceData& faceData ){
+ brush.AddFace( vector3_to_array( faceData.m_p0 ), vector3_to_array( faceData.m_p1 ), vector3_to_array( faceData.m_p2 ), 0 );
+}
+typedef ReferenceCaller1<DBrush, const _QERFaceData&, DBrush_addFace> DBrushAddFaceCaller;
- for ( int i = g_FuncTable.m_pfnGetFaceCount( brush ) - 1; i >= 0 ; i-- )
- { // running backwards so i dont have to use the count function each time (OPT)
- _QERFaceData* faceData = g_FuncTable.m_pfnGetFaceData( brush, i );
+void DBrush_addFaceTextured( DBrush& brush, const _QERFaceData& faceData ){
+ brush.AddFace( vector3_to_array( faceData.m_p0 ), vector3_to_array( faceData.m_p1 ), vector3_to_array( faceData.m_p2 ), &faceData );
+}
+typedef ReferenceCaller1<DBrush, const _QERFaceData&, DBrush_addFaceTextured> DBrushAddFaceTexturedCaller;
- if ( faceData == NULL ) {
- DoMessageBox( "Null pointer returned", "WARNING!", MB_OK );
- }
+void DBrush::LoadFromBrush( scene::Instance& brush, bool textured ){
+ ClearFaces();
+ ClearPoints();
- if ( textured ) {
- AddFace( faceData->m_v1, faceData->m_v2, faceData->m_v3, faceData );
- }
- else{
- AddFace( faceData->m_v1, faceData->m_v2, faceData->m_v3, NULL );
- }
- }
+ GlobalBrushCreator().Brush_forEachFace( brush.path().top(), textured ? BrushFaceDataCallback( DBrushAddFaceTexturedCaller( *this ) ) : BrushFaceDataCallback( DBrushAddFaceCaller( *this ) ) );
- QER_brush = brush;
+ QER_entity = brush.path().parent().get_pointer();
+ QER_brush = brush.path().top().get_pointer();
}
int DBrush::PointPosition( vec3_t pnt ){
int state = POINT_IN_BRUSH; // if nothing happens point is inside brush
- for ( list<DPlane *>::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
+ for ( std::list<DPlane *>::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
{
float dist = ( *chkPlane )->DistanceToPoint( pnt );
}
void DBrush::ClearPoints(){
- for ( list<DPoint *>::const_iterator deadPoint = pointList.begin(); deadPoint != pointList.end(); deadPoint++ ) {
+ for ( std::list<DPoint *>::const_iterator deadPoint = pointList.begin(); deadPoint != pointList.end(); deadPoint++ ) {
delete *deadPoint;
}
pointList.clear();
}
void DBrush::ClearFaces(){
- bBoundsBuilt = FALSE;
- for ( list<DPlane *>::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++ )
+ bBoundsBuilt = false;
+ for ( std::list<DPlane *>::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++ )
{
delete *deadPlane;
}
}
bool DBrush::HasPoint( vec3_t pnt ){
- for ( list<DPoint *>::const_iterator chkPoint = pointList.begin(); chkPoint != pointList.end(); chkPoint++ )
+ for ( std::list<DPoint *>::const_iterator chkPoint = pointList.begin(); chkPoint != pointList.end(); chkPoint++ )
{
if ( **chkPoint == pnt ) {
- return TRUE;
+ return true;
}
}
- return FALSE;
+ return false;
}
int DBrush::RemoveRedundantPlanes(){
int cnt = 0;
- list<DPlane *>::iterator chkPlane;
+ std::list<DPlane *>::iterator chkPlane;
// find duplicate planes
- list<DPlane *>::iterator p1 = faceList.begin();
+ std::list<DPlane *>::iterator p1 = faceList.begin();
while ( p1 != faceList.end() )
{
- list<DPlane *>::iterator p2 = p1;
+ std::list<DPlane *>::iterator p2 = p1;
for ( p2++; p2 != faceList.end(); p2++ )
{
if ( **p1 == **p2 ) {
- if ( !strcmp( ( *p1 )->texInfo.m_TextureName, "textures/common/caulk" ) ) {
+ if ( !strcmp( ( *p1 )->m_shader.c_str(), "textures/common/caulk" ) ) {
delete *p1;
p1 = faceList.erase( p1 ); // duplicate plane
}
BuildBounds();
if ( !bBoundsBuilt ) {
- return FALSE;
+ return false;
}
VectorCopy( bbox_min, min );
VectorCopy( bbox_max, max );
- return TRUE;
+ return true;
}
bool DBrush::BBoxCollision( DBrush* chkBrush ){
chkBrush->GetBounds( min2, max2 );
if ( min1[0] >= max2[0] ) {
- return FALSE;
+ return false;
}
if ( min1[1] >= max2[1] ) {
- return FALSE;
+ return false;
}
if ( min1[2] >= max2[2] ) {
- return FALSE;
+ return false;
}
if ( max1[0] <= min2[0] ) {
- return FALSE;
+ return false;
}
if ( max1[1] <= min2[1] ) {
- return FALSE;
+ return false;
}
if ( max1[2] <= min2[2] ) {
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
DPlane* DBrush::HasPlane( DPlane* chkPlane ){
- for ( list<DPlane *>::const_iterator brushPlane = faceList.begin(); brushPlane != faceList.end(); brushPlane++ )
+ for ( std::list<DPlane *>::const_iterator brushPlane = faceList.begin(); brushPlane != faceList.end(); brushPlane++ )
{
if ( **brushPlane == *chkPlane ) {
return *brushPlane;
if ( pointList.size() == 0 ) {
if ( BuildPoints() == 0 ) {
- return FALSE;
+ return false;
}
}
- list<DPoint *>::const_iterator chkPnt = pointList.begin();
+ std::list<DPoint *>::const_iterator chkPnt = pointList.begin();
if ( chkPnt == pointList.end() ) {
- return FALSE;
+ return false;
}
float dist = cuttingPlane->DistanceToPoint( ( *chkPnt )->_pnt );
if ( dist > MAX_ROUND_ERROR ) {
- isInFront = FALSE;
+ isInFront = false;
}
else if ( dist < MAX_ROUND_ERROR ) {
- isInFront = TRUE;
+ isInFront = true;
}
else{
- return TRUE;
+ return true;
}
for ( chkPnt++ = pointList.begin(); chkPnt != pointList.end(); chkPnt++ )
if ( dist > MAX_ROUND_ERROR ) {
if ( isInFront ) {
- return TRUE;
+ return true;
}
}
else if ( dist < MAX_ROUND_ERROR ) {
if ( !isInFront ) {
- return TRUE;
+ return true;
}
}
else{
- return TRUE;
+ return true;
}
}
- return FALSE;
+ return false;
}
-brush_t* DBrush::BuildInRadiant( bool allowDestruction, int* changeCnt, entity_t* entity ){
+
+scene::Node* DBrush::BuildInRadiant( bool allowDestruction, int* changeCnt, scene::Node* entity ){
if ( allowDestruction ) {
- bool kill = TRUE;
+ bool kill = true;
- for ( list<DPlane *>::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
+ for ( std::list<DPlane *>::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
{
if ( ( *chkPlane )->m_bChkOk ) {
- kill = FALSE;
+ kill = false;
break;
}
}
//+djbob: fixed bug when brush had no faces "phantom brush" in radiant.
if ( faceList.size() < 4 ) {
- Sys_Printf( "Possible Phantom Brush Found, will not rebuild\n" );
+ globalErrorStream() << "Possible Phantom Brush Found, will not rebuild\n";
return NULL;
}
//-djbob
- QER_brush = (brush_t*)g_FuncTable.m_pfnCreateBrushHandle();
+ NodeSmartReference node( GlobalBrushCreator().createBrush() );
- for ( list<DPlane *>::const_iterator buildPlane = faceList.begin(); buildPlane != faceList.end(); buildPlane++ ) {
- if ( ( *buildPlane )->AddToBrush_t( QER_brush ) && changeCnt ) {
+ for ( std::list<DPlane *>::const_iterator buildPlane = faceList.begin(); buildPlane != faceList.end(); buildPlane++ ) {
+ if ( ( *buildPlane )->AddToBrush( node ) && changeCnt ) {
( *changeCnt )++;
}
}
if ( entity ) {
- g_FuncTable.m_pfnCommitBrushHandleToEntity( QER_brush, entity );
- g_BrushTable.m_pfnBrush_Build( QER_brush, false, false, false, false );
- g_BrushTable.m_pfnBrush_AddToList( QER_brush, g_AppDataTable.m_pfnSelectedBrushes() );
+ Node_getTraversable( *entity )->insert( node );
}
else {
- g_FuncTable.m_pfnCommitBrushHandle( QER_brush );
+ Node_getTraversable( GlobalRadiant().getMapWorldEntity() )->insert( node );
}
- return QER_brush;
+ QER_entity = entity;
+ QER_brush = node.get_pointer();
+
+ return node.get_pointer();
}
void DBrush::CutByPlane( DPlane *cutPlane, DBrush **newBrush1, DBrush **newBrush2 ){
DBrush* b1 = new DBrush;
DBrush* b2 = new DBrush;
- for ( list<DPlane *>::const_iterator parsePlane = faceList.begin(); parsePlane != faceList.end(); parsePlane++ )
+ for ( std::list<DPlane *>::const_iterator parsePlane = faceList.begin(); parsePlane != faceList.end(); parsePlane++ )
{
b1->AddFace( ( *parsePlane )->points[0], ( *parsePlane )->points[1], ( *parsePlane )->points[2], NULL );
b2->AddFace( ( *parsePlane )->points[0], ( *parsePlane )->points[1], ( *parsePlane )->points[2], NULL );
bool DBrush::IntersectsWith( DBrush *chkBrush ){
if ( pointList.size() == 0 ) {
if ( BuildPoints() == 0 ) {
- return FALSE; // invalid brush!!!!
+ return false; // invalid brush!!!!
}
}
if ( chkBrush->pointList.size() == 0 ) {
if ( chkBrush->BuildPoints() == 0 ) {
- return FALSE; // invalid brush!!!!
+ return false; // invalid brush!!!!
}
}
if ( !BBoxCollision( chkBrush ) ) {
- return FALSE;
+ return false;
}
- list<DPlane *>::const_iterator iplPlane;
+ std::list<DPlane *>::const_iterator iplPlane;
for ( iplPlane = faceList.begin(); iplPlane != faceList.end(); iplPlane++ )
{
- bool allInFront = TRUE;
- for ( list<DPoint *>::const_iterator iPoint = chkBrush->pointList.begin(); iPoint != chkBrush->pointList.end(); iPoint++ )
+ bool allInFront = true;
+ for ( std::list<DPoint *>::const_iterator iPoint = chkBrush->pointList.begin(); iPoint != chkBrush->pointList.end(); iPoint++ )
{
if ( ( *iplPlane )->DistanceToPoint( ( *iPoint )->_pnt ) < -MAX_ROUND_ERROR ) {
- allInFront = FALSE;
+ allInFront = false;
break;
}
}
if ( allInFront ) {
- return FALSE;
+ return false;
}
}
for ( iplPlane = chkBrush->faceList.begin(); iplPlane != chkBrush->faceList.end(); iplPlane++ )
{
- bool allInFront = TRUE;
- for ( list<DPoint *>::const_iterator iPoint = pointList.begin(); iPoint != pointList.end(); iPoint++ )
+ bool allInFront = true;
+ for ( std::list<DPoint *>::const_iterator iPoint = pointList.begin(); iPoint != pointList.end(); iPoint++ )
{
if ( ( *iplPlane )->DistanceToPoint( ( *iPoint )->_pnt ) < -MAX_ROUND_ERROR ) {
- allInFront = FALSE;
+ allInFront = false;
break;
}
}
if ( allInFront ) {
- return FALSE;
+ return false;
}
}
- return TRUE;
+ return true;
}
bool DBrush::IntersectsWith( DPlane* p1, DPlane* p2, vec3_t v ) {
vec3_t vDown = { 0, 0, -1 };
- list<DPlane *>::const_iterator iplPlane;
+ std::list<DPlane *>::const_iterator iplPlane;
for ( iplPlane = faceList.begin(); iplPlane != faceList.end(); iplPlane++ ) {
DPlane* p = ( *iplPlane );
}
if ( p->PlaneIntersection( p1, p2, v ) ) {
if ( PointPosition( v ) != POINT_OUT_BRUSH ) {
- return TRUE;
+ return true;
}
}
}
- return FALSE;
+ return false;
}
void DBrush::BuildBounds(){
}
}
- list<DPoint *>::const_iterator first = pointList.begin();
+ std::list<DPoint *>::const_iterator first = pointList.begin();
VectorCopy( ( *first )->_pnt, bbox_min );
VectorCopy( ( *first )->_pnt, bbox_max );
- list<DPoint *>::const_iterator point = pointList.begin();
+ std::list<DPoint *>::const_iterator point = pointList.begin();
for ( point++; point != pointList.end(); point++ )
{
if ( ( *point )->_pnt[0] > bbox_max[0] ) {
}
}
- bBoundsBuilt = TRUE;
+ bBoundsBuilt = true;
}
}
chkBrush->GetBounds( min2, max2 );
if ( ( min1[0] - max2[0] ) > MAX_ROUND_ERROR ) {
- return FALSE;
+ return false;
}
if ( ( min1[1] - max2[1] ) > MAX_ROUND_ERROR ) {
- return FALSE;
+ return false;
}
if ( ( min1[2] - max2[2] ) > MAX_ROUND_ERROR ) {
- return FALSE;
+ return false;
}
if ( ( min2[0] - max1[0] ) > MAX_ROUND_ERROR ) {
- return FALSE;
+ return false;
}
if ( ( min2[1] - max1[1] ) > MAX_ROUND_ERROR ) {
- return FALSE;
+ return false;
}
if ( ( min2[2] - max1[2] ) > MAX_ROUND_ERROR ) {
- return FALSE;
+ return false;
}
int cnt = 0;
}
if ( cnt > 1 ) {
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
-void DBrush::ResetChecks( list<Str>* exclusionList ){
- for ( list<DPlane *>::const_iterator resetPlane = faceList.begin(); resetPlane != faceList.end(); resetPlane++ )
+void DBrush::ResetChecks( std::list<Str>* exclusionList ){
+ for ( std::list<DPlane *>::const_iterator resetPlane = faceList.begin(); resetPlane != faceList.end(); resetPlane++ )
{
- bool set = FALSE;
+ bool set = false;
if ( exclusionList ) {
- for ( list<Str>::iterator eTexture = exclusionList->begin(); eTexture != exclusionList->end(); eTexture++ )
+ for ( std::list<Str>::iterator eTexture = exclusionList->begin(); eTexture != exclusionList->end(); eTexture++ )
{
- if ( strstr( ( *resetPlane )->texInfo.m_TextureName, eTexture->GetBuffer() ) ) {
- set = TRUE;
+ if ( strstr( ( *resetPlane )->m_shader.c_str(), eTexture->GetBuffer() ) ) {
+ set = true;
break;
}
}
}
DPlane* DBrush::HasPlaneInverted( DPlane *chkPlane ){
- for ( list<DPlane *>::const_iterator brushPlane = faceList.begin(); brushPlane != faceList.end(); brushPlane++ )
+ for ( std::list<DPlane *>::const_iterator brushPlane = faceList.begin(); brushPlane != faceList.end(); brushPlane++ )
{
if ( **brushPlane != *chkPlane ) {
if ( fabs( ( *brushPlane )->_d + chkPlane->_d ) < 0.1 ) {
}
bool DBrush::HasTexture( const char *textureName ){
- for ( list<DPlane *>::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
+ for ( std::list<DPlane *>::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
{
- if ( strstr( ( *chkPlane )->texInfo.m_TextureName, textureName ) ) {
- return TRUE;
+ if ( strstr( ( *chkPlane )->m_shader.c_str(), textureName ) ) {
+ return true;
}
}
- return FALSE;
+ return false;
}
bool DBrush::IsDetail(){
- for ( list<DPlane *>::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
+ for ( std::list<DPlane *>::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
{
- if ( ( *chkPlane )->texInfo.m_nContents & FACE_DETAIL ) {
- return TRUE;
+ if ( ( *chkPlane )->texInfo.contents & FACE_DETAIL ) {
+ return true;
}
}
- return FALSE;
+ return false;
}
void DBrush::BuildFromWinding( DWinding *w ){
if ( w->numpoints < 3 ) {
- Sys_ERROR( "Winding has invalid number of points" );
+ globalErrorStream() << "Winding has invalid number of points";
return;
}
void DBrush::SaveToFile( FILE *pFile ){
fprintf( pFile, "{\n" );
- for ( list<DPlane *>::const_iterator pp = faceList.begin(); pp != faceList.end(); pp++ )
+ for ( std::list<DPlane *>::const_iterator pp = faceList.begin(); pp != faceList.end(); pp++ )
{
char buffer[512];
( *pp )->points[0][0], ( *pp )->points[0][1], ( *pp )->points[0][2],
( *pp )->points[1][0], ( *pp )->points[1][1], ( *pp )->points[1][2],
( *pp )->points[2][0], ( *pp )->points[2][1], ( *pp )->points[2][2],
- ( *pp )->texInfo.m_TextureName,
- ( *pp )->texInfo.m_fShift[0], ( *pp )->texInfo.m_fShift[1],
- ( *pp )->texInfo.m_fScale[0], ( *pp )->texInfo.m_fScale[0],
- ( *pp )->texInfo.m_fRotate );
+ ( *pp )->m_shader.c_str(),
+ ( *pp )->texInfo.m_texdef.shift[0], ( *pp )->texInfo.m_texdef.shift[1],
+ ( *pp )->texInfo.m_texdef.scale[0], ( *pp )->texInfo.m_texdef.scale[0],
+ ( *pp )->texInfo.m_texdef.rotate );
- fprintf( pFile, buffer );
+ fprintf( pFile, "%s", buffer );
}
fprintf( pFile, "}\n" );
}
void DBrush::Rotate( vec3_t vOrigin, vec3_t vRotation ){
- for ( list<DPlane *>::const_iterator rotPlane = faceList.begin(); rotPlane != faceList.end(); rotPlane++ )
+ for ( std::list<DPlane *>::const_iterator rotPlane = faceList.begin(); rotPlane != faceList.end(); rotPlane++ )
{
for ( int i = 0; i < 3; i++ )
VectorRotate( ( *rotPlane )->points[i], vRotation, vOrigin );
bool DBrush::ResetTextures( const char* textureName, float fScale[2], float fShift[2], int rotation, const char* newTextureName,
int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation ){
if ( textureName ) {
- bool changed = FALSE;
- for ( list<DPlane *>::const_iterator resetPlane = faceList.begin(); resetPlane != faceList.end(); resetPlane++ )
+ bool changed = false;
+ for ( std::list<DPlane *>::const_iterator resetPlane = faceList.begin(); resetPlane != faceList.end(); resetPlane++ )
{
- if ( !strcmp( ( *resetPlane )->texInfo.m_TextureName, textureName ) ) {
+ if ( !strcmp( ( *resetPlane )->m_shader.c_str(), textureName ) ) {
if ( bResetTextureName ) {
- strcpy( ( *resetPlane )->texInfo.m_TextureName, newTextureName );
+ ( *resetPlane )->m_shader = newTextureName;
}
if ( bResetScale[0] ) {
- ( *resetPlane )->texInfo.m_fScale[0] = fScale[0];
+ ( *resetPlane )->texInfo.m_texdef.scale[0] = fScale[0];
}
if ( bResetScale[1] ) {
- ( *resetPlane )->texInfo.m_fScale[1] = fScale[1];
+ ( *resetPlane )->texInfo.m_texdef.scale[1] = fScale[1];
}
if ( bResetShift[0] ) {
- ( *resetPlane )->texInfo.m_fShift[0] = fShift[0];
+ ( *resetPlane )->texInfo.m_texdef.shift[0] = fShift[0];
}
if ( bResetShift[1] ) {
- ( *resetPlane )->texInfo.m_fShift[1] = fShift[1];
+ ( *resetPlane )->texInfo.m_texdef.shift[1] = fShift[1];
}
if ( bResetRotation ) {
- ( *resetPlane )->texInfo.m_fRotate = (float)rotation;
+ ( *resetPlane )->texInfo.m_texdef.rotate = (float)rotation;
}
- changed = TRUE;
+ changed = true;
}
}
return changed; // no point rebuilding unless we need to, only slows things down
}
else
{
- for ( list<DPlane *>::const_iterator resetPlane = faceList.begin(); resetPlane != faceList.end(); resetPlane++ )
+ for ( std::list<DPlane *>::const_iterator resetPlane = faceList.begin(); resetPlane != faceList.end(); resetPlane++ )
{
if ( bResetTextureName ) {
- strcpy( ( *resetPlane )->texInfo.m_TextureName, newTextureName );
+ ( *resetPlane )->m_shader = newTextureName;
}
if ( bResetScale[0] ) {
- ( *resetPlane )->texInfo.m_fScale[0] = fScale[0];
+ ( *resetPlane )->texInfo.m_texdef.scale[0] = fScale[0];
}
if ( bResetScale[1] ) {
- ( *resetPlane )->texInfo.m_fScale[1] = fScale[1];
+ ( *resetPlane )->texInfo.m_texdef.scale[1] = fScale[1];
}
if ( bResetShift[0] ) {
- ( *resetPlane )->texInfo.m_fShift[0] = fShift[0];
+ ( *resetPlane )->texInfo.m_texdef.shift[0] = fShift[0];
}
if ( bResetShift[1] ) {
- ( *resetPlane )->texInfo.m_fShift[1] = fShift[1];
+ ( *resetPlane )->texInfo.m_texdef.shift[1] = fShift[1];
}
if ( bResetRotation ) {
- ( *resetPlane )->texInfo.m_fRotate = (float)rotation;
+ ( *resetPlane )->texInfo.m_texdef.rotate = (float)rotation;
}
}
- return TRUE;
+ return true;
}
}
bool DBrush::operator ==( DBrush* other ){
- list<DPlane *>::const_iterator chkPlane;
+ std::list<DPlane *>::const_iterator chkPlane;
for ( chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
{
if ( !other->HasPlane( ( *chkPlane ) ) ) {
- return FALSE;
+ return false;
}
}
for ( chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
{
if ( !HasPlane( ( *chkPlane ) ) ) {
- return FALSE;
+ return false;
}
}
- return TRUE;
+ return true;
}
-DPlane* DBrush::AddFace( vec3_t va, vec3_t vb, vec3_t vc, const char *textureName, bool bDetail ){
- bBoundsBuilt = FALSE;
+DPlane* DBrush::AddFace( const vec3_t va, const vec3_t vb, const vec3_t vc, const char *textureName, bool bDetail ){
+ bBoundsBuilt = false;
DPlane* newFace = new DPlane( va, vb, vc, textureName, bDetail );
faceList.push_back( newFace );
DPlane* DBrush::FindPlaneWithClosestNormal( vec_t* normal ) {
vec_t bestDot = -2;
DPlane* bestDotPlane = NULL;
- list<DPlane *>::const_iterator chkPlane;
+ std::list<DPlane *>::const_iterator chkPlane;
for ( chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ ) {
DPlane* pPlane = ( *chkPlane );
BuildPoints();
- for ( list<DPoint *>::const_iterator points = pointList.begin(); points != pointList.end(); points++ ) {
+ for ( std::list<DPoint *>::const_iterator points = pointList.begin(); points != pointList.end(); points++ ) {
DPoint* point = ( *points );
if ( fabs( plane->DistanceToPoint( point->_pnt ) ) < MAX_ROUND_ERROR ) {
}
void DBrush::RemovePlane( DPlane* plane ) {
- bBoundsBuilt = FALSE;
- for ( list<DPlane *>::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++ ) {
+ bBoundsBuilt = false;
+ for ( std::list<DPlane *>::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++ ) {
if ( *deadPlane == plane ) {
delete *deadPlane;
faceList.remove( plane );
}
}
}
-
-void DBrush::RemoveFromRadiant( void ) {
- if ( QER_brush ) {
- g_FuncTable.m_pfnDeleteBrushHandle( QER_brush );
- }
-}
/*
- Copyright (C) 1999-2007 id Software, Inc. and contributors.
+ Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
idVec3 idSplineList::zero( 0,0,0 );
void glLabeledPoint( idVec3 &color, idVec3 &point, float size, const char *label ) {
- qglColor3fv( color );
- qglPointSize( size );
- qglBegin( GL_POINTS );
- qglVertex3fv( point );
- qglEnd();
+ glColor3fv( color );
+ glPointSize( size );
+ glBegin( GL_POINTS );
+ glVertex3fv( point );
+ glEnd();
idVec3 v = point;
v.x += 1;
v.y += 1;
v.z += 1;
- qglRasterPos3fv( v );
- qglCallLists( strlen( label ), GL_UNSIGNED_BYTE, label );
+ glRasterPos3fv( v );
+ glCallLists( strlen( label ), GL_UNSIGNED_BYTE, label );
}
maxs[0] += size;
maxs[1] -= size;
maxs[2] += size;
- qglColor3fv( color );
- qglBegin( GL_LINE_LOOP );
- qglVertex3f( mins[0],mins[1],mins[2] );
- qglVertex3f( maxs[0],mins[1],mins[2] );
- qglVertex3f( maxs[0],maxs[1],mins[2] );
- qglVertex3f( mins[0],maxs[1],mins[2] );
- qglEnd();
- qglBegin( GL_LINE_LOOP );
- qglVertex3f( mins[0],mins[1],maxs[2] );
- qglVertex3f( maxs[0],mins[1],maxs[2] );
- qglVertex3f( maxs[0],maxs[1],maxs[2] );
- qglVertex3f( mins[0],maxs[1],maxs[2] );
- qglEnd();
-
- qglBegin( GL_LINES );
- qglVertex3f( mins[0],mins[1],mins[2] );
- qglVertex3f( mins[0],mins[1],maxs[2] );
- qglVertex3f( mins[0],maxs[1],maxs[2] );
- qglVertex3f( mins[0],maxs[1],mins[2] );
- qglVertex3f( maxs[0],mins[1],mins[2] );
- qglVertex3f( maxs[0],mins[1],maxs[2] );
- qglVertex3f( maxs[0],maxs[1],maxs[2] );
- qglVertex3f( maxs[0],maxs[1],mins[2] );
- qglEnd();
+ glColor3fv( color );
+ glBegin( GL_LINE_LOOP );
+ glVertex3f( mins[0],mins[1],mins[2] );
+ glVertex3f( maxs[0],mins[1],mins[2] );
+ glVertex3f( maxs[0],maxs[1],mins[2] );
+ glVertex3f( mins[0],maxs[1],mins[2] );
+ glEnd();
+ glBegin( GL_LINE_LOOP );
+ glVertex3f( mins[0],mins[1],maxs[2] );
+ glVertex3f( maxs[0],mins[1],maxs[2] );
+ glVertex3f( maxs[0],maxs[1],maxs[2] );
+ glVertex3f( mins[0],maxs[1],maxs[2] );
+ glEnd();
+
+ glBegin( GL_LINES );
+ glVertex3f( mins[0],mins[1],mins[2] );
+ glVertex3f( mins[0],mins[1],maxs[2] );
+ glVertex3f( mins[0],maxs[1],maxs[2] );
+ glVertex3f( mins[0],maxs[1],mins[2] );
+ glVertex3f( maxs[0],mins[1],mins[2] );
+ glVertex3f( maxs[0],mins[1],maxs[2] );
+ glVertex3f( maxs[0],maxs[1],maxs[2] );
+ glVertex3f( maxs[0],maxs[1],mins[2] );
+ glEnd();
}
}
- qglColor3fv( controlColor );
- qglPointSize( 5 );
+ glColor3fv( controlColor );
+ glPointSize( 5 );
- qglBegin( GL_POINTS );
+ glBegin( GL_POINTS );
for ( i = 0; i < controlPoints.Num(); i++ ) {
- qglVertex3fv( *controlPoints[i] );
+ glVertex3fv( *controlPoints[i] );
}
- qglEnd();
+ glEnd();
if ( editMode ) {
for ( i = 0; i < controlPoints.Num(); i++ ) {
}
//Draw the curve
- qglColor3fv( pathColor );
- qglBegin( GL_LINE_STRIP );
+ glColor3fv( pathColor );
+ glBegin( GL_LINE_STRIP );
int count = splinePoints.Num();
for ( i = 0; i < count; i++ ) {
- qglVertex3fv( *splinePoints[i] );
+ glVertex3fv( *splinePoints[i] );
}
- qglEnd();
+ glEnd();
if ( editMode ) {
- qglColor3fv( segmentColor );
- qglPointSize( 3 );
- qglBegin( GL_POINTS );
+ glColor3fv( segmentColor );
+ glPointSize( 3 );
+ glBegin( GL_POINTS );
for ( i = 0; i < count; i++ ) {
- qglVertex3fv( *splinePoints[i] );
+ glVertex3fv( *splinePoints[i] );
}
- qglEnd();
+ glEnd();
}
if ( count > 0 ) {
//assert(activeSegment >=0 && activeSegment < count);
const idVec3 *idSplineList::getPosition( long t ) {
static idVec3 interpolatedPos;
- static long lastTime = -1;
int count = splineTime.Num();
if ( count == 0 ) {
void idCameraDef::buildCamera() {
int i;
- int lastSwitch = 0;
idList<float> waits;
idList<int> targets;
// we have a base time layout for the path and the target path
// now we need to layer on any wait or speed changes
for ( i = 0; i < events.Num(); i++ ) {
- idCameraEvent *ev = events[i];
events[i]->setTriggered( false );
switch ( events[i]->getType() ) {
case idCameraEvent::EVENT_TARGET: {
bool idCameraDef::load( const char *filename ) {
char *buf;
const char *buf_p;
- int length = FS_ReadFile( filename, (void **)&buf );
+
+ FS_ReadFile( filename, (void **)&buf );
if ( !buf ) {
return false;
}
}
void idCameraDef::addTarget( const char *name, idCameraPosition::positionType type ) {
- const char *text = ( name == NULL ) ? va( "target0%d", numTargets() + 1 ) : name;
idCameraPosition *pos = newFromType( type );
if ( pos ) {
pos->setName( name );
/*
- Copyright (C) 1999-2007 id Software, Inc. and contributors.
+ Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
i = a.length(); // i == 0
i = c.length(); // i == 4
- const char *s1 = a.c_str(); // s1 == "\0"
- const char *s2 = c.c_str(); // s2 == "test\0"
-
t = new idStr(); // t->len == 0, t->data == "\0"
delete t; // t == ?
/*
- Copyright (C) 1999-2007 id Software, Inc. and contributors.
+ Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
#include <sys/types.h>
#include <sys/stat.h>
-#ifdef _WIN32
+#ifdef WIN32
#include <direct.h>
#include <windows.h>
#endif
}
strncpy( qdir, path, c + len + count - path );
Sys_Printf( "qdir: %s\n", qdir );
- for ( i = 0; i < strlen( qdir ); i++ )
+ for ( i = 0; i < (int) strlen( qdir ); i++ )
{
if ( qdir[i] == '\\' ) {
qdir[i] = '/';
if ( *c == '/' || *c == '\\' ) {
strncpy( gamedir, path, c + 1 - path );
- for ( i = 0; i < strlen( gamedir ); i++ )
+ for ( i = 0; i < (int) strlen( gamedir ); i++ )
{
if ( gamedir[i] == '\\' ) {
gamedir[i] = '/';
char *ExpandPath( const char *path ){
static char full[1024];
- if ( !*qdir || path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
- if ( !qdir[0] ) {
++ if ( !qdir ) {
+ Error( "ExpandPath called without qdir set" );
+ }
+ if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
strcpy( full, path );
return full;
}
char *ExpandGamePath( const char *path ){
static char full[1024];
- if ( !*gamedir ) {
- if ( !qdir[0] ) {
- Error( "ExpandGamePath called without qdir set" );
++ if ( !gamedir[0] ) {
+ Error( "ExpandGamePath called without gamedir set" );
}
if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
strcpy( full, path );
strcat( out, "\\" );
#else
// Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
- getcwd( out, 256 );
+ if ( !getcwd( out, 256 ) ) {
+ *out = 0;
+ }
strcat( out, "/" );
#endif
while ( out[i] != 0 )
void Q_mkdir( const char *path ){
+ char parentbuf[256];
+ const char *p = NULL;
+ int retry = 2;
+ while ( retry-- )
+ {
#ifdef WIN32
- if ( _mkdir( path ) != -1 ) {
- return;
- }
+ const char *q = NULL;
+ if ( _mkdir( path ) != -1 ) {
+ return;
+ }
+ if ( errno == ENOENT ) {
+ p = strrchr( path, '/' );
+ q = strrchr( path, '\\' );
+ if ( q && ( !p || q < p ) ) {
+ p = q;
+ }
+ }
#else
- if ( mkdir( path, 0777 ) != -1 ) {
- return;
- }
+ if ( mkdir( path, 0777 ) != -1 ) {
+ return;
+ }
+ if ( errno == ENOENT ) {
+ p = strrchr( path, '/' );
+ }
#endif
+ if ( p ) {
+ strncpy( parentbuf, path, sizeof( parentbuf ) );
+ if ( (int) ( p - path ) < (int) sizeof( parentbuf ) ) {
+ parentbuf[p - path] = 0;
+ Sys_Printf( "mkdir: %s: creating parent %s first\n", path, parentbuf );
+ Q_mkdir( parentbuf );
+ continue;
+ }
+ }
+ break;
+ }
if ( errno != EEXIST ) {
Error( "mkdir %s: %s",path, strerror( errno ) );
}
/*
- Copyright (C) 1999-2007 id Software, Inc. and contributors.
+ Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
#endif
- #define MAX_OS_PATH 1024
+#ifdef PATH_MAX
+#define MAX_OS_PATH PATH_MAX
+#else
+ #define MAX_OS_PATH 4096
+#endif
#define MEM_BLOCKSIZE 4096
// the dec offsetof macro doesnt work very well...
double I_FloatTime( void );
-void Error( const char *error, ... );
+void Error( const char *error, ... )
+#ifdef __GNUC__
+__attribute__( ( noreturn ) )
+#endif
+;
int CheckParm( const char *check );
FILE *SafeOpenWrite( const char *filename );
/*
- Copyright (C) 1999-2007 id Software, Inc. and contributors.
+ Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
#include "libxml/tree.h"
// utf8 conversion
+ #include <glib.h>
#include <glib/gconvert.h>
#include <glib/gmem.h>
char buf[1024];
sprintf( buf, "%f %f %f", v[0], v[1], v[2] );
- ret = xmlNewNode( NULL, "point" );
- xmlNodeSetContent( ret, buf );
+ ret = xmlNewNode( NULL, (xmlChar*)"point" );
+ xmlNodeSetContent( ret, (xmlChar*)buf );
return ret;
}
// l_net library defines an upper limit of MAX_NETMESSAGE
// there are some size check errors, so we use MAX_NETMESSAGE-10 to be safe
// if the size of the buffer exceeds MAX_NETMESSAGE-10 we'll send in several network messages
- while ( pos < xml_buf->use )
+ while ( pos < (int)xml_buf->use )
{
// what size are we gonna send now?
( xml_buf->use - pos < MAX_NETMESSAGE - 10 ) ? ( size = xml_buf->use - pos ) : ( size = MAX_NETMESSAGE - 10 );
// now build a proper "select" XML node
sprintf( buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg );
- node = xmlNewNode( NULL, "select" );
- xmlNodeSetContent( node, buf );
+ node = xmlNewNode( NULL, (xmlChar*)"select" );
+ xmlNodeSetContent( node, (xmlChar*)buf );
level[0] = (int)'0' + ( bError ? SYS_ERR : SYS_WRN ) ;
level[1] = 0;
- xmlSetProp( node, "level", (char *)&level );
+ xmlSetProp( node, (xmlChar*)"level", (xmlChar *)&level );
// a 'select' information
sprintf( buf, "%i %i", entitynum, brushnum );
- select = xmlNewNode( NULL, "brush" );
- xmlNodeSetContent( select, buf );
+ select = xmlNewNode( NULL, (xmlChar*)"brush" );
+ xmlNodeSetContent( select, (xmlChar*)buf );
xmlAddChild( node, select );
xml_SendNode( node );
char buf[1024];
char level[2];
- node = xmlNewNode( NULL, "pointmsg" );
- xmlNodeSetContent( node, msg );
+ node = xmlNewNode( NULL, (xmlChar*)"pointmsg" );
+ xmlNodeSetContent( node, (xmlChar*)msg );
level[0] = (int)'0' + SYS_ERR;
level[1] = 0;
- xmlSetProp( node, "level", (char *)&level );
+ xmlSetProp( node, (xmlChar*)"level", (xmlChar *)&level );
// a 'point' node
sprintf( buf, "%g %g %g", pt[0], pt[1], pt[2] );
- point = xmlNewNode( NULL, "point" );
- xmlNodeSetContent( point, buf );
+ point = xmlNewNode( NULL, (xmlChar*)"point" );
+ xmlNodeSetContent( point, (xmlChar*)buf );
xmlAddChild( node, point );
xml_SendNode( node );
char level[2];
int i;
- node = xmlNewNode( NULL, "windingmsg" );
- xmlNodeSetContent( node, msg );
+ node = xmlNewNode( NULL, (xmlChar*)"windingmsg" );
+ xmlNodeSetContent( node, (xmlChar*)msg );
level[0] = (int)'0' + SYS_ERR;
level[1] = 0;
- xmlSetProp( node, "level", (char *)&level );
+ xmlSetProp( node, (xmlChar*)"level", (xmlChar *)&level );
// a 'winding' node
sprintf( buf, "%i ", numpoints );
for ( i = 0; i < numpoints; i++ )
strcat( buf, smlbuf );
}
- winding = xmlNewNode( NULL, "winding" );
- xmlNodeSetContent( winding, buf );
+ winding = xmlNewNode( NULL, (xmlChar*)"winding" );
+ xmlNodeSetContent( winding, (xmlChar*)buf );
xmlAddChild( node, winding );
xml_SendNode( node );
char sMsg[1024];
Net_Setup();
- Net_StringToAddress( (char *)dest, &address );
+ Net_StringToAddress( dest, &address );
brdcst_socket = Net_Connect( &address, 0 );
if ( brdcst_socket ) {
// send in a header
*/
if ( !bGotXML ) {
// initialize
- doc = xmlNewDoc( "1.0" );
- doc->children = xmlNewDocRawNode( doc, NULL, "q3map_feedback", NULL );
+ doc = xmlNewDoc( (xmlChar*)"1.0" );
+ doc->children = xmlNewDocRawNode( doc, NULL, (xmlChar*)"q3map_feedback", NULL );
bGotXML = qtrue;
}
- node = xmlNewNode( NULL, "message" );
+ node = xmlNewNode( NULL, (xmlChar*)"message" );
{
gchar* utf8 = g_locale_to_utf8( buf, -1, NULL, NULL, NULL );
- xmlNodeSetContent( node, utf8 );
+ xmlNodeSetContent( node, (xmlChar*)utf8 );
g_free( utf8 );
}
level[0] = (int)'0' + flag;
level[1] = 0;
- xmlSetProp( node, "level", (char *)&level );
+ xmlSetProp( node, (xmlChar*)"level", (xmlChar *)&level );
xml_SendNode( node );
}
-/* -------------------------------------------------------------------------------
+/* -------------------------------------------------------------------------------;
Copyright (C) 1999-2007 id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
/* dependencies */
#include "q3map2.h"
+
+
/*
Random()
returns a pseudorandom number between 0 and 1
}
+ char *Q_strncpyz( char *dst, const char *src, size_t len ) {
+ if ( len == 0 ) {
+ abort();
+ }
+
+ strncpy( dst, src, len );
+ dst[ len - 1 ] = '\0';
+ return dst;
+ }
+
+
+ char *Q_strcat( char *dst, size_t dlen, const char *src ) {
+ size_t n = strlen( dst );
+
+ if ( n > dlen ) {
+ abort(); /* buffer overflow */
+ }
+
+ return Q_strncpyz( dst + n, src, dlen - n );
+ }
+
+
+ char *Q_strncat( char *dst, size_t dlen, const char *src, size_t slen ) {
+ size_t n = strlen( dst );
+
+ if ( n > dlen ) {
+ abort(); /* buffer overflow */
+ }
+
+ return Q_strncpyz( dst + n, src, MIN( slen, dlen - n ) );
+ }
+
/*
ExitQ3Map()
}
}
-static int MD4BlockChecksum( void * buffer, int length ) {
- unsigned char digest[16];
- int checksum;
- md4_get_digest( buffer, length, digest );
- /* I suppose it has to be done that way for legacy reasons? */
- checksum = digest[0] & ( digest[1] << 8 ) & ( digest[2] << 16 ) & ( digest[3] << 24 );
- checksum ^= digest[4] & ( digest[5] << 8 ) & ( digest[6] << 16 ) & ( digest[7] << 24 );
- checksum ^= digest[8] & ( digest[9] << 8 ) & ( digest[10] << 16 ) & ( digest[11] << 24 );
- checksum ^= digest[12] & ( digest[13] << 8 ) & ( digest[14] << 16 ) & ( digest[15] << 24 );
- return checksum;
+
+/* minimap stuff */
+
+typedef struct minimap_s
+{
+ bspModel_t *model;
+ int width;
+ int height;
+ int samples;
+ float *sample_offsets;
+ float sharpen_boxmult;
+ float sharpen_centermult;
+ float boost, brightness, contrast;
+ float *data1f;
+ float *sharpendata1f;
+ vec3_t mins, size;
+}
+minimap_t;
+static minimap_t minimap;
+
+qboolean BrushIntersectionWithLine( bspBrush_t *brush, vec3_t start, vec3_t dir, float *t_in, float *t_out ){
+ int i;
+ qboolean in = qfalse, out = qfalse;
+ bspBrushSide_t *sides = &bspBrushSides[brush->firstSide];
+
+ for ( i = 0; i < brush->numSides; ++i )
+ {
+ bspPlane_t *p = &bspPlanes[sides[i].planeNum];
+ float sn = DotProduct( start, p->normal );
+ float dn = DotProduct( dir, p->normal );
+ if ( dn == 0 ) {
+ if ( sn > p->dist ) {
+ return qfalse; // outside!
+ }
+ }
+ else
+ {
+ float t = ( p->dist - sn ) / dn;
+ if ( dn < 0 ) {
+ if ( !in || t > *t_in ) {
+ *t_in = t;
+ in = qtrue;
+ // as t_in can only increase, and t_out can only decrease, early out
+ if ( out && *t_in >= *t_out ) {
+ return qfalse;
+ }
+ }
+ }
+ else
+ {
+ if ( !out || t < *t_out ) {
+ *t_out = t;
+ out = qtrue;
+ // as t_in can only increase, and t_out can only decrease, early out
+ if ( in && *t_in >= *t_out ) {
+ return qfalse;
+ }
+ }
+ }
+ }
+ }
+ return in && out;
+}
+
+static float MiniMapSample( float x, float y ){
+ vec3_t org, dir;
+ int i, bi;
+ float t0, t1;
+ float samp;
+ bspBrush_t *b;
+ bspBrushSide_t *s;
+ int cnt;
+
+ org[0] = x;
+ org[1] = y;
+ org[2] = 0;
+ dir[0] = 0;
+ dir[1] = 0;
+ dir[2] = 1;
+
+ cnt = 0;
+ samp = 0;
+ for ( i = 0; i < minimap.model->numBSPBrushes; ++i )
+ {
+ bi = minimap.model->firstBSPBrush + i;
+ if ( opaqueBrushes[bi >> 3] & ( 1 << ( bi & 7 ) ) ) {
+ b = &bspBrushes[bi];
+
+ // sort out mins/maxs of the brush
+ s = &bspBrushSides[b->firstSide];
+ if ( x < -bspPlanes[s[0].planeNum].dist ) {
+ continue;
+ }
+ if ( x > +bspPlanes[s[1].planeNum].dist ) {
+ continue;
+ }
+ if ( y < -bspPlanes[s[2].planeNum].dist ) {
+ continue;
+ }
+ if ( y > +bspPlanes[s[3].planeNum].dist ) {
+ continue;
+ }
+
+ if ( BrushIntersectionWithLine( b, org, dir, &t0, &t1 ) ) {
+ samp += t1 - t0;
+ ++cnt;
+ }
+ }
+ }
+
+ return samp;
+}
+
+void RandomVector2f( float v[2] ){
+ do
+ {
+ v[0] = 2 * Random() - 1;
+ v[1] = 2 * Random() - 1;
+ }
+ while ( v[0] * v[0] + v[1] * v[1] > 1 );
+}
+
+static void MiniMapRandomlySupersampled( int y ){
+ int x, i;
+ float *p = &minimap.data1f[y * minimap.width];
+ float ymin = minimap.mins[1] + minimap.size[1] * ( y / (float) minimap.height );
+ float dx = minimap.size[0] / (float) minimap.width;
+ float dy = minimap.size[1] / (float) minimap.height;
+ float uv[2];
+ float thisval;
+
+ for ( x = 0; x < minimap.width; ++x )
+ {
+ float xmin = minimap.mins[0] + minimap.size[0] * ( x / (float) minimap.width );
+ float val = 0;
+
+ for ( i = 0; i < minimap.samples; ++i )
+ {
+ RandomVector2f( uv );
+ thisval = MiniMapSample(
+ xmin + ( uv[0] + 0.5 ) * dx, /* exaggerated random pattern for better results */
+ ymin + ( uv[1] + 0.5 ) * dy /* exaggerated random pattern for better results */
+ );
+ val += thisval;
+ }
+ val /= minimap.samples * minimap.size[2];
+ *p++ = val;
+ }
+}
+
+static void MiniMapSupersampled( int y ){
+ int x, i;
+ float *p = &minimap.data1f[y * minimap.width];
+ float ymin = minimap.mins[1] + minimap.size[1] * ( y / (float) minimap.height );
+ float dx = minimap.size[0] / (float) minimap.width;
+ float dy = minimap.size[1] / (float) minimap.height;
+
+ for ( x = 0; x < minimap.width; ++x )
+ {
+ float xmin = minimap.mins[0] + minimap.size[0] * ( x / (float) minimap.width );
+ float val = 0;
+
+ for ( i = 0; i < minimap.samples; ++i )
+ {
+ float thisval = MiniMapSample(
+ xmin + minimap.sample_offsets[2 * i + 0] * dx,
+ ymin + minimap.sample_offsets[2 * i + 1] * dy
+ );
+ val += thisval;
+ }
+ val /= minimap.samples * minimap.size[2];
+ *p++ = val;
+ }
+}
+
+static void MiniMapNoSupersampling( int y ){
+ int x;
+ float *p = &minimap.data1f[y * minimap.width];
+ float ymin = minimap.mins[1] + minimap.size[1] * ( ( y + 0.5 ) / (float) minimap.height );
+
+ for ( x = 0; x < minimap.width; ++x )
+ {
+ float xmin = minimap.mins[0] + minimap.size[0] * ( ( x + 0.5 ) / (float) minimap.width );
+ *p++ = MiniMapSample( xmin, ymin ) / minimap.size[2];
+ }
+}
+
+static void MiniMapSharpen( int y ){
+ int x;
+ qboolean up = ( y > 0 );
+ qboolean down = ( y < minimap.height - 1 );
+ float *p = &minimap.data1f[y * minimap.width];
+ float *q = &minimap.sharpendata1f[y * minimap.width];
+
+ for ( x = 0; x < minimap.width; ++x )
+ {
+ qboolean left = ( x > 0 );
+ qboolean right = ( x < minimap.width - 1 );
+ float val = p[0] * minimap.sharpen_centermult;
+
+ if ( left && up ) {
+ val += p[-1 - minimap.width] * minimap.sharpen_boxmult;
+ }
+ if ( left && down ) {
+ val += p[-1 + minimap.width] * minimap.sharpen_boxmult;
+ }
+ if ( right && up ) {
+ val += p[+1 - minimap.width] * minimap.sharpen_boxmult;
+ }
+ if ( right && down ) {
+ val += p[+1 + minimap.width] * minimap.sharpen_boxmult;
+ }
+
+ if ( left ) {
+ val += p[-1] * minimap.sharpen_boxmult;
+ }
+ if ( right ) {
+ val += p[+1] * minimap.sharpen_boxmult;
+ }
+ if ( up ) {
+ val += p[-minimap.width] * minimap.sharpen_boxmult;
+ }
+ if ( down ) {
+ val += p[+minimap.width] * minimap.sharpen_boxmult;
+ }
+
+ ++p;
+ *q++ = val;
+ }
+}
+
+static void MiniMapContrastBoost( int y ){
+ int x;
+ float *q = &minimap.data1f[y * minimap.width];
+ for ( x = 0; x < minimap.width; ++x )
+ {
+ *q = *q * minimap.boost / ( ( minimap.boost - 1 ) * *q + 1 );
+ ++q;
+ }
+}
+
+static void MiniMapBrightnessContrast( int y ){
+ int x;
+ float *q = &minimap.data1f[y * minimap.width];
+ for ( x = 0; x < minimap.width; ++x )
+ {
+ *q = *q * minimap.contrast + minimap.brightness;
+ ++q;
+ }
+}
+
+void MiniMapMakeMinsMaxs( vec3_t mins_in, vec3_t maxs_in, float border, qboolean keepaspect ){
+ vec3_t mins, maxs, extend;
+ VectorCopy( mins_in, mins );
+ VectorCopy( maxs_in, maxs );
+
+ // line compatible to nexuiz mapinfo
+ Sys_Printf( "size %f %f %f %f %f %f\n", mins[0], mins[1], mins[2], maxs[0], maxs[1], maxs[2] );
+
+ if ( keepaspect ) {
+ VectorSubtract( maxs, mins, extend );
+ if ( extend[1] > extend[0] ) {
+ mins[0] -= ( extend[1] - extend[0] ) * 0.5;
+ maxs[0] += ( extend[1] - extend[0] ) * 0.5;
+ }
+ else
+ {
+ mins[1] -= ( extend[0] - extend[1] ) * 0.5;
+ maxs[1] += ( extend[0] - extend[1] ) * 0.5;
+ }
+ }
+
+ /* border: amount of black area around the image */
+ /* input: border, 1-2*border, border but we need border/(1-2*border) */
+
+ VectorSubtract( maxs, mins, extend );
+ VectorScale( extend, border / ( 1 - 2 * border ), extend );
+
+ VectorSubtract( mins, extend, mins );
+ VectorAdd( maxs, extend, maxs );
+
+ VectorCopy( mins, minimap.mins );
+ VectorSubtract( maxs, mins, minimap.size );
+
+ // line compatible to nexuiz mapinfo
+ Sys_Printf( "size_texcoords %f %f %f %f %f %f\n", mins[0], mins[1], mins[2], maxs[0], maxs[1], maxs[2] );
+}
+
+/*
+ MiniMapSetupBrushes()
+ determines solid non-sky brushes in the world
+ */
+
+void MiniMapSetupBrushes( void ){
+ SetupBrushesFlags( C_SOLID | C_SKY, C_SOLID, 0, 0 );
+ // at least one must be solid
+ // none may be sky
+ // not all may be nodraw
+}
+
+qboolean MiniMapEvaluateSampleOffsets( int *bestj, int *bestk, float *bestval ){
+ float val, dx, dy;
+ int j, k;
+
+ *bestj = *bestk = -1;
+ *bestval = 3; /* max possible val is 2 */
+
+ for ( j = 0; j < minimap.samples; ++j )
+ for ( k = j + 1; k < minimap.samples; ++k )
+ {
+ dx = minimap.sample_offsets[2 * j + 0] - minimap.sample_offsets[2 * k + 0];
+ dy = minimap.sample_offsets[2 * j + 1] - minimap.sample_offsets[2 * k + 1];
+ if ( dx > +0.5 ) {
+ dx -= 1;
+ }
+ if ( dx < -0.5 ) {
+ dx += 1;
+ }
+ if ( dy > +0.5 ) {
+ dy -= 1;
+ }
+ if ( dy < -0.5 ) {
+ dy += 1;
+ }
+ val = dx * dx + dy * dy;
+ if ( val < *bestval ) {
+ *bestj = j;
+ *bestk = k;
+ *bestval = val;
+ }
+ }
+
+ return *bestval < 3;
+}
+
+void MiniMapMakeSampleOffsets(){
+ int i, j, k, jj, kk;
+ float val, valj, valk, sx, sy, rx, ry;
+
+ Sys_Printf( "Generating good sample offsets (this may take a while)...\n" );
+
+ /* start with entirely random samples */
+ for ( i = 0; i < minimap.samples; ++i )
+ {
+ minimap.sample_offsets[2 * i + 0] = Random();
+ minimap.sample_offsets[2 * i + 1] = Random();
+ }
+
+ for ( i = 0; i < 1000; ++i )
+ {
+ if ( MiniMapEvaluateSampleOffsets( &j, &k, &val ) ) {
+ sx = minimap.sample_offsets[2 * j + 0];
+ sy = minimap.sample_offsets[2 * j + 1];
+ minimap.sample_offsets[2 * j + 0] = rx = Random();
+ minimap.sample_offsets[2 * j + 1] = ry = Random();
+ if ( !MiniMapEvaluateSampleOffsets( &jj, &kk, &valj ) ) {
+ valj = -1;
+ }
+ minimap.sample_offsets[2 * j + 0] = sx;
+ minimap.sample_offsets[2 * j + 1] = sy;
+
+ sx = minimap.sample_offsets[2 * k + 0];
+ sy = minimap.sample_offsets[2 * k + 1];
+ minimap.sample_offsets[2 * k + 0] = rx;
+ minimap.sample_offsets[2 * k + 1] = ry;
+ if ( !MiniMapEvaluateSampleOffsets( &jj, &kk, &valk ) ) {
+ valk = -1;
+ }
+ minimap.sample_offsets[2 * k + 0] = sx;
+ minimap.sample_offsets[2 * k + 1] = sy;
+
+ if ( valj > valk ) {
+ if ( valj > val ) {
+ /* valj is the greatest */
+ minimap.sample_offsets[2 * j + 0] = rx;
+ minimap.sample_offsets[2 * j + 1] = ry;
+ i = -1;
+ }
+ else
+ {
+ /* valj is the greater and it is useless - forget it */
+ }
+ }
+ else
+ {
+ if ( valk > val ) {
+ /* valk is the greatest */
+ minimap.sample_offsets[2 * k + 0] = rx;
+ minimap.sample_offsets[2 * k + 1] = ry;
+ i = -1;
+ }
+ else
+ {
+ /* valk is the greater and it is useless - forget it */
+ }
+ }
+ }
+ else{
+ break;
+ }
+ }
+}
+
+void MergeRelativePath( char *out, const char *absolute, const char *relative ){
+ const char *endpos = absolute + strlen( absolute );
+ while ( endpos != absolute && ( endpos[-1] == '/' || endpos[-1] == '\\' ) )
+ --endpos;
+ while ( relative[0] == '.' && relative[1] == '.' && ( relative[2] == '/' || relative[2] == '\\' ) )
+ {
+ relative += 3;
+ while ( endpos != absolute )
+ {
+ --endpos;
+ if ( *endpos == '/' || *endpos == '\\' ) {
+ break;
+ }
+ }
+ while ( endpos != absolute && ( endpos[-1] == '/' || endpos[-1] == '\\' ) )
+ --endpos;
+ }
+ memcpy( out, absolute, endpos - absolute );
+ out[endpos - absolute] = '/';
+ strcpy( out + ( endpos - absolute + 1 ), relative );
+}
+
+int MiniMapBSPMain( int argc, char **argv ){
+ char minimapFilename[1024];
+ char basename[1024];
+ char path[1024];
+ char relativeMinimapFilename[1024];
+ qboolean autolevel;
+ float minimapSharpen;
+ float border;
+ byte *data4b, *p;
+ float *q;
+ int x, y;
+ int i;
+ miniMapMode_t mode;
+ vec3_t mins, maxs;
+ qboolean keepaspect;
+
+ /* arg checking */
+ if ( argc < 2 ) {
+ Sys_Printf( "Usage: q3map [-v] -minimap [-size n] [-sharpen f] [-samples n | -random n] [-o filename.tga] [-minmax Xmin Ymin Zmin Xmax Ymax Zmax] <mapname>\n" );
+ return 0;
+ }
+
+ /* load the BSP first */
+ strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
+ StripExtension( source );
+ DefaultExtension( source, ".bsp" );
+ Sys_Printf( "Loading %s\n", source );
+ BeginMapShaderFile( source );
+ LoadShaderInfo();
+ LoadBSPFile( source );
+
+ minimap.model = &bspModels[0];
+ VectorCopy( minimap.model->mins, mins );
+ VectorCopy( minimap.model->maxs, maxs );
+
+ *minimapFilename = 0;
+ minimapSharpen = game->miniMapSharpen;
+ minimap.width = minimap.height = game->miniMapSize;
+ border = game->miniMapBorder;
+ keepaspect = game->miniMapKeepAspect;
+ mode = game->miniMapMode;
+
+ autolevel = qfalse;
+ minimap.samples = 1;
+ minimap.sample_offsets = NULL;
+ minimap.boost = 1.0;
+ minimap.brightness = 0.0;
+ minimap.contrast = 1.0;
+
+ /* process arguments */
+ for ( i = 1; i < ( argc - 1 ); i++ )
+ {
+ if ( !strcmp( argv[ i ], "-size" ) ) {
+ minimap.width = minimap.height = atoi( argv[i + 1] );
+ i++;
+ Sys_Printf( "Image size set to %i\n", minimap.width );
+ }
+ else if ( !strcmp( argv[ i ], "-sharpen" ) ) {
+ minimapSharpen = atof( argv[i + 1] );
+ i++;
+ Sys_Printf( "Sharpening coefficient set to %f\n", minimapSharpen );
+ }
+ else if ( !strcmp( argv[ i ], "-samples" ) ) {
+ minimap.samples = atoi( argv[i + 1] );
+ i++;
+ Sys_Printf( "Samples set to %i\n", minimap.samples );
+ if ( minimap.sample_offsets ) {
+ free( minimap.sample_offsets );
+ }
+ minimap.sample_offsets = malloc( 2 * sizeof( *minimap.sample_offsets ) * minimap.samples );
+ MiniMapMakeSampleOffsets();
+ }
+ else if ( !strcmp( argv[ i ], "-random" ) ) {
+ minimap.samples = atoi( argv[i + 1] );
+ i++;
+ Sys_Printf( "Random samples set to %i\n", minimap.samples );
+ if ( minimap.sample_offsets ) {
+ free( minimap.sample_offsets );
+ }
+ minimap.sample_offsets = NULL;
+ }
+ else if ( !strcmp( argv[ i ], "-border" ) ) {
+ border = atof( argv[i + 1] );
+ i++;
+ Sys_Printf( "Border set to %f\n", border );
+ }
+ else if ( !strcmp( argv[ i ], "-keepaspect" ) ) {
+ keepaspect = qtrue;
+ Sys_Printf( "Keeping aspect ratio by letterboxing\n", border );
+ }
+ else if ( !strcmp( argv[ i ], "-nokeepaspect" ) ) {
+ keepaspect = qfalse;
+ Sys_Printf( "Not keeping aspect ratio\n", border );
+ }
+ else if ( !strcmp( argv[ i ], "-o" ) ) {
+ strcpy( minimapFilename, argv[i + 1] );
+ i++;
+ Sys_Printf( "Output file name set to %s\n", minimapFilename );
+ }
+ else if ( !strcmp( argv[ i ], "-minmax" ) && i < ( argc - 7 ) ) {
+ mins[0] = atof( argv[i + 1] );
+ mins[1] = atof( argv[i + 2] );
+ mins[2] = atof( argv[i + 3] );
+ maxs[0] = atof( argv[i + 4] );
+ maxs[1] = atof( argv[i + 5] );
+ maxs[2] = atof( argv[i + 6] );
+ i += 6;
+ Sys_Printf( "Map mins/maxs overridden\n" );
+ }
+ else if ( !strcmp( argv[ i ], "-gray" ) ) {
+ mode = MINIMAP_MODE_GRAY;
+ Sys_Printf( "Writing as white-on-black image\n" );
+ }
+ else if ( !strcmp( argv[ i ], "-black" ) ) {
+ mode = MINIMAP_MODE_BLACK;
+ Sys_Printf( "Writing as black alpha image\n" );
+ }
+ else if ( !strcmp( argv[ i ], "-white" ) ) {
+ mode = MINIMAP_MODE_WHITE;
+ Sys_Printf( "Writing as white alpha image\n" );
+ }
+ else if ( !strcmp( argv[ i ], "-boost" ) && i < ( argc - 2 ) ) {
+ minimap.boost = atof( argv[i + 1] );
+ i++;
+ Sys_Printf( "Contrast boost set to %f\n", minimap.boost );
+ }
+ else if ( !strcmp( argv[ i ], "-brightness" ) && i < ( argc - 2 ) ) {
+ minimap.brightness = atof( argv[i + 1] );
+ i++;
+ Sys_Printf( "Brightness set to %f\n", minimap.brightness );
+ }
+ else if ( !strcmp( argv[ i ], "-contrast" ) && i < ( argc - 2 ) ) {
+ minimap.contrast = atof( argv[i + 1] );
+ i++;
+ Sys_Printf( "Contrast set to %f\n", minimap.contrast );
+ }
+ else if ( !strcmp( argv[ i ], "-autolevel" ) ) {
+ autolevel = qtrue;
+ Sys_Printf( "Auto level enabled\n", border );
+ }
+ else if ( !strcmp( argv[ i ], "-noautolevel" ) ) {
+ autolevel = qfalse;
+ Sys_Printf( "Auto level disabled\n", border );
+ }
+ }
+
+ MiniMapMakeMinsMaxs( mins, maxs, border, keepaspect );
+
+ if ( !*minimapFilename ) {
+ ExtractFileBase( source, basename );
+ ExtractFilePath( source, path );
+ sprintf( relativeMinimapFilename, game->miniMapNameFormat, basename );
+ MergeRelativePath( minimapFilename, path, relativeMinimapFilename );
+ Sys_Printf( "Output file name automatically set to %s\n", minimapFilename );
+ }
+ ExtractFilePath( minimapFilename, path );
+ Q_mkdir( path );
+
+ if ( minimapSharpen >= 0 ) {
+ minimap.sharpen_centermult = 8 * minimapSharpen + 1;
+ minimap.sharpen_boxmult = -minimapSharpen;
+ }
+
+ minimap.data1f = safe_malloc( minimap.width * minimap.height * sizeof( *minimap.data1f ) );
+ data4b = safe_malloc( minimap.width * minimap.height * 4 );
+ if ( minimapSharpen >= 0 ) {
+ minimap.sharpendata1f = safe_malloc( minimap.width * minimap.height * sizeof( *minimap.data1f ) );
+ }
+
+ MiniMapSetupBrushes();
+
+ if ( minimap.samples <= 1 ) {
+ Sys_Printf( "\n--- MiniMapNoSupersampling (%d) ---\n", minimap.height );
+ RunThreadsOnIndividual( minimap.height, qtrue, MiniMapNoSupersampling );
+ }
+ else
+ {
+ if ( minimap.sample_offsets ) {
+ Sys_Printf( "\n--- MiniMapSupersampled (%d) ---\n", minimap.height );
+ RunThreadsOnIndividual( minimap.height, qtrue, MiniMapSupersampled );
+ }
+ else
+ {
+ Sys_Printf( "\n--- MiniMapRandomlySupersampled (%d) ---\n", minimap.height );
+ RunThreadsOnIndividual( minimap.height, qtrue, MiniMapRandomlySupersampled );
+ }
+ }
+
+ if ( minimap.boost != 1.0 ) {
+ Sys_Printf( "\n--- MiniMapContrastBoost (%d) ---\n", minimap.height );
+ RunThreadsOnIndividual( minimap.height, qtrue, MiniMapContrastBoost );
+ }
+
+ if ( autolevel ) {
+ Sys_Printf( "\n--- MiniMapAutoLevel (%d) ---\n", minimap.height );
+ float mi = 1, ma = 0;
+ float s, o;
+
+ // TODO threads!
+ q = minimap.data1f;
+ for ( y = 0; y < minimap.height; ++y )
+ for ( x = 0; x < minimap.width; ++x )
+ {
+ float v = *q++;
+ if ( v < mi ) {
+ mi = v;
+ }
+ if ( v > ma ) {
+ ma = v;
+ }
+ }
+ if ( ma > mi ) {
+ s = 1 / ( ma - mi );
+ o = mi / ( ma - mi );
+
+ // equations:
+ // brightness + contrast * v
+ // after autolevel:
+ // brightness + contrast * (v * s - o)
+ // =
+ // (brightness - contrast * o) + (contrast * s) * v
+ minimap.brightness = minimap.brightness - minimap.contrast * o;
+ minimap.contrast *= s;
+
+ Sys_Printf( "Auto level: Brightness changed to %f\n", minimap.brightness );
+ Sys_Printf( "Auto level: Contrast changed to %f\n", minimap.contrast );
+ }
+ else{
+ Sys_Printf( "Auto level: failed because all pixels are the same value\n" );
+ }
+ }
+
+ if ( minimap.brightness != 0 || minimap.contrast != 1 ) {
+ Sys_Printf( "\n--- MiniMapBrightnessContrast (%d) ---\n", minimap.height );
+ RunThreadsOnIndividual( minimap.height, qtrue, MiniMapBrightnessContrast );
+ }
+
+ if ( minimap.sharpendata1f ) {
+ Sys_Printf( "\n--- MiniMapSharpen (%d) ---\n", minimap.height );
+ RunThreadsOnIndividual( minimap.height, qtrue, MiniMapSharpen );
+ q = minimap.sharpendata1f;
+ }
+ else
+ {
+ q = minimap.data1f;
+ }
+
+ Sys_Printf( "\nConverting..." );
+
+ switch ( mode )
+ {
+ case MINIMAP_MODE_GRAY:
+ p = data4b;
+ for ( y = 0; y < minimap.height; ++y )
+ for ( x = 0; x < minimap.width; ++x )
+ {
+ byte b;
+ float v = *q++;
+ if ( v < 0 ) {
+ v = 0;
+ }
+ if ( v > 255.0 / 256.0 ) {
+ v = 255.0 / 256.0;
+ }
+ b = v * 256;
+ *p++ = b;
+ }
+ Sys_Printf( " writing to %s...", minimapFilename );
+ WriteTGAGray( minimapFilename, data4b, minimap.width, minimap.height );
+ break;
+ case MINIMAP_MODE_BLACK:
+ p = data4b;
+ for ( y = 0; y < minimap.height; ++y )
+ for ( x = 0; x < minimap.width; ++x )
+ {
+ byte b;
+ float v = *q++;
+ if ( v < 0 ) {
+ v = 0;
+ }
+ if ( v > 255.0 / 256.0 ) {
+ v = 255.0 / 256.0;
+ }
+ b = v * 256;
+ *p++ = 0;
+ *p++ = 0;
+ *p++ = 0;
+ *p++ = b;
+ }
+ Sys_Printf( " writing to %s...", minimapFilename );
+ WriteTGA( minimapFilename, data4b, minimap.width, minimap.height );
+ break;
+ case MINIMAP_MODE_WHITE:
+ p = data4b;
+ for ( y = 0; y < minimap.height; ++y )
+ for ( x = 0; x < minimap.width; ++x )
+ {
+ byte b;
+ float v = *q++;
+ if ( v < 0 ) {
+ v = 0;
+ }
+ if ( v > 255.0 / 256.0 ) {
+ v = 255.0 / 256.0;
+ }
+ b = v * 256;
+ *p++ = 255;
+ *p++ = 255;
+ *p++ = 255;
+ *p++ = b;
+ }
+ Sys_Printf( " writing to %s...", minimapFilename );
+ WriteTGA( minimapFilename, data4b, minimap.width, minimap.height );
+ break;
+ }
+
+ Sys_Printf( " done.\n" );
+
+ /* return to sender */
+ return 0;
+}
+
+
+
+
+
+/*
+ MD4BlockChecksum()
+ calculates an md4 checksum for a block of data
+ */
+
+static int MD4BlockChecksum( void *buffer, int length ){
+ return Com_BlockChecksum( buffer, length );
}
/*
lump = (byte*) header + offset;
lumpInt = LittleLong( (int) *( (int*) lump ) );
lumpFloat = LittleFloat( (float) *( (float*) lump ) );
- memcpy( lumpString, (char*) lump, ( length < 1024 ? length : 1024 ) );
- lumpString[ 1024 ] = '\0';
+ memcpy( lumpString, (char*) lump, ( (size_t)length < sizeof( lumpString ) ? (size_t)length : sizeof( lumpString ) - 1 ) );
+ lumpString[ sizeof( lumpString ) - 1 ] = '\0';
/* print basic lump info */
Sys_Printf( "Lump: %d\n", i );
}
+static void ExtrapolateTexcoords( const float *axyz, const float *ast, const float *bxyz, const float *bst, const float *cxyz, const float *cst, const float *axyz_new, float *ast_out, const float *bxyz_new, float *bst_out, const float *cxyz_new, float *cst_out ){
+ vec4_t scoeffs, tcoeffs;
+ float md;
+ m4x4_t solvematrix;
+
+ vec3_t norm;
+ vec3_t dab, dac;
+ VectorSubtract( bxyz, axyz, dab );
+ VectorSubtract( cxyz, axyz, dac );
+ CrossProduct( dab, dac, norm );
+
+ // assume:
+ // s = f(x, y, z)
+ // s(v + norm) = s(v) when n ortho xyz
+
+ // s(v) = DotProduct(v, scoeffs) + scoeffs[3]
+
+ // solve:
+ // scoeffs * (axyz, 1) == ast[0]
+ // scoeffs * (bxyz, 1) == bst[0]
+ // scoeffs * (cxyz, 1) == cst[0]
+ // scoeffs * (norm, 0) == 0
+ // scoeffs * [axyz, 1 | bxyz, 1 | cxyz, 1 | norm, 0] = [ast[0], bst[0], cst[0], 0]
+ solvematrix[0] = axyz[0];
+ solvematrix[4] = axyz[1];
+ solvematrix[8] = axyz[2];
+ solvematrix[12] = 1;
+ solvematrix[1] = bxyz[0];
+ solvematrix[5] = bxyz[1];
+ solvematrix[9] = bxyz[2];
+ solvematrix[13] = 1;
+ solvematrix[2] = cxyz[0];
+ solvematrix[6] = cxyz[1];
+ solvematrix[10] = cxyz[2];
+ solvematrix[14] = 1;
+ solvematrix[3] = norm[0];
+ solvematrix[7] = norm[1];
+ solvematrix[11] = norm[2];
+ solvematrix[15] = 0;
+
+ md = m4_det( solvematrix );
+ if ( md * md < 1e-10 ) {
+ Sys_Printf( "Cannot invert some matrix, some texcoords aren't extrapolated!" );
+ return;
+ }
+
+ m4x4_invert( solvematrix );
+
+ scoeffs[0] = ast[0];
+ scoeffs[1] = bst[0];
+ scoeffs[2] = cst[0];
+ scoeffs[3] = 0;
+ m4x4_transform_vec4( solvematrix, scoeffs );
+ tcoeffs[0] = ast[1];
+ tcoeffs[1] = bst[1];
+ tcoeffs[2] = cst[1];
+ tcoeffs[3] = 0;
+ m4x4_transform_vec4( solvematrix, tcoeffs );
+
+ ast_out[0] = scoeffs[0] * axyz_new[0] + scoeffs[1] * axyz_new[1] + scoeffs[2] * axyz_new[2] + scoeffs[3];
+ ast_out[1] = tcoeffs[0] * axyz_new[0] + tcoeffs[1] * axyz_new[1] + tcoeffs[2] * axyz_new[2] + tcoeffs[3];
+ bst_out[0] = scoeffs[0] * bxyz_new[0] + scoeffs[1] * bxyz_new[1] + scoeffs[2] * bxyz_new[2] + scoeffs[3];
+ bst_out[1] = tcoeffs[0] * bxyz_new[0] + tcoeffs[1] * bxyz_new[1] + tcoeffs[2] * bxyz_new[2] + tcoeffs[3];
+ cst_out[0] = scoeffs[0] * cxyz_new[0] + scoeffs[1] * cxyz_new[1] + scoeffs[2] * cxyz_new[2] + scoeffs[3];
+ cst_out[1] = tcoeffs[0] * cxyz_new[0] + tcoeffs[1] * cxyz_new[1] + tcoeffs[2] * cxyz_new[2] + tcoeffs[3];
+}
/*
ScaleBSPMain()
*/
int ScaleBSPMain( int argc, char **argv ){
- int i;
- float f, scale;
+ int i, j;
+ float f, a;
+ vec3_t scale;
vec3_t vec;
char str[ 1024 ];
+ int uniform, axis;
+ qboolean texscale;
+ float *old_xyzst = NULL;
+ float spawn_ref = 0;
/* arg checking */
- if ( argc < 2 ) {
- Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
+ if ( argc < 3 ) {
+ Sys_Printf( "Usage: q3map [-v] -scale [-tex] [-spawn_ref <value>] <value> <mapname>\n" );
return 0;
}
+ texscale = qfalse;
+ for ( i = 1; i < argc - 2; ++i )
+ {
+ if ( !strcmp( argv[i], "-tex" ) ) {
+ texscale = qtrue;
+ }
+ else if ( !strcmp( argv[i], "-spawn_ref" ) ) {
+ spawn_ref = atof( argv[i + 1] );
+ ++i;
+ }
+ else{
+ break;
+ }
+ }
+
/* get scale */
- scale = atof( argv[ argc - 2 ] );
- if ( scale == 0.0f ) {
- Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
+ // if(argc-2 >= i) // always true
+ scale[2] = scale[1] = scale[0] = atof( argv[ argc - 2 ] );
+ if ( argc - 3 >= i ) {
+ scale[1] = scale[0] = atof( argv[ argc - 3 ] );
+ }
+ if ( argc - 4 >= i ) {
+ scale[0] = atof( argv[ argc - 4 ] );
+ }
+
+ uniform = ( ( scale[0] == scale[1] ) && ( scale[1] == scale[2] ) );
+
+ if ( scale[0] == 0.0f || scale[1] == 0.0f || scale[2] == 0.0f ) {
+ Sys_Printf( "Usage: q3map [-v] -scale [-tex] [-spawn_ref <value>] <value> <mapname>\n" );
Sys_Printf( "Non-zero scale value required.\n" );
return 0;
}
{
/* scale origin */
GetVectorForKey( &entities[ i ], "origin", vec );
- if ( ( vec[ 0 ] + vec[ 1 ] + vec[ 2 ] ) ) {
- VectorScale( vec, scale, vec );
+ if ( ( vec[ 0 ] || vec[ 1 ] || vec[ 2 ] ) ) {
+ if ( !strncmp( ValueForKey( &entities[i], "classname" ), "info_player_", 12 ) ) {
+ vec[2] += spawn_ref;
+ }
+ vec[0] *= scale[0];
+ vec[1] *= scale[1];
+ vec[2] *= scale[2];
+ if ( !strncmp( ValueForKey( &entities[i], "classname" ), "info_player_", 12 ) ) {
+ vec[2] -= spawn_ref;
+ }
sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
SetKeyValue( &entities[ i ], "origin", str );
}
+ a = FloatForKey( &entities[ i ], "angle" );
+ if ( a == -1 || a == -2 ) { // z scale
+ axis = 2;
+ }
+ else if ( fabs( sin( DEG2RAD( a ) ) ) < 0.707 ) {
+ axis = 0;
+ }
+ else{
+ axis = 1;
+ }
+
/* scale door lip */
f = FloatForKey( &entities[ i ], "lip" );
if ( f ) {
- f *= scale;
+ f *= scale[axis];
sprintf( str, "%f", f );
SetKeyValue( &entities[ i ], "lip", str );
}
+
+ /* scale plat height */
+ f = FloatForKey( &entities[ i ], "height" );
+ if ( f ) {
+ f *= scale[2];
+ sprintf( str, "%f", f );
+ SetKeyValue( &entities[ i ], "height", str );
+ }
+
+ // TODO maybe allow a definition file for entities to specify which values are scaled how?
}
/* scale models */
for ( i = 0; i < numBSPModels; i++ )
{
- VectorScale( bspModels[ i ].mins, scale, bspModels[ i ].mins );
- VectorScale( bspModels[ i ].maxs, scale, bspModels[ i ].maxs );
+ bspModels[ i ].mins[0] *= scale[0];
+ bspModels[ i ].mins[1] *= scale[1];
+ bspModels[ i ].mins[2] *= scale[2];
+ bspModels[ i ].maxs[0] *= scale[0];
+ bspModels[ i ].maxs[1] *= scale[1];
+ bspModels[ i ].maxs[2] *= scale[2];
}
/* scale nodes */
for ( i = 0; i < numBSPNodes; i++ )
{
- VectorScale( bspNodes[ i ].mins, scale, bspNodes[ i ].mins );
- VectorScale( bspNodes[ i ].maxs, scale, bspNodes[ i ].maxs );
+ bspNodes[ i ].mins[0] *= scale[0];
+ bspNodes[ i ].mins[1] *= scale[1];
+ bspNodes[ i ].mins[2] *= scale[2];
+ bspNodes[ i ].maxs[0] *= scale[0];
+ bspNodes[ i ].maxs[1] *= scale[1];
+ bspNodes[ i ].maxs[2] *= scale[2];
}
/* scale leafs */
for ( i = 0; i < numBSPLeafs; i++ )
{
- VectorScale( bspLeafs[ i ].mins, scale, bspLeafs[ i ].mins );
- VectorScale( bspLeafs[ i ].maxs, scale, bspLeafs[ i ].maxs );
+ bspLeafs[ i ].mins[0] *= scale[0];
+ bspLeafs[ i ].mins[1] *= scale[1];
+ bspLeafs[ i ].mins[2] *= scale[2];
+ bspLeafs[ i ].maxs[0] *= scale[0];
+ bspLeafs[ i ].maxs[1] *= scale[1];
+ bspLeafs[ i ].maxs[2] *= scale[2];
+ }
+
+ if ( texscale ) {
+ Sys_Printf( "Using texture unlocking (and probably breaking texture alignment a lot)\n" );
+ old_xyzst = safe_malloc( sizeof( *old_xyzst ) * numBSPDrawVerts * 5 );
+ for ( i = 0; i < numBSPDrawVerts; i++ )
+ {
+ old_xyzst[5 * i + 0] = bspDrawVerts[i].xyz[0];
+ old_xyzst[5 * i + 1] = bspDrawVerts[i].xyz[1];
+ old_xyzst[5 * i + 2] = bspDrawVerts[i].xyz[2];
+ old_xyzst[5 * i + 3] = bspDrawVerts[i].st[0];
+ old_xyzst[5 * i + 4] = bspDrawVerts[i].st[1];
+ }
}
/* scale drawverts */
for ( i = 0; i < numBSPDrawVerts; i++ )
- VectorScale( bspDrawVerts[ i ].xyz, scale, bspDrawVerts[ i ].xyz );
+ {
+ bspDrawVerts[i].xyz[0] *= scale[0];
+ bspDrawVerts[i].xyz[1] *= scale[1];
+ bspDrawVerts[i].xyz[2] *= scale[2];
+ bspDrawVerts[i].normal[0] /= scale[0];
+ bspDrawVerts[i].normal[1] /= scale[1];
+ bspDrawVerts[i].normal[2] /= scale[2];
+ VectorNormalize( bspDrawVerts[i].normal, bspDrawVerts[i].normal );
+ }
+
+ if ( texscale ) {
+ for ( i = 0; i < numBSPDrawSurfaces; i++ )
+ {
+ switch ( bspDrawSurfaces[i].surfaceType )
+ {
+ case SURFACE_FACE:
+ case SURFACE_META:
+ if ( bspDrawSurfaces[i].numIndexes % 3 ) {
+ Error( "Not a triangulation!" );
+ }
+ for ( j = bspDrawSurfaces[i].firstIndex; j < bspDrawSurfaces[i].firstIndex + bspDrawSurfaces[i].numIndexes; j += 3 )
+ {
+ int ia = bspDrawIndexes[j] + bspDrawSurfaces[i].firstVert, ib = bspDrawIndexes[j + 1] + bspDrawSurfaces[i].firstVert, ic = bspDrawIndexes[j + 2] + bspDrawSurfaces[i].firstVert;
+ bspDrawVert_t *a = &bspDrawVerts[ia], *b = &bspDrawVerts[ib], *c = &bspDrawVerts[ic];
+ float *oa = &old_xyzst[ia * 5], *ob = &old_xyzst[ib * 5], *oc = &old_xyzst[ic * 5];
+ // extrapolate:
+ // a->xyz -> oa
+ // b->xyz -> ob
+ // c->xyz -> oc
+ ExtrapolateTexcoords(
+ &oa[0], &oa[3],
+ &ob[0], &ob[3],
+ &oc[0], &oc[3],
+ a->xyz, a->st,
+ b->xyz, b->st,
+ c->xyz, c->st );
+ }
+ break;
+ }
+ }
+ }
/* scale planes */
- for ( i = 0; i < numBSPPlanes; i++ )
- bspPlanes[ i ].dist *= scale;
+ if ( uniform ) {
+ for ( i = 0; i < numBSPPlanes; i++ )
+ {
+ bspPlanes[ i ].dist *= scale[0];
+ }
+ }
+ else
+ {
+ for ( i = 0; i < numBSPPlanes; i++ )
+ {
+ bspPlanes[ i ].normal[0] /= scale[0];
+ bspPlanes[ i ].normal[1] /= scale[1];
+ bspPlanes[ i ].normal[2] /= scale[2];
+ f = 1 / VectorLength( bspPlanes[i].normal );
+ VectorScale( bspPlanes[i].normal, f, bspPlanes[i].normal );
+ bspPlanes[ i ].dist *= f;
+ }
+ }
/* scale gridsize */
GetVectorForKey( &entities[ 0 ], "gridsize", vec );
if ( ( vec[ 0 ] + vec[ 1 ] + vec[ 2 ] ) == 0.0f ) {
VectorCopy( gridSize, vec );
}
- VectorScale( vec, scale, vec );
+ vec[0] *= scale[0];
+ vec[1] *= scale[1];
+ vec[2] *= scale[2];
sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
SetKeyValue( &entities[ 0 ], "gridsize", str );
+ /* inject command line parameters */
+ InjectCommandLine( argv, 0, argc - 1 );
+
/* write the bsp */
UnparseEntities();
StripExtension( source );
}
+/*
+ PseudoCompileBSP()
+ a stripped down ProcessModels
+ */
+void PseudoCompileBSP( qboolean need_tree ){
+ int models;
+ char modelValue[10];
+ entity_t *entity;
+ face_t *faces;
+ tree_t *tree;
+ node_t *node;
+ brush_t *brush;
+ side_t *side;
+ int i;
+
+ SetDrawSurfacesBuffer();
+ mapDrawSurfs = safe_malloc( sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
+ memset( mapDrawSurfs, 0, sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
+ numMapDrawSurfs = 0;
+
+ BeginBSPFile();
+ models = 1;
+ for ( mapEntityNum = 0; mapEntityNum < numEntities; mapEntityNum++ )
+ {
+ /* get entity */
+ entity = &entities[ mapEntityNum ];
+ if ( entity->brushes == NULL && entity->patches == NULL ) {
+ continue;
+ }
+
+ if ( mapEntityNum != 0 ) {
+ sprintf( modelValue, "*%d", models++ );
+ SetKeyValue( entity, "model", modelValue );
+ }
+
+ /* process the model */
+ Sys_FPrintf( SYS_VRB, "############### model %i ###############\n", numBSPModels );
+ BeginModel();
+
+ entity->firstDrawSurf = numMapDrawSurfs;
+
+ ClearMetaTriangles();
+ PatchMapDrawSurfs( entity );
+
+ if ( mapEntityNum == 0 && need_tree ) {
+ faces = MakeStructuralBSPFaceList( entities[0].brushes );
+ tree = FaceBSP( faces );
+ node = tree->headnode;
+ }
+ else
+ {
+ node = AllocNode();
+ node->planenum = PLANENUM_LEAF;
+ tree = AllocTree();
+ tree->headnode = node;
+ }
+
+ /* a minimized ClipSidesIntoTree */
+ for ( brush = entity->brushes; brush; brush = brush->next )
+ {
+ /* walk the brush sides */
+ for ( i = 0; i < brush->numsides; i++ )
+ {
+ /* get side */
+ side = &brush->sides[ i ];
+ if ( side->winding == NULL ) {
+ continue;
+ }
+ /* shader? */
+ if ( side->shaderInfo == NULL ) {
+ continue;
+ }
+ /* save this winding as a visible surface */
+ DrawSurfaceForSide( entity, brush, side, side->winding );
+ }
+ }
+
+ if ( meta ) {
+ ClassifyEntitySurfaces( entity );
+ MakeEntityDecals( entity );
+ MakeEntityMetaTriangles( entity );
+ SmoothMetaTriangles();
+ MergeMetaTriangles();
+ }
+ FilterDrawsurfsIntoTree( entity, tree );
+
+ FilterStructuralBrushesIntoTree( entity, tree );
+ FilterDetailBrushesIntoTree( entity, tree );
+
+ EmitBrushes( entity->brushes, &entity->firstBrush, &entity->numBrushes );
+ EndModel( entity, node );
+ }
+ EndBSPFile( qfalse );
+}
/*
ConvertBSPMain()
int i;
int ( *convertFunc )( char * );
game_t *convertGame;
+ char ext[1024];
+ qboolean map_allowed, force_bsp, force_map;
/* set default */
convertFunc = ConvertBSPToASE;
convertGame = NULL;
+ map_allowed = qfalse;
+ force_bsp = qfalse;
+ force_map = qfalse;
/* arg checking */
if ( argc < 1 ) {
- Sys_Printf( "Usage: q3map -convert [-format <ase|map>] [-v] <mapname>\n" );
+ Sys_Printf( "Usage: q3map -convert [-format <ase|obj|map_bp|map>] [-shadersasbitmap|-lightmapsastexcoord|-deluxemapsastexcoord] [-readbsp|-readmap [-meta|-patchmeta]] [-v] <mapname>\n" );
return 0;
}
i++;
if ( !Q_stricmp( argv[ i ], "ase" ) ) {
convertFunc = ConvertBSPToASE;
+ map_allowed = qfalse;
+ }
+ else if ( !Q_stricmp( argv[ i ], "obj" ) ) {
+ convertFunc = ConvertBSPToOBJ;
+ map_allowed = qfalse;
+ }
+ else if ( !Q_stricmp( argv[ i ], "map_bp" ) ) {
+ convertFunc = ConvertBSPToMap_BP;
+ map_allowed = qtrue;
}
else if ( !Q_stricmp( argv[ i ], "map" ) ) {
convertFunc = ConvertBSPToMap;
+ map_allowed = qtrue;
}
else
{
convertGame = GetGame( argv[ i ] );
+ map_allowed = qfalse;
if ( convertGame == NULL ) {
Sys_Printf( "Unknown conversion format \"%s\". Defaulting to ASE.\n", argv[ i ] );
}
}
}
+ else if ( !strcmp( argv[ i ], "-ne" ) ) {
+ normalEpsilon = atof( argv[ i + 1 ] );
+ i++;
+ Sys_Printf( "Normal epsilon set to %f\n", normalEpsilon );
+ }
+ else if ( !strcmp( argv[ i ], "-de" ) ) {
+ distanceEpsilon = atof( argv[ i + 1 ] );
+ i++;
+ Sys_Printf( "Distance epsilon set to %f\n", distanceEpsilon );
+ }
+ else if ( !strcmp( argv[ i ], "-shaderasbitmap" ) || !strcmp( argv[ i ], "-shadersasbitmap" ) ) {
+ shadersAsBitmap = qtrue;
+ }
+ else if ( !strcmp( argv[ i ], "-lightmapastexcoord" ) || !strcmp( argv[ i ], "-lightmapsastexcoord" ) ) {
+ lightmapsAsTexcoord = qtrue;
+ }
+ else if ( !strcmp( argv[ i ], "-deluxemapastexcoord" ) || !strcmp( argv[ i ], "-deluxemapsastexcoord" ) ) {
+ lightmapsAsTexcoord = qtrue;
+ deluxemap = qtrue;
+ }
+ else if ( !strcmp( argv[ i ], "-readbsp" ) ) {
+ force_bsp = qtrue;
+ }
+ else if ( !strcmp( argv[ i ], "-readmap" ) ) {
+ force_map = qtrue;
+ }
+ else if ( !strcmp( argv[ i ], "-meta" ) ) {
+ meta = qtrue;
+ }
+ else if ( !strcmp( argv[ i ], "-patchmeta" ) ) {
+ meta = qtrue;
+ patchMeta = qtrue;
+ }
}
- /* clean up map name */
- strcpy( source, ExpandArg( argv[ i ] ) );
- StripExtension( source );
- DefaultExtension( source, ".bsp" );
-
LoadShaderInfo();
- Sys_Printf( "Loading %s\n", source );
-
- /* ydnar: load surface file */
- //% LoadSurfaceExtraFile( source );
+ /* clean up map name */
+ strcpy( source, ExpandArg( argv[i] ) );
+ ExtractFileExtension( source, ext );
- LoadBSPFile( source );
+ if ( !map_allowed && !force_map ) {
+ force_bsp = qtrue;
+ }
- /* parse bsp entities */
- ParseEntities();
+ if ( force_map || ( !force_bsp && !Q_stricmp( ext, "map" ) && map_allowed ) ) {
+ if ( !map_allowed ) {
+ Sys_Printf( "WARNING: the requested conversion should not be done from .map files. Compile a .bsp first.\n" );
+ }
+ StripExtension( source );
+ DefaultExtension( source, ".map" );
+ Sys_Printf( "Loading %s\n", source );
+ LoadMapFile( source, qfalse, convertGame == NULL );
+ PseudoCompileBSP( convertGame != NULL );
+ }
+ else
+ {
+ StripExtension( source );
+ DefaultExtension( source, ".bsp" );
+ Sys_Printf( "Loading %s\n", source );
+ LoadBSPFile( source );
+ ParseEntities();
+ }
/* bsp format convert? */
if ( convertGame != NULL ) {
/* verbose */
else if ( !strcmp( argv[ i ], "-v" ) ) {
- verbose = qtrue;
- argv[ i ] = NULL;
+ if ( !verbose ) {
+ verbose = qtrue;
+ argv[ i ] = NULL;
+ }
}
/* force */
Sys_Printf( "Q3Map - v1.0r (c) 1999 Id Software Inc.\n" );
Sys_Printf( "Q3Map (ydnar) - v" Q3MAP_VERSION "\n" );
- Sys_Printf( "GtkRadiant - v" RADIANT_VERSION " " __DATE__ " " __TIME__ "\n" );
+ Sys_Printf( "NetRadiant - v" RADIANT_VERSION " " __DATE__ " " __TIME__ "\n" );
Sys_Printf( "%s\n", Q3MAP_MOTD );
/* ydnar: new path initialization */
InitPaths( &argc, argv );
+ /* set game options */
+ if ( !patchSubdivisions ) {
+ patchSubdivisions = game->patchSubdivisions;
+ }
+
/* check if we have enough options left to attempt something */
if ( argc < 2 ) {
Error( "Usage: %s [general options] [options] mapfile", argv[ 0 ] );
r = ConvertBSPMain( argc - 1, argv + 1 );
}
+ /* div0: minimap */
+ else if ( !strcmp( argv[ 1 ], "-minimap" ) ) {
+ r = MiniMapBSPMain( argc - 1, argv + 1 );
+ }
+
/* ydnar: otherwise create a bsp */
else{
r = BSPMain( argc, argv );
char *basePaths[ MAX_BASE_PATHS ];
int numGamePaths;
char *gamePaths[ MAX_GAME_PATHS ];
-
+char *homeBasePath = NULL;
/*
#ifndef Q_UNIX
return NULL;
#else
+ static char buf[ 4096 ];
+ struct passwd pw, *pwp;
char *home;
- uid_t id;
- struct passwd *pwd;
+ static char homeBuf[MAX_OS_PATH];
/* get the home environment variable */
home = getenv( "HOME" );
- if ( home == NULL ) {
- /* do some more digging */
- id = getuid();
- setpwent();
- while ( ( pwd = getpwent() ) != NULL )
- {
- if ( pwd->pw_uid == id ) {
- home = pwd->pw_dir;
- break;
- }
- if ( home ) {
- return Q_strncpyz( buf, home, sizeof( buf ) );
- }
+
+ /* look up home dir in password database */
- if ( getpwuid_r( getuid(), &pw, buf, sizeof( buf ), &pwp ) == 0 ) {
- return pw.pw_dir;
++ if(!home)
++ {
++ if ( getpwuid_r( getuid(), &pw, buf, sizeof( buf ), &pwp ) == 0 ) {
++ return pw.pw_dir;
+ }
- endpwent();
}
- return NULL;
+ snprintf( homeBuf, sizeof( homeBuf ), "%s/.", home );
+
+ /* return it */
+ return homeBuf;
#endif
}
*/
void LokiInitPaths( char *argv0 ){
+ char *home;
+
+ if ( !homePath ) {
+ /* get home dir */
+ home = LokiGetHomeDir();
+ if ( home == NULL ) {
+ home = ".";
+ }
+
+ /* set home path */
+ homePath = home;
+ }
+ else{
+ home = homePath;
+ }
+
#ifndef Q_UNIX
/* this is kinda crap, but hey */
strcpy( installPath, "../" );
#else
char temp[ MAX_OS_PATH ];
- char *home;
+ char last0[ 2 ];
char *path;
char *last;
qboolean found;
- /* get home dir */
- home = LokiGetHomeDir();
- if ( home == NULL ) {
- home = ".";
- }
-
+ path = getenv( "PATH" );
+
/* do some path divining */
- strcpy( temp, argv0 );
- if ( strrchr( argv0, '/' ) ) {
+ Q_strncpyz( temp, argv0, sizeof( temp ) );
+ if ( strrchr( temp, '/' ) ) {
argv0 = strrchr( argv0, '/' ) + 1;
}
- else
- {
- /* get path environment variable */
- path = getenv( "PATH" );
-
- /* minor setup */
- last = last0;
- last[ 0 ] = path[ 0 ];
- last[ 1 ] = '\0';
+ else if ( path ) {
found = qfalse;
+ last = path;
/* go through each : segment of path */
while ( last[ 0 ] != '\0' && found == qfalse )
/* found home dir candidate */
if ( *path == '~' ) {
- strcpy( temp, home );
+ Q_strncpyz( temp, home, sizeof( temp ) );
path++;
}
/* concatenate */
if ( last > ( path + 1 ) ) {
- strncat( temp, path, ( last - path ) );
- strcat( temp, "/" );
+ Q_strncat( temp, sizeof( temp ), path, ( last - path ) );
+ Q_strcat( temp, sizeof( temp ), "/" );
}
- strcat( temp, "./" );
- strcat( temp, argv0 );
+ Q_strcat( temp, sizeof( temp ), "./" );
+ Q_strcat( temp, sizeof( temp ), argv0 );
/* verify the path */
if ( access( temp, X_OK ) == 0 ) {
*( strrchr( installPath, '/' ) ) = '\0';
*( strrchr( installPath, '/' ) + 1 ) = '\0';
}
-
- /* set home path */
- homePath = home;
#endif
}
*/
void AddHomeBasePath( char *path ){
- #ifdef Q_UNIX
int i;
char temp[ MAX_OS_PATH ];
+ int homePathLen;
+ if ( !homePath ) {
+ return;
+ }
/* dummy check */
if ( path == NULL || path[ 0 ] == '\0' ) {
return;
}
+ /* strip leading dot, if homePath does not end in /. */
+ homePathLen = strlen( homePath );
+ if ( !strcmp( path, "." ) ) {
+ /* -fs_homebase . means that -fs_home is to be used as is */
+ strcpy( temp, homePath );
+ }
+ else if ( homePathLen >= 2 && !strcmp( homePath + homePathLen - 2, "/." ) ) {
+ /* remove trailing /. of homePath */
+ homePathLen -= 2;
+
+ /* concatenate home dir and path */
+ sprintf( temp, "%.*s/%s", homePathLen, homePath, path );
+ }
+ else
+ {
+ /* remove leading . of path */
+ if ( path[0] == '.' ) {
+ ++path;
+ }
+
+ /* concatenate home dir and path */
+ sprintf( temp, "%s/%s", homePath, path );
+ }
+
/* make a hole */
- for ( i = 0; i < ( MAX_BASE_PATHS - 1 ); i++ )
+ for ( i = ( MAX_BASE_PATHS - 2 ); i >= 0; i-- )
basePaths[ i + 1 ] = basePaths[ i ];
- /* concatenate home dir and path */
- sprintf( temp, "%s/%s", homePath, path );
-
/* add it to the list */
basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
strcpy( basePaths[ 0 ], temp );
CleanPath( basePaths[ 0 ] );
numBasePaths++;
- #endif
}
argv[ i ] = NULL;
}
+ /* -fs_forbiddenpath */
+ else if ( strcmp( argv[ i ], "-fs_forbiddenpath" ) == 0 ) {
+ if ( ++i >= *argc ) {
+ Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
+ }
+ argv[ i - 1 ] = NULL;
+ if ( g_numForbiddenDirs < VFS_MAXDIRS ) {
+ strncpy( g_strForbiddenDirs[g_numForbiddenDirs], argv[i], PATH_MAX );
+ g_strForbiddenDirs[g_numForbiddenDirs][PATH_MAX] = 0;
+ ++g_numForbiddenDirs;
+ }
+ argv[ i ] = NULL;
+ }
+
/* -fs_basepath */
else if ( strcmp( argv[ i ], "-fs_basepath" ) == 0 ) {
if ( ++i >= *argc ) {
AddGamePath( argv[ i ] );
argv[ i ] = NULL;
}
+
+ /* -fs_home */
+ else if ( strcmp( argv[ i ], "-fs_home" ) == 0 ) {
+ if ( ++i >= *argc ) {
+ Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
+ }
+ argv[ i - 1 ] = NULL;
+ homePath = argv[i];
+ argv[ i ] = NULL;
+ }
+
+ /* -fs_homebase */
+ else if ( strcmp( argv[ i ], "-fs_homebase" ) == 0 ) {
+ if ( ++i >= *argc ) {
+ Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
+ }
+ argv[ i - 1 ] = NULL;
+ homeBasePath = argv[i];
+ argv[ i ] = NULL;
+ }
+
+ /* -fs_homepath - sets both of them */
+ else if ( strcmp( argv[ i ], "-fs_homepath" ) == 0 ) {
+ if ( ++i >= *argc ) {
+ Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
+ }
+ argv[ i - 1 ] = NULL;
+ homePath = argv[i];
+ homeBasePath = ".";
+ argv[ i ] = NULL;
+ }
}
/* remove processed arguments */
}
/* this only affects unix */
- AddHomeBasePath( game->homeBasePath );
+ if ( homeBasePath ) {
+ AddHomeBasePath( homeBasePath );
+ }
+ else{
+ AddHomeBasePath( game->homeBasePath );
+ }
/* initialize vfs paths */
if ( numBasePaths > MAX_BASE_PATHS ) {
/* version */
-#define Q3MAP_VERSION "2.5.17"
-#define Q3MAP_MOTD "Last one turns the lights off"
+#ifndef Q3MAP_VERSION
+#error no Q3MAP_VERSION defined
+#endif
+#define Q3MAP_MOTD "Your map saw the pretty lights from q3map2's BFG"
+
#include "cmdlib.h"
#include "mathlib.h"
#include "md5lib.h"
-#include "md4lib.h"
#include "ddslib.h"
#include "picomodel.h"
#include "inout.h"
#include "vfs.h"
#include "png.h"
-
+#include "md4.h"
#include <stdlib.h>
+ #define MIN(a, b) ((a) < (b) ? (a) : (b))
+ #define MAX(a, b) ((a) > (b) ? (a) : (b))
/* -------------------------------------------------------------------------------
#define Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES 1
#define Q3MAP2_EXPERIMENTAL_SNAP_NORMAL_FIX 1
#define Q3MAP2_EXPERIMENTAL_SNAP_PLANE_FIX 1
-#define Q3MAP2_EXPERIMENTAL_MODEL_CLIPPING_FIX 1
/* general */
#define MAX_QPATH 64
#define DEF_RADIOSITY_BOUNCE 1.0f /* ydnar: default to 100% re-emitted light */
#define MAX_SHADER_INFO 8192
-#define MAX_CUST_SURFACEPARMS 64
+#define MAX_CUST_SURFACEPARMS 256
#define SHADER_MAX_VERTEXES 1000
#define SHADER_MAX_INDEXES ( 6 * SHADER_MAX_VERTEXES )
/* bsp */
#define MAX_PATCH_SIZE 32
#define MAX_BRUSH_SIDES 1024
-#define MAX_BUILD_SIDES 300
+#define MAX_BUILD_SIDES 1024
#define MAX_EXPANDED_AXIS 128
#define HINT_PRIORITY 1000 /* ydnar: force hint splits first and antiportal/areaportal splits last */
#define ANTIPORTAL_PRIORITY -1000
#define AREAPORTAL_PRIORITY -1000
+#define DETAIL_PRIORITY -3000
#define PSIDE_FRONT 1
#define PSIDE_BACK 2
#define PORTALFILE "PRT1"
-#define MAX_PORTALS 32768
+#define MAX_PORTALS 0x20000 /* same as MAX_MAP_PORTALS */
#define MAX_SEPERATORS MAX_POINTS_ON_WINDING
#define MAX_POINTS_ON_FIXED_WINDING 24 /* ydnar: increased this from 12 at the expense of more memory */
-#define MAX_PORTALS_ON_LEAF 128
+#define MAX_PORTALS_ON_LEAF 1024
/* light */
#define LIGHT_FAST_TEMP 512
#define LIGHT_FAST_ACTUAL ( LIGHT_FAST | LIGHT_FAST_TEMP )
#define LIGHT_NEGATIVE 1024
+#define LIGHT_UNNORMALIZED 2048 /* vortex: do not normalize _color */
#define LIGHT_SUN_DEFAULT ( LIGHT_ATTEN_ANGLE | LIGHT_GRID | LIGHT_SURFACES )
#define LIGHT_AREA_DEFAULT ( LIGHT_ATTEN_ANGLE | LIGHT_ATTEN_DISTANCE | LIGHT_GRID | LIGHT_SURFACES ) /* q3a and wolf are the same */
#define GRID_EPSILON 0.0f
#define DEFAULT_LIGHTMAP_SAMPLE_SIZE 16
+#define DEFAULT_LIGHTMAP_MIN_SAMPLE_SIZE 0
#define DEFAULT_LIGHTMAP_SAMPLE_OFFSET 1.0f
#define DEFAULT_SUBDIVIDE_THRESHOLD 1.0f
#define BSP_LUXEL_SIZE 3
#define RAD_LUXEL_SIZE 3
#define SUPER_LUXEL_SIZE 4
+#define SUPER_FLAG_SIZE 4
+#define FLAG_FORCE_SUBSAMPLING 1
+#define FLAG_ALREADY_SUBSAMPLED 2
#define SUPER_ORIGIN_SIZE 3
#define SUPER_NORMAL_SIZE 4
#define SUPER_DELUXEL_SIZE 3
#define BSP_DELUXEL_SIZE 3
+#define SUPER_FLOODLIGHT_SIZE 4
#define VERTEX_LUXEL( s, v ) ( vertexLuxels[ s ] + ( ( v ) * VERTEX_LUXEL_SIZE ) )
#define RAD_VERTEX_LUXEL( s, v )( radVertexLuxels[ s ] + ( ( v ) * VERTEX_LUXEL_SIZE ) )
#define BSP_LUXEL( s, x, y ) ( lm->bspLuxels[ s ] + ( ( ( ( y ) * lm->w ) + ( x ) ) * BSP_LUXEL_SIZE ) )
#define RAD_LUXEL( s, x, y ) ( lm->radLuxels[ s ] + ( ( ( ( y ) * lm->w ) + ( x ) ) * RAD_LUXEL_SIZE ) )
#define SUPER_LUXEL( s, x, y ) ( lm->superLuxels[ s ] + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_LUXEL_SIZE ) )
+#define SUPER_FLAG( x, y ) ( lm->superFlags + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_FLAG_SIZE ) )
#define SUPER_DELUXEL( x, y ) ( lm->superDeluxels + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_DELUXEL_SIZE ) )
#define BSP_DELUXEL( x, y ) ( lm->bspDeluxels + ( ( ( ( y ) * lm->w ) + ( x ) ) * BSP_DELUXEL_SIZE ) )
#define SUPER_CLUSTER( x, y ) ( lm->superClusters + ( ( ( y ) * lm->sw ) + ( x ) ) )
#define SUPER_ORIGIN( x, y ) ( lm->superOrigins + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_ORIGIN_SIZE ) )
#define SUPER_NORMAL( x, y ) ( lm->superNormals + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_NORMAL_SIZE ) )
#define SUPER_DIRT( x, y ) ( lm->superNormals + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_NORMAL_SIZE ) + 3 ) /* stash dirtyness in normal[ 3 ] */
+#define SUPER_FLOODLIGHT( x, y ) ( lm->superFloodLight + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_FLOODLIGHT_SIZE ) )
#define MAX_LIGHTMAP_SHADERS 256
/* ok to increase these at the expense of more memory */
-#define MAX_MAP_MODELS 0x400
-#define MAX_MAP_BRUSHES 0x10000
-#define MAX_MAP_ENTITIES 0x1000 //% 0x800 /* ydnar */
-#define MAX_MAP_ENTSTRING 0x80000 //% 0x40000 /* ydnar */
-#define MAX_MAP_SHADERS 0x800 //% 0x400 /* ydnar */
-
#define MAX_MAP_AREAS 0x100 /* MAX_MAP_AREA_BYTES in q_shared must match! */
#define MAX_MAP_FOGS 30 //& 0x100 /* RBSP (32 - world fog - goggles) */
-#define MAX_MAP_PLANES 0x100000 //% 0x20000 /* ydnar for md */
-#define MAX_MAP_NODES 0x20000
-#define MAX_MAP_BRUSHSIDES 0x100000 //% 0x20000 /* ydnar */
#define MAX_MAP_LEAFS 0x20000
-#define MAX_MAP_LEAFFACES 0x100000 //% 0x20000 /* ydnar */
-#define MAX_MAP_LEAFBRUSHES 0x40000
#define MAX_MAP_PORTALS 0x20000
#define MAX_MAP_LIGHTING 0x800000
#define MAX_MAP_LIGHTGRID 0x100000 //% 0x800000 /* ydnar: set to points, not bytes */
-#define MAX_MAP_VISIBILITY 0x200000
+#define MAX_MAP_VISCLUSTERS 0x4000 // <= MAX_MAP_LEAFS
+#define MAX_MAP_VISIBILITY ( VIS_HEADER_SIZE + MAX_MAP_VISCLUSTERS * ( ( ( MAX_MAP_VISCLUSTERS + 63 ) & ~63 ) >> 3 ) )
#define MAX_MAP_DRAW_SURFS 0x20000
-#define MAX_MAP_DRAW_VERTS 0x100000
-#define MAX_MAP_DRAW_INDEXES 0x80000
#define MAX_MAP_ADVERTISEMENTS 30
------------------------------------------------------------------------------- */
/* ydnar: for smaller structs */
-typedef char qb_t;
+typedef unsigned char qb_t;
/* ydnar: for q3map_tcMod */
}
surfaceParm_t;
+typedef enum
+{
+ MINIMAP_MODE_GRAY,
+ MINIMAP_MODE_BLACK,
+ MINIMAP_MODE_WHITE
+}
+miniMapMode_t;
typedef struct game_s
{
qboolean wolfLight; /* when true, lights work like wolf q3map */
int lightmapSize; /* bsp lightmap width/height */
float lightmapGamma; /* default lightmap gamma */
+ qboolean lightmapsRGB; /* default lightmap sRGB mode */
+ qboolean texturesRGB; /* default texture sRGB mode */
+ qboolean colorsRGB; /* default color sRGB mode */
+ float lightmapExposure; /* default lightmap exposure */
float lightmapCompensate; /* default lightmap compensate value */
+ float gridScale; /* vortex: default lightgrid scale (affects both directional and ambient spectres) */
+ float gridAmbientScale; /* vortex: default lightgrid ambient spectre scale */
+ qboolean lightAngleHL; /* jal: use half-lambert curve for light angle attenuation */
+ qboolean noStyles; /* use lightstyles hack or not */
+ qboolean keepLights; /* keep light entities on bsp */
+ int patchSubdivisions; /* default patch subdivisions tolerance */
+ qboolean patchShadows; /* patch casting enabled */
+ qboolean deluxeMap; /* compile deluxemaps */
+ int deluxeMode; /* deluxemap mode (0 - modelspace, 1 - tangentspace with renormalization, 2 - tangentspace without renormalization) */
+ int miniMapSize; /* minimap size */
+ float miniMapSharpen; /* minimap sharpening coefficient */
+ float miniMapBorder; /* minimap border amount */
+ qboolean miniMapKeepAspect; /* minimap keep aspect ratio by letterboxing */
+ miniMapMode_t miniMapMode; /* minimap mode */
+ char *miniMapNameFormat; /* minimap name format */
char *bspIdent; /* 4-letter bsp file prefix */
int bspVersion; /* bsp version to use */
qboolean lumpSwap; /* cod-style len/ofs order */
}
remap_t;
+typedef struct skinfile_s
+{
+ struct skinfile_s *next;
+ char name[ 1024 ];
+ char to[ MAX_QPATH ];
+}
+skinfile_t;
+
/* wingdi.h hack, it's the same: 0 */
#undef CM_NONE
CM_ALPHA_SCALE,
CM_COLOR_DOT_PRODUCT,
CM_ALPHA_DOT_PRODUCT,
+ CM_COLOR_DOT_PRODUCT_SCALE,
+ CM_ALPHA_DOT_PRODUCT_SCALE,
CM_COLOR_DOT_PRODUCT_2,
- CM_ALPHA_DOT_PRODUCT_2
+ CM_ALPHA_DOT_PRODUCT_2,
+ CM_COLOR_DOT_PRODUCT_2_SCALE,
+ CM_ALPHA_DOT_PRODUCT_2_SCALE
}
colorModType_t;
char *backShader; /* for surfaces that generate different front and back passes */
char *cloneShader; /* ydnar: for cloning of a surface */
char *remapShader; /* ydnar: remap a shader in final stage */
+ char *deprecateShader; /* vortex: shader is deprecated and replaced by this on use */
surfaceModel_t *surfaceModel; /* ydnar: for distribution of models */
foliage_t *foliage; /* ydnar/splash damage: wolf et foliage */
qb_t noFog; /* ydnar: supress fogging */
qb_t clipModel; /* ydnar: solid model hack */
qb_t noVertexLight; /* ydnar: leave vertex color alone */
+ qb_t noDirty; /* jal: do not apply the dirty pass to this surface */
byte styleMarker; /* ydnar: light styles hack */
vec3_t averageColor;
byte lightStyle;
+ /* vortex: per-surface floodlight */
+ float floodlightDirectionScale;
+ vec3_t floodlightRGB;
+ float floodlightIntensity;
+ float floodlightDistance;
+
qb_t lmMergable; /* ydnar */
int lmCustomWidth, lmCustomHeight; /* ydnar */
float lmBrightness; /* ydnar */
struct face_s *next;
int planenum;
int priority;
- qboolean checked;
+ //qboolean checked;
int compileFlags;
winding_t *w;
}
vec3_t normal;
vec_t dist;
int type;
- struct plane_s *hash_chain;
+ int counter;
+ int hash_chain;
}
plane_t;
shaderInfo_t *celShader; /* :) */
/* ydnar: gs mods */
+ int lightmapSampleSize; /* jal : entity based _lightmapsamplesize */
float lightmapScale;
+ float shadeAngleDegrees; /* jal : entity based _shadeangle */
vec3_t eMins, eMaxs;
indexMap_t *im;
shaderInfo_t *celShader; /* :) */
/* ydnar: gs mods */
+ int lightmapSampleSize; /* jal : entity based _lightmapsamplesize */
float lightmapScale;
vec3_t eMins, eMaxs;
indexMap_t *im;
/* ydnar: per-surface (per-entity, actually) lightmap sample size scaling */
float lightmapScale;
+ /* jal: per-surface (per-entity, actually) shadeangle */
+ float shadeAngleDegrees;
+
/* ydnar: surface classification */
vec3_t mins, maxs;
vec3_t lightmapAxis;
shaderInfo_t *si;
side_t *side;
int entityNum, surfaceNum, planeNum, fogNum, sampleSize, castShadows, recvShadows;
+ float shadeAngleDegrees;
vec4_t plane;
vec3_t lightmapAxis;
int indexes[ 3 ];
int mapEntityNum, firstDrawSurf;
int firstBrush, numBrushes; /* only valid during BSP compile */
epair_t *epairs;
+ vec3_t originbrush_origin;
}
entity_t;
entity_t *occupant; /* for leak file testing */
struct portal_s *portals; /* also on nodes during construction */
+
+ qboolean has_structural_children;
}
node_t;
float radiusByDist; /* for spotlights */
float fade; /* ydnar: from wolf, for linear lights */
float angleScale; /* ydnar: stolen from vlight for K */
+ float extraDist; /* "extra dimension" distance of the light, to kill hot spots */
float add; /* ydnar: used for area lights */
float envelope; /* ydnar: units until falloff < tolerance */
/* input and output */
vec3_t color; /* starts out at full color, may be reduced if transparent surfaces are crossed */
+ vec3_t colorNoShadow; /* result color with no shadow casting */
+ vec3_t directionContribution; /* result contribution to the deluxe map */
/* output */
vec3_t hit;
int compileFlags; /* for determining surface compile flags traced through */
qboolean passSolid;
qboolean opaque;
+ vec_t forceSubsampling; /* needs subsampling (alphashadow), value = max color contribution possible from it */
/* working data */
int numTestNodes;
int numLightClusters, *lightClusters;
int sampleSize, actualSampleSize, axisNum;
+
+ /* vortex: per-surface floodlight */
+ float floodlightDirectionScale;
+ vec3_t floodlightRGB;
+ float floodlightIntensity;
+ float floodlightDistance;
+
int entityNum;
int recvShadows;
vec3_t mins, maxs, axis, origin, *vecs;
float *bspLuxels[ MAX_LIGHTMAPS ];
float *radLuxels[ MAX_LIGHTMAPS ];
float *superLuxels[ MAX_LIGHTMAPS ];
+ unsigned char *superFlags;
float *superOrigins;
float *superNormals;
int *superClusters;
float *superDeluxels; /* average light direction */
float *bspDeluxels;
+ float *superFloodLight;
}
rawLightmap_t;
typedef struct surfaceInfo_s
{
- bspModel_t *model;
+ int modelindex;
shaderInfo_t *si;
rawLightmap_t *lm;
int parentSurfaceNum, childSurfaceNum;
}
surfaceInfo_t;
-
-
/* -------------------------------------------------------------------------------
prototypes
/* main.c */
vec_t Random( void );
+ char *Q_strncpyz( char *dst, const char *src, size_t len );
+ char *Q_strcat( char *dst, size_t dlen, const char *src );
+ char *Q_strncat( char *dst, size_t dlen, const char *src, size_t slen );
int BSPInfo( int count, char **fileNames );
int ScaleBSPMain( int argc, char **argv );
int ConvertMain( int argc, char **argv );
/* convert_map.c */
int ConvertBSPToMap( char *bspName );
+int ConvertBSPToMap_BP( char *bspName );
/* convert_ase.c */
int ConvertBSPToASE( char *bspName );
+/* convert_obj.c */
+int ConvertBSPToOBJ( char *bspName );
+
/* brush.c */
sideRef_t *AllocSideRef( side_t *side, sideRef_t *next );
/* map.c */
-void LoadMapFile( char *filename, qboolean onlyLights );
+void LoadMapFile( char *filename, qboolean onlyLights, qboolean noCollapseGroups );
int FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points );
int PlaneTypeForNormal( vec3_t normal );
void AddBrushBevels( void );
-brush_t *FinishBrush( void );
+brush_t *FinishBrush( qboolean noCollapseGroups );
/* portals.c */
qboolean PortalPassable( portal_t *p );
-qboolean FloodEntities( tree_t *tree );
+#define FLOODENTITIES_LEAKED 1
+#define FLOODENTITIES_GOOD 0
+#define FLOODENTITIES_EMPTY -1
+int FloodEntities( tree_t *tree );
void FillOutside( node_t *headnode );
void FloodAreas( tree_t *tree );
face_t *VisibleFaces( entity_t *e, tree_t *tree );
int EmitShader( const char *shader, int *contentFlags, int *surfaceFlags );
void BeginBSPFile( void );
-void EndBSPFile( void );
+void EndBSPFile( qboolean do_write );
void EmitBrushes( brush_t *brushes, int *firstBrush, int *numBrushes );
void EmitFogs( void );
void ParsePatch( qboolean onlyLights );
mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength );
void PatchMapDrawSurfs( entity_t *e );
+void TriangulatePatchSurface( entity_t *e, mapDrawSurface_t *ds );
/* tjunction.c */
/* model.c */
void PicoPrintFunc( int level, const char *str );
-void PicoLoadFileFunc( char *name, byte **buffer, int *bufSize );
-picoModel_t *FindModel( char *name, int frame );
-picoModel_t *LoadModel( char *name, int frame );
-void InsertModel( char *name, int frame, m4x4_t transform, remap_t *remap, shaderInfo_t *celShader, int eNum, int castShadows, int recvShadows, int spawnFlags, float lightmapScale );
+void PicoLoadFileFunc( const char *name, byte **buffer, int *bufSize );
+picoModel_t *FindModel( const char *name, int frame );
+picoModel_t *LoadModel( const char *name, int frame );
+void InsertModel( const char *name, int skin, int frame, m4x4_t transform, remap_t *remap, shaderInfo_t *celShader, int eNum, int castShadows, int recvShadows, int spawnFlags, float lightmapScale, int lightmapSampleSize, float shadeAngle );
void AddTriangleModels( entity_t *e );
mapDrawSurface_t *AllocDrawSurface( surfaceType_t type );
void FinishSurface( mapDrawSurface_t *ds );
void StripFaceSurface( mapDrawSurface_t *ds );
+void MaxAreaFaceSurface( mapDrawSurface_t *ds );
qboolean CalcSurfaceTextureRange( mapDrawSurface_t *ds );
qboolean CalcLightmapAxis( vec3_t normal, vec3_t axis );
void ClassifySurfaces( int numSurfs, mapDrawSurface_t *ds );
void AddEntitySurfaceModels( entity_t *e );
mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, winding_t *w );
mapDrawSurface_t *DrawSurfaceForMesh( entity_t *e, parseMesh_t *p, mesh_t *mesh );
-mapDrawSurface_t *DrawSurfaceForFlare( int entNum, vec3_t origin, vec3_t normal, vec3_t color, char *flareShader, int lightStyle );
+mapDrawSurface_t *DrawSurfaceForFlare( int entNum, vec3_t origin, vec3_t normal, vec3_t color, const char *flareShader, int lightStyle );
mapDrawSurface_t *DrawSurfaceForShader( char *shader );
void ClipSidesIntoTree( entity_t *e, tree_t *tree );
void MakeDebugPortalSurfs( tree_t *tree );
void AddEntitySurfaceModels( entity_t *e );
int AddSurfaceModels( mapDrawSurface_t *ds );
void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree );
+void EmitPatchSurface( entity_t *e, mapDrawSurface_t *ds );
+void EmitTriangleSurface( mapDrawSurface_t *ds );
/* surface_fur.c */
void FixMetaTJunctions( void );
void SmoothMetaTriangles( void );
void MergeMetaTriangles( void );
+void EmitMetaStats(); // vortex: print meta statistics even in no-verbose mode
/* surface_extra.c */
int GetSurfaceExtraCastShadows( int num );
int GetSurfaceExtraRecvShadows( int num );
int GetSurfaceExtraSampleSize( int num );
+int GetSurfaceExtraMinSampleSize( int num );
float GetSurfaceExtraLongestCurve( int num );
void GetSurfaceExtraLightmapAxis( int num, vec3_t lightmapAxis );
void ProcessDecals( void );
void MakeEntityDecals( entity_t *e );
+/* map.c */
+void TextureAxisFromPlane( plane_t *pln, vec3_t xv, vec3_t yv );
/* brush_primit.c */
void ComputeAxisBase( vec3_t normal, vec3_t texX, vec3_t texY );
float DirtForSample( trace_t *trace );
void DirtyRawLightmap( int num );
+void SetupFloodLight();
+void FloodlightRawLightmaps();
+void FloodlightIlluminateLightmap( rawLightmap_t *lm );
+float FloodLightForSample( trace_t *trace, float floodLightDistance, qboolean floodLightLowQuality );
+void FloodLightRawLightmap( int num );
+
void IlluminateRawLightmap( int num );
void IlluminateVertexes( int num );
+void SetupBrushesFlags( int mask_any, int test_any, int mask_all, int test_all );
void SetupBrushes( void );
void SetupClusters( void );
qboolean ClusterVisible( int a, int b );
void LoadShaderInfo( void );
shaderInfo_t *ShaderInfoForShader( const char *shader );
+shaderInfo_t *ShaderInfoForShaderNull( const char *shader );
/* bspfile_abstract.c */
int GetLumpElements( bspHeader_t *header, int lump, int size );
void *GetLump( bspHeader_t *header, int lump );
int CopyLump( bspHeader_t *header, int lump, void *dest, int size );
+int CopyLump_Allocate( bspHeader_t *header, int lump, void **dest, int size, int *allocationVariable );
void AddLump( FILE *file, bspHeader_t *header, int lumpNum, const void *data, int length );
void LoadBSPFile( const char *filename );
void UnparseEntities( void );
void PrintEntity( const entity_t *ent );
void SetKeyValue( entity_t *ent, const char *key, const char *value );
+qboolean KeyExists( const entity_t *ent, const char *key ); /* VorteX: check if key exists */
const char *ValueForKey( const entity_t *ent, const char *key );
int IntForKey( const entity_t *ent, const char *key );
vec_t FloatForKey( const entity_t *ent, const char *key );
void GetVectorForKey( const entity_t *ent, const char *key, vec3_t vec );
entity_t *FindTargetEntity( const char *target );
void GetEntityShadowFlags( const entity_t *ent, const entity_t *ent2, int *castShadows, int *recvShadows );
+void InjectCommandLine( char **argv, int beginArgs, int endArgs );
+
/* bspfile_ibsp.c */
#include "game_quakelive.h" /* most be after game_quake3.h as they share defines! */
,
#include "game_nexuiz.h" /* most be after game_quake3.h as they share defines! */
+ ,
+ #include "game_xonotic.h" /* most be after game_quake3.h as they share defines! */
,
#include "game_tremulous.h" /*LinuxManMikeC: must be after game_quake3.h, depends on #define's set in it */
,
,
#include "game_reaction.h" /* must be after game_quake3.h */
,
- { NULL } /* null game */
+ #include "game_darkplaces.h" /* vortex: darkplaces q1 engine */
+ ,
+ #include "game_dq.h" /* vortex: deluxe quake game ( darkplaces q1 engine) */
+ ,
+ #include "game_prophecy.h" /* vortex: prophecy game ( darkplaces q1 engine) */
+ ,
+ #include "game__null.h" /* null game (must be last item) */
};
#endif
Q_EXTERN game_t *game Q_ASSIGN( &games[ 0 ] );
Q_EXTERN qboolean noHint Q_ASSIGN( qfalse ); /* ydnar */
Q_EXTERN qboolean renameModelShaders Q_ASSIGN( qfalse ); /* ydnar */
Q_EXTERN qboolean skyFixHack Q_ASSIGN( qfalse ); /* ydnar */
+Q_EXTERN qboolean bspAlternateSplitWeights Q_ASSIGN( qfalse ); /* 27 */
+Q_EXTERN qboolean deepBSP Q_ASSIGN( qfalse ); /* div0 */
+Q_EXTERN qboolean maxAreaFaceSurface Q_ASSIGN( qfalse ); /* divVerent */
Q_EXTERN int patchSubdivisions Q_ASSIGN( 8 ); /* ydnar: -patchmeta subdivisions */
Q_EXTERN qboolean debugSurfaces Q_ASSIGN( qfalse );
Q_EXTERN qboolean debugInset Q_ASSIGN( qfalse );
Q_EXTERN qboolean debugPortals Q_ASSIGN( qfalse );
+Q_EXTERN qboolean lightmapTriangleCheck Q_ASSIGN( qfalse );
+Q_EXTERN qboolean lightmapExtraVisClusterNudge Q_ASSIGN( qfalse );
+Q_EXTERN qboolean lightmapFill Q_ASSIGN( qfalse );
+Q_EXTERN int metaAdequateScore Q_ASSIGN( -1 );
+Q_EXTERN int metaGoodScore Q_ASSIGN( -1 );
+Q_EXTERN float metaMaxBBoxDistance Q_ASSIGN( -1 );
#if Q3MAP2_EXPERIMENTAL_SNAP_NORMAL_FIX
// Increasing the normalEpsilon to compensate for new logic in SnapNormal(), where
Q_EXTERN char outbase[ 32 ];
Q_EXTERN int sampleSize; /* lightmap sample size in units */
+Q_EXTERN int minSampleSize; /* minimum sample size to use at all */
+Q_EXTERN int sampleScale; /* vortex: lightmap sample scale (ie quality)*/
Q_EXTERN int mapEntityNum Q_ASSIGN( 0 );
Q_EXTERN int entitySourceBrushes;
-Q_EXTERN plane_t mapplanes[ MAX_MAP_PLANES ]; /* mapplanes[ num ^ 1 ] will always be the mirror or mapplanes[ num ] */
-Q_EXTERN int nummapplanes; /* nummapplanes will always be even */
+Q_EXTERN plane_t *mapplanes Q_ASSIGN( NULL ); /* mapplanes[ num ^ 1 ] will always be the mirror or mapplanes[ num ] */
+Q_EXTERN int nummapplanes Q_ASSIGN( 0 ); /* nummapplanes will always be even */
+Q_EXTERN int allocatedmapplanes Q_ASSIGN( 0 );
Q_EXTERN int numMapPatches;
Q_EXTERN vec3_t mapMins, mapMaxs;
Q_EXTERN int numSurfacesByType[ NUM_SURFACE_TYPES ];
Q_EXTERN int numClearedSurfaces;
Q_EXTERN int numStripSurfaces;
+Q_EXTERN int numMaxAreaSurfaces;
Q_EXTERN int numFanSurfaces;
Q_EXTERN int numMergedSurfaces;
Q_EXTERN int numMergedVerts;
Q_EXTERN qboolean noPassageVis;
Q_EXTERN qboolean passageVisOnly;
Q_EXTERN qboolean mergevis;
+Q_EXTERN qboolean mergevisportals;
Q_EXTERN qboolean nosort;
Q_EXTERN qboolean saveprt;
Q_EXTERN qboolean hint; /* ydnar */
Q_EXTERN char inbase[ MAX_QPATH ];
-
-/* other bits */
-Q_EXTERN int totalvis;
+Q_EXTERN char globalCelShader[ MAX_QPATH ];
Q_EXTERN float farPlaneDist; /* rr2do2, rf, mre, ydnar all contributed to this one... */
/* commandline arguments */
Q_EXTERN qboolean wolfLight Q_ASSIGN( qfalse );
+Q_EXTERN float extraDist Q_ASSIGN( 0.0f );
Q_EXTERN qboolean loMem Q_ASSIGN( qfalse );
Q_EXTERN qboolean noStyles Q_ASSIGN( qfalse );
+Q_EXTERN qboolean keepLights Q_ASSIGN( qfalse );
Q_EXTERN int sampleSize Q_ASSIGN( DEFAULT_LIGHTMAP_SAMPLE_SIZE );
+Q_EXTERN int minSampleSize Q_ASSIGN( DEFAULT_LIGHTMAP_MIN_SAMPLE_SIZE );
Q_EXTERN qboolean noVertexLighting Q_ASSIGN( qfalse );
Q_EXTERN qboolean noGridLighting Q_ASSIGN( qfalse );
Q_EXTERN qboolean deluxemap Q_ASSIGN( qfalse );
Q_EXTERN qboolean debugDeluxemap Q_ASSIGN( qfalse );
+Q_EXTERN int deluxemode Q_ASSIGN( 0 ); /* deluxemap format (0 - modelspace, 1 - tangentspace with renormalization, 2 - tangentspace without renormalization) */
Q_EXTERN qboolean fast Q_ASSIGN( qfalse );
+Q_EXTERN qboolean fastpoint Q_ASSIGN( qtrue );
Q_EXTERN qboolean faster Q_ASSIGN( qfalse );
Q_EXTERN qboolean fastgrid Q_ASSIGN( qfalse );
Q_EXTERN qboolean fastbounce Q_ASSIGN( qfalse );
Q_EXTERN float shadeAngleDegrees Q_ASSIGN( 0.0f );
Q_EXTERN int superSample Q_ASSIGN( 0 );
Q_EXTERN int lightSamples Q_ASSIGN( 1 );
+Q_EXTERN qboolean lightRandomSamples Q_ASSIGN( qfalse );
+Q_EXTERN int lightSamplesSearchBoxSize Q_ASSIGN( 1 );
Q_EXTERN qboolean filter Q_ASSIGN( qfalse );
Q_EXTERN qboolean dark Q_ASSIGN( qfalse );
Q_EXTERN qboolean sunOnly Q_ASSIGN( qfalse );
Q_EXTERN int approximateTolerance Q_ASSIGN( 0 );
Q_EXTERN qboolean noCollapse Q_ASSIGN( qfalse );
+Q_EXTERN int lightmapSearchBlockSize Q_ASSIGN( 0 );
Q_EXTERN qboolean exportLightmaps Q_ASSIGN( qfalse );
Q_EXTERN qboolean externalLightmaps Q_ASSIGN( qfalse );
Q_EXTERN int lmCustomSize Q_ASSIGN( LIGHTMAP_WIDTH );
+Q_EXTERN char * lmCustomDir Q_ASSIGN( NULL );
+Q_EXTERN int lmLimitSize Q_ASSIGN( 0 );
Q_EXTERN qboolean dirty Q_ASSIGN( qfalse );
Q_EXTERN qboolean dirtDebug Q_ASSIGN( qfalse );
Q_EXTERN float dirtScale Q_ASSIGN( 1.0f );
Q_EXTERN float dirtGain Q_ASSIGN( 1.0f );
+/* 27: floodlighting */
+Q_EXTERN qboolean debugnormals Q_ASSIGN( qfalse );
+Q_EXTERN qboolean floodlighty Q_ASSIGN( qfalse );
+Q_EXTERN qboolean floodlight_lowquality Q_ASSIGN( qfalse );
+Q_EXTERN vec3_t floodlightRGB;
+Q_EXTERN float floodlightIntensity Q_ASSIGN( 512.0f );
+Q_EXTERN float floodlightDistance Q_ASSIGN( 1024.0f );
+Q_EXTERN float floodlightDirectionScale Q_ASSIGN( 1.0f );
+
Q_EXTERN qboolean dump Q_ASSIGN( qfalse );
Q_EXTERN qboolean debug Q_ASSIGN( qfalse );
Q_EXTERN qboolean debugUnused Q_ASSIGN( qfalse );
/* for run time tweaking of light sources */
Q_EXTERN float pointScale Q_ASSIGN( 7500.0f );
+Q_EXTERN float spotScale Q_ASSIGN( 7500.0f );
Q_EXTERN float areaScale Q_ASSIGN( 0.25f );
Q_EXTERN float skyScale Q_ASSIGN( 1.0f );
Q_EXTERN float bounceScale Q_ASSIGN( 0.25f );
+/* jal: alternative angle attenuation curve */
+Q_EXTERN qboolean lightAngleHL Q_ASSIGN( qfalse );
+
+/* vortex: gridscale and gridambientscale */
+Q_EXTERN float gridScale Q_ASSIGN( 1.0f );
+Q_EXTERN float gridAmbientScale Q_ASSIGN( 1.0f );
+Q_EXTERN float gridDirectionality Q_ASSIGN( 1.0f );
+Q_EXTERN float gridAmbientDirectionality Q_ASSIGN( 0.0f );
+Q_EXTERN qboolean inGrid Q_ASSIGN( 0 );
+
/* ydnar: lightmap gamma/compensation */
Q_EXTERN float lightmapGamma Q_ASSIGN( 1.0f );
+Q_EXTERN float lightmapsRGB Q_ASSIGN( qfalse );
+Q_EXTERN float texturesRGB Q_ASSIGN( qfalse );
+Q_EXTERN float colorsRGB Q_ASSIGN( qfalse );
+Q_EXTERN float lightmapExposure Q_ASSIGN( 0.0f );
Q_EXTERN float lightmapCompensate Q_ASSIGN( 1.0f );
/* ydnar: for runtime tweaking of falloff tolerance */
Q_EXTERN float formFactorValueScale Q_ASSIGN( 3.0f );
Q_EXTERN float linearScale Q_ASSIGN( 1.0f / 8000.0f );
+// for .ase conversion
+Q_EXTERN qboolean shadersAsBitmap Q_ASSIGN( qfalse );
+Q_EXTERN qboolean lightmapsAsTexcoord Q_ASSIGN( qfalse );
+
Q_EXTERN light_t *lights;
Q_EXTERN int numPointLights;
Q_EXTERN int numSpotLights;
Q_EXTERN int numExtLightmaps Q_ASSIGN( 0 );
Q_EXTERN outLightmap_t *outLightmaps Q_ASSIGN( NULL );
+/* vortex: per surface floodlight statictics */
+Q_EXTERN int numSurfacesFloodlighten Q_ASSIGN( 0 );
+
/* grid points */
Q_EXTERN int numRawGridPoints Q_ASSIGN( 0 );
Q_EXTERN rawGridPoint_t *rawGridPoints Q_ASSIGN( NULL );
Q_EXTERN int numEntities Q_ASSIGN( 0 );
Q_EXTERN int numBSPEntities Q_ASSIGN( 0 );
-Q_EXTERN entity_t entities[ MAX_MAP_ENTITIES ];
+Q_EXTERN int allocatedEntities Q_ASSIGN( 0 );
+Q_EXTERN entity_t* entities Q_ASSIGN( NULL );
Q_EXTERN int numBSPModels Q_ASSIGN( 0 );
-Q_EXTERN bspModel_t bspModels[ MAX_MAP_MODELS ];
+Q_EXTERN int allocatedBSPModels Q_ASSIGN( 0 );
+Q_EXTERN bspModel_t* bspModels Q_ASSIGN( NULL );
Q_EXTERN int numBSPShaders Q_ASSIGN( 0 );
-Q_EXTERN bspShader_t bspShaders[ MAX_MAP_MODELS ];
+Q_EXTERN int allocatedBSPShaders Q_ASSIGN( 0 );
+Q_EXTERN bspShader_t* bspShaders Q_ASSIGN( 0 );
Q_EXTERN int bspEntDataSize Q_ASSIGN( 0 );
-Q_EXTERN char bspEntData[ MAX_MAP_ENTSTRING ];
+Q_EXTERN int allocatedBSPEntData Q_ASSIGN( 0 );
+Q_EXTERN char *bspEntData Q_ASSIGN( 0 );
Q_EXTERN int numBSPLeafs Q_ASSIGN( 0 );
Q_EXTERN bspLeaf_t bspLeafs[ MAX_MAP_LEAFS ];
Q_EXTERN int numBSPPlanes Q_ASSIGN( 0 );
-Q_EXTERN bspPlane_t bspPlanes[ MAX_MAP_PLANES ];
+Q_EXTERN int allocatedBSPPlanes Q_ASSIGN( 0 );
+Q_EXTERN bspPlane_t *bspPlanes;
Q_EXTERN int numBSPNodes Q_ASSIGN( 0 );
-Q_EXTERN bspNode_t bspNodes[ MAX_MAP_NODES ];
+Q_EXTERN int allocatedBSPNodes Q_ASSIGN( 0 );
+Q_EXTERN bspNode_t* bspNodes Q_ASSIGN( NULL );
Q_EXTERN int numBSPLeafSurfaces Q_ASSIGN( 0 );
-Q_EXTERN int bspLeafSurfaces[ MAX_MAP_LEAFFACES ];
+Q_EXTERN int allocatedBSPLeafSurfaces Q_ASSIGN( 0 );
+Q_EXTERN int* bspLeafSurfaces Q_ASSIGN( NULL );
Q_EXTERN int numBSPLeafBrushes Q_ASSIGN( 0 );
-Q_EXTERN int bspLeafBrushes[ MAX_MAP_LEAFBRUSHES ];
+Q_EXTERN int allocatedBSPLeafBrushes Q_ASSIGN( 0 );
+Q_EXTERN int* bspLeafBrushes Q_ASSIGN( NULL );
Q_EXTERN int numBSPBrushes Q_ASSIGN( 0 );
-Q_EXTERN bspBrush_t bspBrushes[ MAX_MAP_BRUSHES ];
+Q_EXTERN int allocatedBSPBrushes Q_ASSIGN( 0 );
+Q_EXTERN bspBrush_t* bspBrushes Q_ASSIGN( NULL );
Q_EXTERN int numBSPBrushSides Q_ASSIGN( 0 );
-Q_EXTERN bspBrushSide_t bspBrushSides[ MAX_MAP_BRUSHSIDES ];
+Q_EXTERN int allocatedBSPBrushSides Q_ASSIGN( 0 );
+Q_EXTERN bspBrushSide_t* bspBrushSides Q_ASSIGN( NULL );
Q_EXTERN int numBSPLightBytes Q_ASSIGN( 0 );
Q_EXTERN byte *bspLightBytes Q_ASSIGN( NULL );
Q_EXTERN byte bspVisBytes[ MAX_MAP_VISIBILITY ];
Q_EXTERN int numBSPDrawVerts Q_ASSIGN( 0 );
-Q_EXTERN bspDrawVert_t *bspDrawVerts Q_ASSIGN( NULL );
+Q_EXTERN bspDrawVert_t *bspDrawVerts Q_ASSIGN( NULL );
Q_EXTERN int numBSPDrawIndexes Q_ASSIGN( 0 );
-Q_EXTERN int bspDrawIndexes[ MAX_MAP_DRAW_INDEXES ];
+Q_EXTERN int allocatedBSPDrawIndexes Q_ASSIGN( 0 );
+Q_EXTERN int *bspDrawIndexes Q_ASSIGN( NULL );
Q_EXTERN int numBSPDrawSurfaces Q_ASSIGN( 0 );
Q_EXTERN bspDrawSurface_t *bspDrawSurfaces Q_ASSIGN( NULL );
Q_EXTERN int numBSPAds Q_ASSIGN( 0 );
Q_EXTERN bspAdvertisement_t bspAds[ MAX_MAP_ADVERTISEMENTS ];
+#define AUTOEXPAND_BY_REALLOC( ptr, reqitem, allocated, def ) \
+ do \
+ { \
+ if ( reqitem >= allocated ) \
+ { \
+ if ( allocated == 0 ) { \
+ allocated = def; } \
+ while ( reqitem >= allocated && allocated ) \
+ allocated *= 2; \
+ if ( !allocated || allocated > 2147483647 / (int)sizeof( *ptr ) ) \
+ { \
+ Error( # ptr " over 2 GB" ); \
+ } \
+ ptr = realloc( ptr, sizeof( *ptr ) * allocated ); \
+ if ( !ptr ) { \
+ Error( # ptr " out of memory" ); } \
+ } \
+ } \
+ while ( 0 )
+
+#define AUTOEXPAND_BY_REALLOC_BSP( suffix, def ) AUTOEXPAND_BY_REALLOC( bsp ## suffix, numBSP ## suffix, allocatedBSP ## suffix, def )
+
+#define Image_LinearFloatFromsRGBFloat( c ) ( ( ( c ) <= 0.04045f ) ? ( c ) * ( 1.0f / 12.92f ) : (float)pow( ( ( c ) + 0.055f ) * ( 1.0f / 1.055f ), 2.4f ) )
+#define Image_sRGBFloatFromLinearFloat( c ) ( ( ( c ) < 0.0031308f ) ? ( c ) * 12.92f : 1.055f * (float)pow( ( c ), 1.0f / 2.4f ) - 0.055f )
/* end marker */
#endif