diff options
author | tma <tma@edf5b092-35ff-0310-97b2-ce42778d08ea> | 2005-09-28 18:55:31 +0000 |
---|---|---|
committer | tma <tma@edf5b092-35ff-0310-97b2-ce42778d08ea> | 2005-09-28 18:55:31 +0000 |
commit | ec912002d3f75729c627cf467903c4607a529495 (patch) | |
tree | b944aa3ec6a159d4607b3bb25cb09640bca02ddb | |
parent | ea1ca0473a510a02fff82788a2a6c8d95a6bf2d3 (diff) | |
download | ioquake3-aero-ec912002d3f75729c627cf467903c4607a529495.tar.gz ioquake3-aero-ec912002d3f75729c627cf467903c4607a529495.zip |
* Removed q3map and associated common and libs directories
git-svn-id: svn://svn.icculus.org/quake3/trunk@123 edf5b092-35ff-0310-97b2-ce42778d08ea
106 files changed, 0 insertions, 59274 deletions
diff --git a/common/aselib.c b/common/aselib.c deleted file mode 100644 index dd6ebb2..0000000 --- a/common/aselib.c +++ /dev/null @@ -1,933 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "aselib.h" - -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> - -#define MAX_ASE_MATERIALS 32 -#define MAX_ASE_OBJECTS 64 -#define MAX_ASE_ANIMATIONS 32 -#define MAX_ASE_ANIMATION_FRAMES 512 - -#define VERBOSE( x ) { if ( ase.verbose ) { printf x ; } } - -typedef struct -{ - float x, y, z; - float nx, ny, nz; - float s, t; -} aseVertex_t; - -typedef struct -{ - float s, t; -} aseTVertex_t; - -typedef int aseFace_t[3]; - -typedef struct -{ - int numFaces; - int numVertexes; - int numTVertexes; - - int timeValue; - - aseVertex_t *vertexes; - aseTVertex_t *tvertexes; - aseFace_t *faces, *tfaces; - - int currentFace, currentVertex; -} aseMesh_t; - -typedef struct -{ - int numFrames; - aseMesh_t frames[MAX_ASE_ANIMATION_FRAMES]; - - int currentFrame; -} aseMeshAnimation_t; - -typedef struct -{ - char name[128]; -} aseMaterial_t; - -/* -** contains the animate sequence of a single surface -** using a single material -*/ -typedef struct -{ - char name[128]; - - int materialRef; - int numAnimations; - - aseMeshAnimation_t anim; - -} aseGeomObject_t; - -typedef struct -{ - int numMaterials; - aseMaterial_t materials[MAX_ASE_MATERIALS]; - aseGeomObject_t objects[MAX_ASE_OBJECTS]; - - char *buffer; - char *curpos; - int len; - - int currentObject; - qboolean verbose; - qboolean grabAnims; - -} ase_t; - -static char s_token[1024]; -static ase_t ase; - -static void ASE_Process( void ); -static void ASE_FreeGeomObject( int ndx ); - -/* -** ASE_Load -*/ -void ASE_Load( const char *filename, qboolean verbose, qboolean grabAnims ) -{ - FILE *fp = fopen( filename, "rb" ); - - if ( !fp ) - Error( "File not found '%s'", filename ); - - memset( &ase, 0, sizeof( ase ) ); - - ase.verbose = verbose; - ase.grabAnims = grabAnims; - ase.len = Q_filelength( fp ); - - ase.curpos = ase.buffer = malloc( ase.len ); - - printf( "Processing '%s'\n", filename ); - - if ( fread( ase.buffer, ase.len, 1, fp ) != 1 ) - { - fclose( fp ); - Error( "fread() != -1 for '%s'", filename ); - } - - fclose( fp ); - - ASE_Process(); -} - -/* -** ASE_Free -*/ -void ASE_Free( void ) -{ - int i; - - for ( i = 0; i < ase.currentObject; i++ ) - { - ASE_FreeGeomObject( i ); - } -} - -/* -** ASE_GetNumSurfaces -*/ -int ASE_GetNumSurfaces( void ) -{ - return ase.currentObject; -} - -/* -** ASE_GetSurfaceName -*/ -const char *ASE_GetSurfaceName( int which ) -{ - aseGeomObject_t *pObject = &ase.objects[which]; - - if ( !pObject->anim.numFrames ) - return 0; - - return pObject->name; -} - -/* -** ASE_GetSurfaceAnimation -** -** Returns an animation (sequence of polysets) -*/ -polyset_t *ASE_GetSurfaceAnimation( int which, int *pNumFrames, int skipFrameStart, int skipFrameEnd, int maxFrames ) -{ - aseGeomObject_t *pObject = &ase.objects[which]; - polyset_t *psets; - int numFramesInAnimation; - int numFramesToKeep; - int i, f; - - if ( !pObject->anim.numFrames ) - return 0; - - if ( pObject->anim.numFrames > maxFrames && maxFrames != -1 ) - { - numFramesInAnimation = maxFrames; - } - else - { - numFramesInAnimation = pObject->anim.numFrames; - if ( maxFrames != -1 ) - printf( "WARNING: ASE_GetSurfaceAnimation maxFrames > numFramesInAnimation\n" ); - } - - if ( skipFrameEnd != -1 ) - numFramesToKeep = numFramesInAnimation - ( skipFrameEnd - skipFrameStart + 1 ); - else - numFramesToKeep = numFramesInAnimation; - - *pNumFrames = numFramesToKeep; - - psets = calloc( sizeof( polyset_t ) * numFramesToKeep, 1 ); - - for ( f = 0, i = 0; i < numFramesInAnimation; i++ ) - { - int t; - aseMesh_t *pMesh = &pObject->anim.frames[i]; - - if ( skipFrameStart != -1 ) - { - if ( i >= skipFrameStart && i <= skipFrameEnd ) - continue; - } - - strcpy( psets[f].name, pObject->name ); - strcpy( psets[f].materialname, ase.materials[pObject->materialRef].name ); - - psets[f].triangles = calloc( sizeof( triangle_t ) * pObject->anim.frames[i].numFaces, 1 ); - psets[f].numtriangles = pObject->anim.frames[i].numFaces; - - for ( t = 0; t < pObject->anim.frames[i].numFaces; t++ ) - { - int k; - - for ( k = 0; k < 3; k++ ) - { - psets[f].triangles[t].verts[k][0] = pMesh->vertexes[pMesh->faces[t][k]].x; - psets[f].triangles[t].verts[k][1] = pMesh->vertexes[pMesh->faces[t][k]].y; - psets[f].triangles[t].verts[k][2] = pMesh->vertexes[pMesh->faces[t][k]].z; - - if ( pMesh->tvertexes && pMesh->tfaces ) - { - psets[f].triangles[t].texcoords[k][0] = pMesh->tvertexes[pMesh->tfaces[t][k]].s; - psets[f].triangles[t].texcoords[k][1] = pMesh->tvertexes[pMesh->tfaces[t][k]].t; - } - - } - } - - f++; - } - - return psets; -} - -static void ASE_FreeGeomObject( int ndx ) -{ - aseGeomObject_t *pObject; - int i; - - pObject = &ase.objects[ndx]; - - for ( i = 0; i < pObject->anim.numFrames; i++ ) - { - if ( pObject->anim.frames[i].vertexes ) - { - free( pObject->anim.frames[i].vertexes ); - } - if ( pObject->anim.frames[i].tvertexes ) - { - free( pObject->anim.frames[i].tvertexes ); - } - if ( pObject->anim.frames[i].faces ) - { - free( pObject->anim.frames[i].faces ); - } - if ( pObject->anim.frames[i].tfaces ) - { - free( pObject->anim.frames[i].tfaces ); - } - } - - memset( pObject, 0, sizeof( *pObject ) ); -} - -static aseMesh_t *ASE_GetCurrentMesh( void ) -{ - aseGeomObject_t *pObject; - - if ( ase.currentObject >= MAX_ASE_OBJECTS ) - { - Error( "Too many GEOMOBJECTs" ); - return 0; // never called - } - - pObject = &ase.objects[ase.currentObject]; - - if ( pObject->anim.currentFrame >= MAX_ASE_ANIMATION_FRAMES ) - { - Error( "Too many MESHes" ); - return 0; - } - - return &pObject->anim.frames[pObject->anim.currentFrame]; -} - -static int CharIsTokenDelimiter( int ch ) -{ - if ( ch <= 32 ) - return 1; - return 0; -} - -static int ASE_GetToken( qboolean restOfLine ) -{ - int i = 0; - - if ( ase.buffer == 0 ) - return 0; - - if ( ( ase.curpos - ase.buffer ) == ase.len ) - return 0; - - // skip over crap - while ( ( ( ase.curpos - ase.buffer ) < ase.len ) && - ( *ase.curpos <= 32 ) ) - { - ase.curpos++; - } - - while ( ( ase.curpos - ase.buffer ) < ase.len ) - { - s_token[i] = *ase.curpos; - - ase.curpos++; - i++; - - if ( ( CharIsTokenDelimiter( s_token[i-1] ) && !restOfLine ) || - ( ( s_token[i-1] == '\n' ) || ( s_token[i-1] == '\r' ) ) ) - { - s_token[i-1] = 0; - break; - } - } - - s_token[i] = 0; - - return 1; -} - -static void ASE_ParseBracedBlock( void (*parser)( const char *token ) ) -{ - int indent = 0; - - while ( ASE_GetToken( qfalse ) ) - { - if ( !strcmp( s_token, "{" ) ) - { - indent++; - } - else if ( !strcmp( s_token, "}" ) ) - { - --indent; - if ( indent == 0 ) - break; - else if ( indent < 0 ) - Error( "Unexpected '}'" ); - } - else - { - if ( parser ) - parser( s_token ); - } - } -} - -static void ASE_SkipEnclosingBraces( void ) -{ - int indent = 0; - - while ( ASE_GetToken( qfalse ) ) - { - if ( !strcmp( s_token, "{" ) ) - { - indent++; - } - else if ( !strcmp( s_token, "}" ) ) - { - indent--; - if ( indent == 0 ) - break; - else if ( indent < 0 ) - Error( "Unexpected '}'" ); - } - } -} - -static void ASE_SkipRestOfLine( void ) -{ - ASE_GetToken( qtrue ); -} - -static void ASE_KeyMAP_DIFFUSE( const char *token ) -{ - char buffer[1024], buff1[1024], buff2[1024]; - char *buf1, *buf2; - int i = 0, count; - - if ( !strcmp( token, "*BITMAP" ) ) - { - ASE_GetToken( qfalse ); - - strcpy( buffer, s_token + 1 ); - if ( strchr( buffer, '"' ) ) - *strchr( buffer, '"' ) = 0; - - while ( buffer[i] ) - { - if ( buffer[i] == '\\' ) - buffer[i] = '/'; - i++; - } - - buf1 = buffer; - buf2 = gamedir; - // need to compare win32 volumes to potential unix junk - // - if ( (gamedir[1] == ':' && (buffer[0] == '/' && buffer[1] == '/')) || - (buffer[1] == ':' && (gamedir[0] == '/' && gamedir[1] == '/')) ) { - if (buffer[1] == ':') { - buf1 = buffer + 2; - buf2 = gamedir + 2; - } else { - buf1 = gamedir + 2; - buf2 = buffer +2; - } - count = 0; - while (*buf2 && count < 2) { - if (*buf2 == '/') { - count++; - } - buf2++; - } - } - strcpy(buff1, buf1); - strlwr(buff1); - strcpy(buff2, buf2); - strlwr(buff2); - if ( strstr( buff2, buff1 + 2 ) ) - { - strcpy( ase.materials[ase.numMaterials].name, strstr( buff2, buff1 + 2 ) + strlen( buff1 ) - 2 ); - } - else - { - sprintf( ase.materials[ase.numMaterials].name, "(not converted: '%s')", buffer ); - printf( "WARNING: illegal material name '%s'\n", buffer ); - } - } - else - { - } -} - -static void ASE_KeyMATERIAL( const char *token ) -{ - if ( !strcmp( token, "*MAP_DIFFUSE" ) ) - { - ASE_ParseBracedBlock( ASE_KeyMAP_DIFFUSE ); - } - else - { - } -} - -static void ASE_KeyMATERIAL_LIST( const char *token ) -{ - if ( !strcmp( token, "*MATERIAL_COUNT" ) ) - { - ASE_GetToken( qfalse ); - VERBOSE( ( "..num materials: %s\n", s_token ) ); - if ( atoi( s_token ) > MAX_ASE_MATERIALS ) - { - Error( "Too many materials!" ); - } - ase.numMaterials = 0; - } - else if ( !strcmp( token, "*MATERIAL" ) ) - { - VERBOSE( ( "..material %d ", ase.numMaterials ) ); - ASE_ParseBracedBlock( ASE_KeyMATERIAL ); - ase.numMaterials++; - } -} - -static void ASE_KeyMESH_VERTEX_LIST( const char *token ) -{ - aseMesh_t *pMesh = ASE_GetCurrentMesh(); - - if ( !strcmp( token, "*MESH_VERTEX" ) ) - { - ASE_GetToken( qfalse ); // skip number - - ASE_GetToken( qfalse ); - pMesh->vertexes[pMesh->currentVertex].y = atof( s_token ); - - ASE_GetToken( qfalse ); - pMesh->vertexes[pMesh->currentVertex].x = -atof( s_token ); - - ASE_GetToken( qfalse ); - pMesh->vertexes[pMesh->currentVertex].z = atof( s_token ); - - pMesh->currentVertex++; - - if ( pMesh->currentVertex > pMesh->numVertexes ) - { - Error( "pMesh->currentVertex >= pMesh->numVertexes" ); - } - } - else - { - Error( "Unknown token '%s' while parsing MESH_VERTEX_LIST", token ); - } -} - -static void ASE_KeyMESH_FACE_LIST( const char *token ) -{ - aseMesh_t *pMesh = ASE_GetCurrentMesh(); - - if ( !strcmp( token, "*MESH_FACE" ) ) - { - ASE_GetToken( qfalse ); // skip face number - - ASE_GetToken( qfalse ); // skip label - ASE_GetToken( qfalse ); // first vertex - pMesh->faces[pMesh->currentFace][0] = atoi( s_token ); - - ASE_GetToken( qfalse ); // skip label - ASE_GetToken( qfalse ); // second vertex - pMesh->faces[pMesh->currentFace][2] = atoi( s_token ); - - ASE_GetToken( qfalse ); // skip label - ASE_GetToken( qfalse ); // third vertex - pMesh->faces[pMesh->currentFace][1] = atoi( s_token ); - - ASE_GetToken( qtrue ); - -/* - if ( ( p = strstr( s_token, "*MESH_MTLID" ) ) != 0 ) - { - p += strlen( "*MESH_MTLID" ) + 1; - mtlID = atoi( p ); - } - else - { - Error( "No *MESH_MTLID found for face!" ); - } -*/ - - pMesh->currentFace++; - } - else - { - Error( "Unknown token '%s' while parsing MESH_FACE_LIST", token ); - } -} - -static void ASE_KeyTFACE_LIST( const char *token ) -{ - aseMesh_t *pMesh = ASE_GetCurrentMesh(); - - if ( !strcmp( token, "*MESH_TFACE" ) ) - { - int a, b, c; - - ASE_GetToken( qfalse ); - - ASE_GetToken( qfalse ); - a = atoi( s_token ); - ASE_GetToken( qfalse ); - c = atoi( s_token ); - ASE_GetToken( qfalse ); - b = atoi( s_token ); - - pMesh->tfaces[pMesh->currentFace][0] = a; - pMesh->tfaces[pMesh->currentFace][1] = b; - pMesh->tfaces[pMesh->currentFace][2] = c; - - pMesh->currentFace++; - } - else - { - Error( "Unknown token '%s' in MESH_TFACE", token ); - } -} - -static void ASE_KeyMESH_TVERTLIST( const char *token ) -{ - aseMesh_t *pMesh = ASE_GetCurrentMesh(); - - if ( !strcmp( token, "*MESH_TVERT" ) ) - { - char u[80], v[80], w[80]; - - ASE_GetToken( qfalse ); - - ASE_GetToken( qfalse ); - strcpy( u, s_token ); - - ASE_GetToken( qfalse ); - strcpy( v, s_token ); - - ASE_GetToken( qfalse ); - strcpy( w, s_token ); - - pMesh->tvertexes[pMesh->currentVertex].s = atof( u ); - pMesh->tvertexes[pMesh->currentVertex].t = 1.0f - atof( v ); - - pMesh->currentVertex++; - - if ( pMesh->currentVertex > pMesh->numTVertexes ) - { - Error( "pMesh->currentVertex > pMesh->numTVertexes" ); - } - } - else - { - Error( "Unknown token '%s' while parsing MESH_TVERTLIST" ); - } -} - -static void ASE_KeyMESH( const char *token ) -{ - aseMesh_t *pMesh = ASE_GetCurrentMesh(); - - if ( !strcmp( token, "*TIMEVALUE" ) ) - { - ASE_GetToken( qfalse ); - - pMesh->timeValue = atoi( s_token ); - VERBOSE( ( ".....timevalue: %d\n", pMesh->timeValue ) ); - } - else if ( !strcmp( token, "*MESH_NUMVERTEX" ) ) - { - ASE_GetToken( qfalse ); - - pMesh->numVertexes = atoi( s_token ); - VERBOSE( ( ".....TIMEVALUE: %d\n", pMesh->timeValue ) ); - VERBOSE( ( ".....num vertexes: %d\n", pMesh->numVertexes ) ); - } - else if ( !strcmp( token, "*MESH_NUMFACES" ) ) - { - ASE_GetToken( qfalse ); - - pMesh->numFaces = atoi( s_token ); - VERBOSE( ( ".....num faces: %d\n", pMesh->numFaces ) ); - } - else if ( !strcmp( token, "*MESH_NUMTVFACES" ) ) - { - ASE_GetToken( qfalse ); - - if ( atoi( s_token ) != pMesh->numFaces ) - { - Error( "MESH_NUMTVFACES != MESH_NUMFACES" ); - } - } - else if ( !strcmp( token, "*MESH_NUMTVERTEX" ) ) - { - ASE_GetToken( qfalse ); - - pMesh->numTVertexes = atoi( s_token ); - VERBOSE( ( ".....num tvertexes: %d\n", pMesh->numTVertexes ) ); - } - else if ( !strcmp( token, "*MESH_VERTEX_LIST" ) ) - { - pMesh->vertexes = calloc( sizeof( aseVertex_t ) * pMesh->numVertexes, 1 ); - pMesh->currentVertex = 0; - VERBOSE( ( ".....parsing MESH_VERTEX_LIST\n" ) ); - ASE_ParseBracedBlock( ASE_KeyMESH_VERTEX_LIST ); - } - else if ( !strcmp( token, "*MESH_TVERTLIST" ) ) - { - pMesh->currentVertex = 0; - pMesh->tvertexes = calloc( sizeof( aseTVertex_t ) * pMesh->numTVertexes, 1 ); - VERBOSE( ( ".....parsing MESH_TVERTLIST\n" ) ); - ASE_ParseBracedBlock( ASE_KeyMESH_TVERTLIST ); - } - else if ( !strcmp( token, "*MESH_FACE_LIST" ) ) - { - pMesh->faces = calloc( sizeof( aseFace_t ) * pMesh->numFaces, 1 ); - pMesh->currentFace = 0; - VERBOSE( ( ".....parsing MESH_FACE_LIST\n" ) ); - ASE_ParseBracedBlock( ASE_KeyMESH_FACE_LIST ); - } - else if ( !strcmp( token, "*MESH_TFACELIST" ) ) - { - pMesh->tfaces = calloc( sizeof( aseFace_t ) * pMesh->numFaces, 1 ); - pMesh->currentFace = 0; - VERBOSE( ( ".....parsing MESH_TFACE_LIST\n" ) ); - ASE_ParseBracedBlock( ASE_KeyTFACE_LIST ); - } - else if ( !strcmp( token, "*MESH_NORMALS" ) ) - { - ASE_ParseBracedBlock( 0 ); - } -} - -static void ASE_KeyMESH_ANIMATION( const char *token ) -{ - aseMesh_t *pMesh = ASE_GetCurrentMesh(); - - // loads a single animation frame - if ( !strcmp( token, "*MESH" ) ) - { - VERBOSE( ( "...found MESH\n" ) ); - assert( pMesh->faces == 0 ); - assert( pMesh->vertexes == 0 ); - assert( pMesh->tvertexes == 0 ); - memset( pMesh, 0, sizeof( *pMesh ) ); - - ASE_ParseBracedBlock( ASE_KeyMESH ); - - if ( ++ase.objects[ase.currentObject].anim.currentFrame == MAX_ASE_ANIMATION_FRAMES ) - { - Error( "Too many animation frames" ); - } - } - else - { - Error( "Unknown token '%s' while parsing MESH_ANIMATION", token ); - } -} - -static void ASE_KeyGEOMOBJECT( const char *token ) -{ - if ( !strcmp( token, "*NODE_NAME" ) ) - { - char *name = ase.objects[ase.currentObject].name; - - ASE_GetToken( qtrue ); - VERBOSE( ( " %s\n", s_token ) ); - strcpy( ase.objects[ase.currentObject].name, s_token + 1 ); - if ( strchr( ase.objects[ase.currentObject].name, '"' ) ) - *strchr( ase.objects[ase.currentObject].name, '"' ) = 0; - - if ( strstr( name, "tag" ) == name ) - { - while ( strchr( name, '_' ) != strrchr( name, '_' ) ) - { - *strrchr( name, '_' ) = 0; - } - while ( strrchr( name, ' ' ) ) - { - *strrchr( name, ' ' ) = 0; - } - } - } - else if ( !strcmp( token, "*NODE_PARENT" ) ) - { - ASE_SkipRestOfLine(); - } - // ignore unused data blocks - else if ( !strcmp( token, "*NODE_TM" ) || - !strcmp( token, "*TM_ANIMATION" ) ) - { - ASE_ParseBracedBlock( 0 ); - } - // ignore regular meshes that aren't part of animation - else if ( !strcmp( token, "*MESH" ) && !ase.grabAnims ) - { -/* - if ( strstr( ase.objects[ase.currentObject].name, "tag_" ) == ase.objects[ase.currentObject].name ) - { - s_forceStaticMesh = true; - ASE_ParseBracedBlock( ASE_KeyMESH ); - s_forceStaticMesh = false; - } -*/ - ASE_ParseBracedBlock( ASE_KeyMESH ); - if ( ++ase.objects[ase.currentObject].anim.currentFrame == MAX_ASE_ANIMATION_FRAMES ) - { - Error( "Too many animation frames" ); - } - ase.objects[ase.currentObject].anim.numFrames = ase.objects[ase.currentObject].anim.currentFrame; - ase.objects[ase.currentObject].numAnimations++; -/* - // ignore meshes that aren't part of animations if this object isn't a - // a tag - else - { - ASE_ParseBracedBlock( 0 ); - } -*/ - } - // according to spec these are obsolete - else if ( !strcmp( token, "*MATERIAL_REF" ) ) - { - ASE_GetToken( qfalse ); - - ase.objects[ase.currentObject].materialRef = atoi( s_token ); - } - // loads a sequence of animation frames - else if ( !strcmp( token, "*MESH_ANIMATION" ) ) - { - if ( ase.grabAnims ) - { - VERBOSE( ( "..found MESH_ANIMATION\n" ) ); - - if ( ase.objects[ase.currentObject].numAnimations ) - { - Error( "Multiple MESH_ANIMATIONS within a single GEOM_OBJECT" ); - } - ASE_ParseBracedBlock( ASE_KeyMESH_ANIMATION ); - ase.objects[ase.currentObject].anim.numFrames = ase.objects[ase.currentObject].anim.currentFrame; - ase.objects[ase.currentObject].numAnimations++; - } - else - { - ASE_SkipEnclosingBraces(); - } - } - // skip unused info - else if ( !strcmp( token, "*PROP_MOTIONBLUR" ) || - !strcmp( token, "*PROP_CASTSHADOW" ) || - !strcmp( token, "*PROP_RECVSHADOW" ) ) - { - ASE_SkipRestOfLine(); - } -} - -static void ConcatenateObjects( aseGeomObject_t *pObjA, aseGeomObject_t *pObjB ) -{ -} - -static void CollapseObjects( void ) -{ - int i; - int numObjects = ase.currentObject; - - for ( i = 0; i < numObjects; i++ ) - { - int j; - - // skip tags - if ( strstr( ase.objects[i].name, "tag" ) == ase.objects[i].name ) - { - continue; - } - - if ( !ase.objects[i].numAnimations ) - { - continue; - } - - for ( j = i + 1; j < numObjects; j++ ) - { - if ( strstr( ase.objects[j].name, "tag" ) == ase.objects[j].name ) - { - continue; - } - if ( ase.objects[i].materialRef == ase.objects[j].materialRef ) - { - if ( ase.objects[j].numAnimations ) - { - ConcatenateObjects( &ase.objects[i], &ase.objects[j] ); - } - } - } - } -} - -/* -** ASE_Process -*/ -static void ASE_Process( void ) -{ - while ( ASE_GetToken( qfalse ) ) - { - if ( !strcmp( s_token, "*3DSMAX_ASCIIEXPORT" ) || - !strcmp( s_token, "*COMMENT" ) ) - { - ASE_SkipRestOfLine(); - } - else if ( !strcmp( s_token, "*SCENE" ) ) - ASE_SkipEnclosingBraces(); - else if ( !strcmp( s_token, "*MATERIAL_LIST" ) ) - { - VERBOSE( ("MATERIAL_LIST\n") ); - - ASE_ParseBracedBlock( ASE_KeyMATERIAL_LIST ); - } - else if ( !strcmp( s_token, "*GEOMOBJECT" ) ) - { - VERBOSE( ("GEOMOBJECT" ) ); - - ASE_ParseBracedBlock( ASE_KeyGEOMOBJECT ); - - if ( strstr( ase.objects[ase.currentObject].name, "Bip" ) || - strstr( ase.objects[ase.currentObject].name, "ignore_" ) ) - { - ASE_FreeGeomObject( ase.currentObject ); - VERBOSE( ( "(discarding BIP/ignore object)\n" ) ); - } - else if ( ( strstr( ase.objects[ase.currentObject].name, "h_" ) != ase.objects[ase.currentObject].name ) && - ( strstr( ase.objects[ase.currentObject].name, "l_" ) != ase.objects[ase.currentObject].name ) && - ( strstr( ase.objects[ase.currentObject].name, "u_" ) != ase.objects[ase.currentObject].name ) && - ( strstr( ase.objects[ase.currentObject].name, "tag" ) != ase.objects[ase.currentObject].name ) && - ase.grabAnims ) - { - VERBOSE( ( "(ignoring improperly labeled object '%s')\n", ase.objects[ase.currentObject].name ) ); - ASE_FreeGeomObject( ase.currentObject ); - } - else - { - if ( ++ase.currentObject == MAX_ASE_OBJECTS ) - { - Error( "Too many GEOMOBJECTs" ); - } - } - } - else if ( s_token[0] ) - { - printf( "Unknown token '%s'\n", s_token ); - } - } - - if ( !ase.currentObject ) - Error( "No animation data!" ); - - CollapseObjects(); -} - diff --git a/common/aselib.h b/common/aselib.h deleted file mode 100644 index 2bc756b..0000000 --- a/common/aselib.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "cmdlib.h" -#include "mathlib.h" -#include "polyset.h" - -void ASE_Load( const char *filename, qboolean verbose, qboolean meshanims ); -int ASE_GetNumSurfaces( void ); -polyset_t *ASE_GetSurfaceAnimation( int ndx, int *numFrames, int skipFrameStart, int skipFrameEnd, int maxFrames ); -const char *ASE_GetSurfaceName( int ndx ); -void ASE_Free( void ); diff --git a/common/bspfile.c b/common/bspfile.c deleted file mode 100644 index 38c8051..0000000 --- a/common/bspfile.c +++ /dev/null @@ -1,564 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "cmdlib.h" -#include "mathlib.h" -#include "bspfile.h" -#include "scriplib.h" - -void GetLeafNums (void); - -//============================================================================= - -int nummodels; -dmodel_t dmodels[MAX_MAP_MODELS]; - -int numShaders; -dshader_t dshaders[MAX_MAP_SHADERS]; - -int entdatasize; -char dentdata[MAX_MAP_ENTSTRING]; - -int numleafs; -dleaf_t dleafs[MAX_MAP_LEAFS]; - -int numplanes; -dplane_t dplanes[MAX_MAP_PLANES]; - -int numnodes; -dnode_t dnodes[MAX_MAP_NODES]; - -int numleafsurfaces; -int dleafsurfaces[MAX_MAP_LEAFFACES]; - -int numleafbrushes; -int dleafbrushes[MAX_MAP_LEAFBRUSHES]; - -int numbrushes; -dbrush_t dbrushes[MAX_MAP_BRUSHES]; - -int numbrushsides; -dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES]; - -int numLightBytes; -byte lightBytes[MAX_MAP_LIGHTING]; - -int numGridPoints; -byte gridData[MAX_MAP_LIGHTGRID]; - -int numVisBytes; -byte visBytes[MAX_MAP_VISIBILITY]; - -int numDrawVerts; -drawVert_t drawVerts[MAX_MAP_DRAW_VERTS]; - -int numDrawIndexes; -int drawIndexes[MAX_MAP_DRAW_INDEXES]; - -int numDrawSurfaces; -dsurface_t drawSurfaces[MAX_MAP_DRAW_SURFS]; - -int numFogs; -dfog_t dfogs[MAX_MAP_FOGS]; - -//============================================================================= - -/* -============= -SwapBlock - -If all values are 32 bits, this can be used to swap everything -============= -*/ -void SwapBlock( int *block, int sizeOfBlock ) { - int i; - - sizeOfBlock >>= 2; - for ( i = 0 ; i < sizeOfBlock ; i++ ) { - block[i] = LittleLong( block[i] ); - } -} - -/* -============= -SwapBSPFile - -Byte swaps all data in a bsp file. -============= -*/ -void SwapBSPFile( void ) { - int i; - - // models - SwapBlock( (int *)dmodels, nummodels * sizeof( dmodels[0] ) ); - - // shaders (don't swap the name) - for ( i = 0 ; i < numShaders ; i++ ) { - dshaders[i].contentFlags = LittleLong( dshaders[i].contentFlags ); - dshaders[i].surfaceFlags = LittleLong( dshaders[i].surfaceFlags ); - } - - // planes - SwapBlock( (int *)dplanes, numplanes * sizeof( dplanes[0] ) ); - - // nodes - SwapBlock( (int *)dnodes, numnodes * sizeof( dnodes[0] ) ); - - // leafs - SwapBlock( (int *)dleafs, numleafs * sizeof( dleafs[0] ) ); - - // leaffaces - SwapBlock( (int *)dleafsurfaces, numleafsurfaces * sizeof( dleafsurfaces[0] ) ); - - // leafbrushes - SwapBlock( (int *)dleafbrushes, numleafbrushes * sizeof( dleafbrushes[0] ) ); - - // brushes - SwapBlock( (int *)dbrushes, numbrushes * sizeof( dbrushes[0] ) ); - - // brushsides - SwapBlock( (int *)dbrushsides, numbrushsides * sizeof( dbrushsides[0] ) ); - - // vis - ((int *)&visBytes)[0] = LittleLong( ((int *)&visBytes)[0] ); - ((int *)&visBytes)[1] = LittleLong( ((int *)&visBytes)[1] ); - - // drawverts (don't swap colors ) - for ( i = 0 ; i < numDrawVerts ; i++ ) { - drawVerts[i].lightmap[0] = LittleFloat( drawVerts[i].lightmap[0] ); - drawVerts[i].lightmap[1] = LittleFloat( drawVerts[i].lightmap[1] ); - drawVerts[i].st[0] = LittleFloat( drawVerts[i].st[0] ); - drawVerts[i].st[1] = LittleFloat( drawVerts[i].st[1] ); - drawVerts[i].xyz[0] = LittleFloat( drawVerts[i].xyz[0] ); - drawVerts[i].xyz[1] = LittleFloat( drawVerts[i].xyz[1] ); - drawVerts[i].xyz[2] = LittleFloat( drawVerts[i].xyz[2] ); - drawVerts[i].normal[0] = LittleFloat( drawVerts[i].normal[0] ); - drawVerts[i].normal[1] = LittleFloat( drawVerts[i].normal[1] ); - drawVerts[i].normal[2] = LittleFloat( drawVerts[i].normal[2] ); - } - - // drawindexes - SwapBlock( (int *)drawIndexes, numDrawIndexes * sizeof( drawIndexes[0] ) ); - - // drawsurfs - SwapBlock( (int *)drawSurfaces, numDrawSurfaces * sizeof( drawSurfaces[0] ) ); - - // fogs - for ( i = 0 ; i < numFogs ; i++ ) { - dfogs[i].brushNum = LittleLong( dfogs[i].brushNum ); - dfogs[i].visibleSide = LittleLong( dfogs[i].visibleSide ); - } -} - - - -/* -============= -CopyLump -============= -*/ -int CopyLump( dheader_t *header, int lump, void *dest, int size ) { - int length, ofs; - - length = header->lumps[lump].filelen; - ofs = header->lumps[lump].fileofs; - - if ( length % size ) { - Error ("LoadBSPFile: odd lump size"); - } - - memcpy( dest, (byte *)header + ofs, length ); - - return length / size; -} - -/* -============= -LoadBSPFile -============= -*/ -void LoadBSPFile( const char *filename ) { - dheader_t *header; - - // load the file header - LoadFile (filename, (void **)&header); - - // swap the header - SwapBlock( (int *)header, sizeof(*header) ); - - if ( header->ident != BSP_IDENT ) { - Error( "%s is not a IBSP file", filename ); - } - if ( header->version != BSP_VERSION ) { - Error( "%s is version %i, not %i", filename, header->version, BSP_VERSION ); - } - - numShaders = CopyLump( header, LUMP_SHADERS, dshaders, sizeof(dshader_t) ); - nummodels = CopyLump( header, LUMP_MODELS, dmodels, sizeof(dmodel_t) ); - numplanes = CopyLump( header, LUMP_PLANES, dplanes, sizeof(dplane_t) ); - numleafs = CopyLump( header, LUMP_LEAFS, dleafs, sizeof(dleaf_t) ); - numnodes = CopyLump( header, LUMP_NODES, dnodes, sizeof(dnode_t) ); - numleafsurfaces = CopyLump( header, LUMP_LEAFSURFACES, dleafsurfaces, sizeof(dleafsurfaces[0]) ); - numleafbrushes = CopyLump( header, LUMP_LEAFBRUSHES, dleafbrushes, sizeof(dleafbrushes[0]) ); - numbrushes = CopyLump( header, LUMP_BRUSHES, dbrushes, sizeof(dbrush_t) ); - numbrushsides = CopyLump( header, LUMP_BRUSHSIDES, dbrushsides, sizeof(dbrushside_t) ); - numDrawVerts = CopyLump( header, LUMP_DRAWVERTS, drawVerts, sizeof(drawVert_t) ); - numDrawSurfaces = CopyLump( header, LUMP_SURFACES, drawSurfaces, sizeof(dsurface_t) ); - numFogs = CopyLump( header, LUMP_FOGS, dfogs, sizeof(dfog_t) ); - numDrawIndexes = CopyLump( header, LUMP_DRAWINDEXES, drawIndexes, sizeof(drawIndexes[0]) ); - - numVisBytes = CopyLump( header, LUMP_VISIBILITY, visBytes, 1 ); - numLightBytes = CopyLump( header, LUMP_LIGHTMAPS, lightBytes, 1 ); - entdatasize = CopyLump( header, LUMP_ENTITIES, dentdata, 1); - - numGridPoints = CopyLump( header, LUMP_LIGHTGRID, gridData, 8 ); - - - free( header ); // everything has been copied out - - // swap everything - SwapBSPFile(); -} - - -//============================================================================ - -/* -============= -AddLump -============= -*/ -void AddLump( FILE *bspfile, dheader_t *header, int lumpnum, const void *data, int len ) { - lump_t *lump; - - lump = &header->lumps[lumpnum]; - - lump->fileofs = LittleLong( ftell(bspfile) ); - lump->filelen = LittleLong( len ); - SafeWrite( bspfile, data, (len+3)&~3 ); -} - -/* -============= -WriteBSPFile - -Swaps the bsp file in place, so it should not be referenced again -============= -*/ -void WriteBSPFile( const char *filename ) { - dheader_t outheader, *header; - FILE *bspfile; - - header = &outheader; - memset( header, 0, sizeof(dheader_t) ); - - SwapBSPFile(); - - header->ident = LittleLong( BSP_IDENT ); - header->version = LittleLong( BSP_VERSION ); - - bspfile = SafeOpenWrite( filename ); - SafeWrite( bspfile, header, sizeof(dheader_t) ); // overwritten later - - AddLump( bspfile, header, LUMP_SHADERS, dshaders, numShaders*sizeof(dshader_t) ); - AddLump( bspfile, header, LUMP_PLANES, dplanes, numplanes*sizeof(dplane_t) ); - AddLump( bspfile, header, LUMP_LEAFS, dleafs, numleafs*sizeof(dleaf_t) ); - AddLump( bspfile, header, LUMP_NODES, dnodes, numnodes*sizeof(dnode_t) ); - AddLump( bspfile, header, LUMP_BRUSHES, dbrushes, numbrushes*sizeof(dbrush_t) ); - AddLump( bspfile, header, LUMP_BRUSHSIDES, dbrushsides, numbrushsides*sizeof(dbrushside_t) ); - AddLump( bspfile, header, LUMP_LEAFSURFACES, dleafsurfaces, numleafsurfaces*sizeof(dleafsurfaces[0]) ); - AddLump( bspfile, header, LUMP_LEAFBRUSHES, dleafbrushes, numleafbrushes*sizeof(dleafbrushes[0]) ); - AddLump( bspfile, header, LUMP_MODELS, dmodels, nummodels*sizeof(dmodel_t) ); - AddLump( bspfile, header, LUMP_DRAWVERTS, drawVerts, numDrawVerts*sizeof(drawVert_t) ); - AddLump( bspfile, header, LUMP_SURFACES, drawSurfaces, numDrawSurfaces*sizeof(dsurface_t) ); - AddLump( bspfile, header, LUMP_VISIBILITY, visBytes, numVisBytes ); - AddLump( bspfile, header, LUMP_LIGHTMAPS, lightBytes, numLightBytes ); - AddLump( bspfile, header, LUMP_LIGHTGRID, gridData, 8 * numGridPoints ); - AddLump( bspfile, header, LUMP_ENTITIES, dentdata, entdatasize ); - AddLump( bspfile, header, LUMP_FOGS, dfogs, numFogs * sizeof(dfog_t) ); - AddLump( bspfile, header, LUMP_DRAWINDEXES, drawIndexes, numDrawIndexes * sizeof(drawIndexes[0]) ); - - fseek (bspfile, 0, SEEK_SET); - SafeWrite (bspfile, header, sizeof(dheader_t)); - fclose (bspfile); -} - -//============================================================================ - -/* -============= -PrintBSPFileSizes - -Dumps info about current file -============= -*/ -void PrintBSPFileSizes( void ) { - if ( !num_entities ) { - ParseEntities(); - } - - printf ("%6i models %7i\n" - ,nummodels, (int)(nummodels*sizeof(dmodel_t))); - printf ("%6i shaders %7i\n" - ,numShaders, (int)(numShaders*sizeof(dshader_t))); - printf ("%6i brushes %7i\n" - ,numbrushes, (int)(numbrushes*sizeof(dbrush_t))); - printf ("%6i brushsides %7i\n" - ,numbrushsides, (int)(numbrushsides*sizeof(dbrushside_t))); - printf ("%6i fogs %7i\n" - ,numFogs, (int)(numFogs*sizeof(dfog_t))); - printf ("%6i planes %7i\n" - ,numplanes, (int)(numplanes*sizeof(dplane_t))); - printf ("%6i entdata %7i\n", num_entities, entdatasize); - - printf ("\n"); - - printf ("%6i nodes %7i\n" - ,numnodes, (int)(numnodes*sizeof(dnode_t))); - printf ("%6i leafs %7i\n" - ,numleafs, (int)(numleafs*sizeof(dleaf_t))); - printf ("%6i leafsurfaces %7i\n" - ,numleafsurfaces, (int)(numleafsurfaces*sizeof(dleafsurfaces[0]))); - printf ("%6i leafbrushes %7i\n" - ,numleafbrushes, (int)(numleafbrushes*sizeof(dleafbrushes[0]))); - printf ("%6i drawverts %7i\n" - ,numDrawVerts, (int)(numDrawVerts*sizeof(drawVerts[0]))); - printf ("%6i drawindexes %7i\n" - ,numDrawIndexes, (int)(numDrawIndexes*sizeof(drawIndexes[0]))); - printf ("%6i drawsurfaces %7i\n" - ,numDrawSurfaces, (int)(numDrawSurfaces*sizeof(drawSurfaces[0]))); - - printf ("%6i lightmaps %7i\n" - ,numLightBytes / (LIGHTMAP_WIDTH*LIGHTMAP_HEIGHT*3), numLightBytes ); - printf (" visibility %7i\n" - , numVisBytes ); -} - - -//============================================ - -int num_entities; -entity_t entities[MAX_MAP_ENTITIES]; - -void StripTrailing( char *e ) { - char *s; - - s = e + strlen(e)-1; - while (s >= e && *s <= 32) - { - *s = 0; - s--; - } -} - -/* -================= -ParseEpair -================= -*/ -epair_t *ParseEpair( void ) { - epair_t *e; - - e = malloc( sizeof(epair_t) ); - memset( e, 0, sizeof(epair_t) ); - - if ( strlen(token) >= MAX_KEY-1 ) { - Error ("ParseEpar: token too long"); - } - e->key = copystring( token ); - GetToken( qfalse ); - if ( strlen(token) >= MAX_VALUE-1 ) { - Error ("ParseEpar: token too long"); - } - e->value = copystring( token ); - - // strip trailing spaces that sometimes get accidentally - // added in the editor - StripTrailing( e->key ); - StripTrailing( e->value ); - - return e; -} - - -/* -================ -ParseEntity -================ -*/ -qboolean ParseEntity( void ) { - epair_t *e; - entity_t *mapent; - - if ( !GetToken (qtrue) ) { - return qfalse; - } - - if ( strcmp (token, "{") ) { - Error ("ParseEntity: { not found"); - } - if ( num_entities == MAX_MAP_ENTITIES ) { - Error ("num_entities == MAX_MAP_ENTITIES"); - } - mapent = &entities[num_entities]; - num_entities++; - - do { - if ( !GetToken (qtrue) ) { - Error ("ParseEntity: EOF without closing brace"); - } - if ( !strcmp (token, "}") ) { - break; - } - e = ParseEpair (); - e->next = mapent->epairs; - mapent->epairs = e; - } while (1); - - return qtrue; -} - -/* -================ -ParseEntities - -Parses the dentdata string into entities -================ -*/ -void ParseEntities( void ) { - num_entities = 0; - ParseFromMemory( dentdata, entdatasize ); - - while ( ParseEntity () ) { - } -} - - -/* -================ -UnparseEntities - -Generates the dentdata string from all the entities -This allows the utilities to add or remove key/value pairs -to the data created by the map editor. -================ -*/ -void UnparseEntities( void ) { - char *buf, *end; - epair_t *ep; - char line[2048]; - int i; - char key[1024], value[1024]; - - buf = dentdata; - end = buf; - *end = 0; - - for (i=0 ; i<num_entities ; i++) { - ep = entities[i].epairs; - if ( !ep ) { - continue; // ent got removed - } - - strcat (end,"{\n"); - end += 2; - - for ( ep = entities[i].epairs ; ep ; ep=ep->next ) { - strcpy (key, ep->key); - StripTrailing (key); - strcpy (value, ep->value); - StripTrailing (value); - - sprintf (line, "\"%s\" \"%s\"\n", key, value); - strcat (end, line); - end += strlen(line); - } - strcat (end,"}\n"); - end += 2; - - if (end > buf + MAX_MAP_ENTSTRING) { - Error ("Entity text too long"); - } - } - entdatasize = end - buf + 1; -} - -void PrintEntity( const entity_t *ent ) { - epair_t *ep; - - printf ("------- entity %p -------\n", ent); - for (ep=ent->epairs ; ep ; ep=ep->next) { - printf( "%s = %s\n", ep->key, ep->value ); - } - -} - -void SetKeyValue( entity_t *ent, const char *key, const char *value ) { - epair_t *ep; - - for ( ep=ent->epairs ; ep ; ep=ep->next ) { - if ( !strcmp (ep->key, key) ) { - free (ep->value); - ep->value = copystring(value); - return; - } - } - ep = malloc (sizeof(*ep)); - ep->next = ent->epairs; - ent->epairs = ep; - ep->key = copystring(key); - ep->value = copystring(value); -} - -const char *ValueForKey( const entity_t *ent, const char *key ) { - epair_t *ep; - - for (ep=ent->epairs ; ep ; ep=ep->next) { - if (!strcmp (ep->key, key) ) { - return ep->value; - } - } - return ""; -} - -vec_t FloatForKey( const entity_t *ent, const char *key ) { - const char *k; - - k = ValueForKey( ent, key ); - return atof(k); -} - -void GetVectorForKey( const entity_t *ent, const char *key, vec3_t vec ) { - const char *k; - double v1, v2, v3; - - k = ValueForKey (ent, key); - - // scanf into doubles, then assign, so it is vec_t size independent - v1 = v2 = v3 = 0; - sscanf (k, "%lf %lf %lf", &v1, &v2, &v3); - vec[0] = v1; - vec[1] = v2; - vec[2] = v3; -} - - diff --git a/common/bspfile.h b/common/bspfile.h deleted file mode 100644 index edd2326..0000000 --- a/common/bspfile.h +++ /dev/null @@ -1,118 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#ifdef _TTIMOBUILD -#include "qfiles.h" -#include "surfaceflags.h" -#else -#include "../code/qcommon/qfiles.h" -#include "../code/game/surfaceflags.h" -#endif - -extern int nummodels; -extern dmodel_t dmodels[MAX_MAP_MODELS]; - -extern int numShaders; -extern dshader_t dshaders[MAX_MAP_MODELS]; - -extern int entdatasize; -extern char dentdata[MAX_MAP_ENTSTRING]; - -extern int numleafs; -extern dleaf_t dleafs[MAX_MAP_LEAFS]; - -extern int numplanes; -extern dplane_t dplanes[MAX_MAP_PLANES]; - -extern int numnodes; -extern dnode_t dnodes[MAX_MAP_NODES]; - -extern int numleafsurfaces; -extern int dleafsurfaces[MAX_MAP_LEAFFACES]; - -extern int numleafbrushes; -extern int dleafbrushes[MAX_MAP_LEAFBRUSHES]; - -extern int numbrushes; -extern dbrush_t dbrushes[MAX_MAP_BRUSHES]; - -extern int numbrushsides; -extern dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES]; - -extern int numLightBytes; -extern byte lightBytes[MAX_MAP_LIGHTING]; - -extern int numGridPoints; -extern byte gridData[MAX_MAP_LIGHTGRID]; - -extern int numVisBytes; -extern byte visBytes[MAX_MAP_VISIBILITY]; - -extern int numDrawVerts; -extern drawVert_t drawVerts[MAX_MAP_DRAW_VERTS]; - -extern int numDrawIndexes; -extern int drawIndexes[MAX_MAP_DRAW_INDEXES]; - -extern int numDrawSurfaces; -extern dsurface_t drawSurfaces[MAX_MAP_DRAW_SURFS]; - -extern int numFogs; -extern dfog_t dfogs[MAX_MAP_FOGS]; - -void LoadBSPFile( const char *filename ); -void WriteBSPFile( const char *filename ); -void PrintBSPFileSizes( void ); - -//=============== - - -typedef struct epair_s { - struct epair_s *next; - char *key; - char *value; -} epair_t; - -typedef struct { - vec3_t origin; - struct bspbrush_s *brushes; - struct parseMesh_s *patches; - int firstDrawSurf; - epair_t *epairs; -} entity_t; - -extern int num_entities; -extern entity_t entities[MAX_MAP_ENTITIES]; - -void ParseEntities( void ); -void UnparseEntities( void ); - -void SetKeyValue( entity_t *ent, const char *key, const char *value ); -const char *ValueForKey( const entity_t *ent, const char *key ); -// will return "" if not present - -vec_t FloatForKey( const entity_t *ent, const char *key ); -void GetVectorForKey( const entity_t *ent, const char *key, vec3_t vec ); - -epair_t *ParseEpair( void ); - -void PrintEntity( const entity_t *ent ); - diff --git a/common/cmdlib.c b/common/cmdlib.c deleted file mode 100644 index 375b19b..0000000 --- a/common/cmdlib.c +++ /dev/null @@ -1,1201 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// cmdlib.c - -#include "cmdlib.h" -#include <sys/types.h> -#include <sys/stat.h> - -#ifdef WIN32 -#include <direct.h> -#include <windows.h> -#endif - -#ifdef NeXT -#include <libc.h> -#endif - -#define BASEDIRNAME "quake" // assumed to have a 2 or 3 following -#define PATHSEPERATOR '/' - -// set these before calling CheckParm -int myargc; -char **myargv; - -char com_token[1024]; -qboolean com_eof; - -qboolean archive; -char archivedir[1024]; - - -/* -=================== -ExpandWildcards - -Mimic unix command line expansion -=================== -*/ -#define MAX_EX_ARGC 1024 -int ex_argc; -char *ex_argv[MAX_EX_ARGC]; -#ifdef _WIN32 -#include "io.h" -void ExpandWildcards( int *argc, char ***argv ) -{ - struct _finddata_t fileinfo; - int handle; - int i; - char filename[1024]; - char filebase[1024]; - char *path; - - ex_argc = 0; - for (i=0 ; i<*argc ; i++) - { - path = (*argv)[i]; - if ( path[0] == '-' - || ( !strstr(path, "*") && !strstr(path, "?") ) ) - { - ex_argv[ex_argc++] = path; - continue; - } - - handle = _findfirst (path, &fileinfo); - if (handle == -1) - return; - - ExtractFilePath (path, filebase); - - do - { - sprintf (filename, "%s%s", filebase, fileinfo.name); - ex_argv[ex_argc++] = copystring (filename); - } while (_findnext( handle, &fileinfo ) != -1); - - _findclose (handle); - } - - *argc = ex_argc; - *argv = ex_argv; -} -#else -void ExpandWildcards (int *argc, char ***argv) -{ -} -#endif - -#ifdef WIN_ERROR -#include <windows.h> -/* -================= -Error - -For abnormal program terminations in windowed apps -================= -*/ -void Error( const char *error, ... ) -{ - va_list argptr; - char text[1024]; - char text2[1024]; - int err; - - err = GetLastError (); - - va_start (argptr,error); - vsprintf (text, error,argptr); - va_end (argptr); - - sprintf (text2, "%s\nGetLastError() = %i", text, err); - MessageBox(NULL, text2, "Error", 0 /* MB_OK */ ); - - exit (1); -} - -#else -/* -================= -Error - -For abnormal program terminations in console apps -================= -*/ -void Error( const char *error, ...) -{ - va_list argptr; - - _printf ("\n************ ERROR ************\n"); - - va_start (argptr,error); - vprintf (error,argptr); - va_end (argptr); - _printf ("\r\n"); - - exit (1); -} -#endif - -// only printf if in verbose mode -qboolean verbose = qfalse; -void qprintf( const char *format, ... ) { - va_list argptr; - - if (!verbose) - return; - - va_start (argptr,format); - vprintf (format,argptr); - va_end (argptr); - -} - -#ifdef WIN32 -HWND hwndOut = NULL; -qboolean lookedForServer = qfalse; -UINT wm_BroadcastCommand = -1; -#endif - -void _printf( const char *format, ... ) { - va_list argptr; - char text[4096]; - ATOM a; - - va_start (argptr,format); - vsprintf (text, format, argptr); - va_end (argptr); - - printf(text); - -#ifdef WIN32 - if (!lookedForServer) { - lookedForServer = qtrue; - hwndOut = FindWindow(NULL, "Q3Map Process Server"); - if (hwndOut) { - wm_BroadcastCommand = RegisterWindowMessage( "Q3MPS_BroadcastCommand" ); - } - } - if (hwndOut) { - a = GlobalAddAtom(text); - PostMessage(hwndOut, wm_BroadcastCommand, 0, (LPARAM)a); - } -#endif -} - - -/* - -qdir will hold the path up to the quake directory, including the slash - - f:\quake\ - /raid/quake/ - -gamedir will hold qdir + the game directory (id1, id2, etc) - - */ - -char qdir[1024]; -char gamedir[1024]; -char writedir[1024]; - -void SetQdirFromPath( const char *path ) -{ - char temp[1024]; - const char *c; - const char *sep; - int len, count; - - if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':')) - { // path is partial - Q_getwd (temp); - strcat (temp, path); - path = temp; - } - - // search for "quake2" in path - - len = strlen(BASEDIRNAME); - for (c=path+strlen(path)-1 ; c != path ; c--) - { - int i; - - if (!Q_strncasecmp (c, BASEDIRNAME, len)) - { - // - //strncpy (qdir, path, c+len+2-path); - // the +2 assumes a 2 or 3 following quake which is not the - // case with a retail install - // so we need to add up how much to the next separator - sep = c + len; - count = 1; - while (*sep && *sep != '/' && *sep != '\\') - { - sep++; - count++; - } - strncpy (qdir, path, c+len+count-path); - qprintf ("qdir: %s\n", qdir); - for ( i = 0; i < strlen( qdir ); i++ ) - { - if ( qdir[i] == '\\' ) - qdir[i] = '/'; - } - - c += len+count; - while (*c) - { - if (*c == '/' || *c == '\\') - { - strncpy (gamedir, path, c+1-path); - - for ( i = 0; i < strlen( gamedir ); i++ ) - { - if ( gamedir[i] == '\\' ) - gamedir[i] = '/'; - } - - qprintf ("gamedir: %s\n", gamedir); - - if ( !writedir[0] ) - strcpy( writedir, gamedir ); - else if ( writedir[strlen( writedir )-1] != '/' ) - { - writedir[strlen( writedir )] = '/'; - writedir[strlen( writedir )+1] = 0; - } - - return; - } - c++; - } - Error ("No gamedir in %s", path); - return; - } - } - Error ("SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path); -} - -char *ExpandArg (const char *path) -{ - static char full[1024]; - - if (path[0] != '/' && path[0] != '\\' && path[1] != ':') - { - Q_getwd (full); - strcat (full, path); - } - else - strcpy (full, path); - return full; -} - -char *ExpandPath (const char *path) -{ - static char full[1024]; - if (!qdir) - Error ("ExpandPath called without qdir set"); - if (path[0] == '/' || path[0] == '\\' || path[1] == ':') { - strcpy( full, path ); - return full; - } - sprintf (full, "%s%s", qdir, path); - return full; -} - -char *ExpandGamePath (const char *path) -{ - static char full[1024]; - if (!qdir) - Error ("ExpandGamePath called without qdir set"); - if (path[0] == '/' || path[0] == '\\' || path[1] == ':') { - strcpy( full, path ); - return full; - } - sprintf (full, "%s%s", gamedir, path); - return full; -} - -char *ExpandPathAndArchive (const char *path) -{ - char *expanded; - char archivename[1024]; - - expanded = ExpandPath (path); - - if (archive) - { - sprintf (archivename, "%s/%s", archivedir, path); - QCopyFile (expanded, archivename); - } - return expanded; -} - - -char *copystring(const char *s) -{ - char *b; - b = malloc(strlen(s)+1); - strcpy (b, s); - return b; -} - - - -/* -================ -I_FloatTime -================ -*/ -double I_FloatTime (void) -{ - time_t t; - - time (&t); - - return t; -#if 0 -// more precise, less portable - struct timeval tp; - struct timezone tzp; - static int secbase; - - gettimeofday(&tp, &tzp); - - if (!secbase) - { - secbase = tp.tv_sec; - return tp.tv_usec/1000000.0; - } - - return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0; -#endif -} - -void Q_getwd (char *out) -{ - int i = 0; - -#ifdef WIN32 - _getcwd (out, 256); - strcat (out, "\\"); -#else - getwd (out); - strcat (out, "/"); -#endif - - while ( out[i] != 0 ) - { - if ( out[i] == '\\' ) - out[i] = '/'; - i++; - } -} - - -void Q_mkdir (const char *path) -{ -#ifdef WIN32 - if (_mkdir (path) != -1) - return; -#else - if (mkdir (path, 0777) != -1) - return; -#endif - if (errno != EEXIST) - Error ("mkdir %s: %s",path, strerror(errno)); -} - -/* -============ -FileTime - -returns -1 if not present -============ -*/ -int FileTime (const char *path) -{ - struct stat buf; - - if (stat (path,&buf) == -1) - return -1; - - return buf.st_mtime; -} - - - -/* -============== -COM_Parse - -Parse a token out of a string -============== -*/ -char *COM_Parse (char *data) -{ - int c; - int len; - - len = 0; - com_token[0] = 0; - - if (!data) - return NULL; - -// skip whitespace -skipwhite: - while ( (c = *data) <= ' ') - { - if (c == 0) - { - com_eof = qtrue; - return NULL; // end of file; - } - data++; - } - -// skip // comments - if (c=='/' && data[1] == '/') - { - while (*data && *data != '\n') - data++; - goto skipwhite; - } - - -// handle quoted strings specially - if (c == '\"') - { - data++; - do - { - c = *data++; - if (c=='\"') - { - com_token[len] = 0; - return data; - } - com_token[len] = c; - len++; - } while (1); - } - -// parse single characters - if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':') - { - com_token[len] = c; - len++; - com_token[len] = 0; - return data+1; - } - -// parse a regular word - do - { - com_token[len] = c; - data++; - len++; - c = *data; - if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':') - break; - } while (c>32); - - com_token[len] = 0; - return data; -} - - -int Q_strncasecmp (const char *s1, const char *s2, int n) -{ - int c1, c2; - - do - { - c1 = *s1++; - c2 = *s2++; - - if (!n--) - return 0; // strings are equal until end point - - if (c1 != c2) - { - if (c1 >= 'a' && c1 <= 'z') - c1 -= ('a' - 'A'); - if (c2 >= 'a' && c2 <= 'z') - c2 -= ('a' - 'A'); - if (c1 != c2) - return -1; // strings not equal - } - } while (c1); - - return 0; // strings are equal -} - -int Q_stricmp (const char *s1, const char *s2) -{ - return Q_strncasecmp (s1, s2, 99999); -} - - -char *strupr (char *start) -{ - char *in; - in = start; - while (*in) - { - *in = toupper(*in); - in++; - } - return start; -} - -char *strlower (char *start) -{ - char *in; - in = start; - while (*in) - { - *in = tolower(*in); - in++; - } - return start; -} - - -/* -============================================================================= - - MISC FUNCTIONS - -============================================================================= -*/ - - -/* -================= -CheckParm - -Checks for the given parameter in the program's command line arguments -Returns the argument number (1 to argc-1) or 0 if not present -================= -*/ -int CheckParm (const char *check) -{ - int i; - - for (i = 1;i<myargc;i++) - { - if ( !Q_stricmp(check, myargv[i]) ) - return i; - } - - return 0; -} - - - -/* -================ -Q_filelength -================ -*/ -int Q_filelength (FILE *f) -{ - int pos; - int end; - - pos = ftell (f); - fseek (f, 0, SEEK_END); - end = ftell (f); - fseek (f, pos, SEEK_SET); - - return end; -} - - -FILE *SafeOpenWrite (const char *filename) -{ - FILE *f; - - f = fopen(filename, "wb"); - - if (!f) - Error ("Error opening %s: %s",filename,strerror(errno)); - - return f; -} - -FILE *SafeOpenRead (const char *filename) -{ - FILE *f; - - f = fopen(filename, "rb"); - - if (!f) - Error ("Error opening %s: %s",filename,strerror(errno)); - - return f; -} - - -void SafeRead (FILE *f, void *buffer, int count) -{ - if ( fread (buffer, 1, count, f) != (size_t)count) - Error ("File read failure"); -} - - -void SafeWrite (FILE *f, const void *buffer, int count) -{ - if (fwrite (buffer, 1, count, f) != (size_t)count) - Error ("File write failure"); -} - - -/* -============== -FileExists -============== -*/ -qboolean FileExists (const char *filename) -{ - FILE *f; - - f = fopen (filename, "r"); - if (!f) - return qfalse; - fclose (f); - return qtrue; -} - -/* -============== -LoadFile -============== -*/ -int LoadFile( const char *filename, void **bufferptr ) -{ - FILE *f; - int length; - void *buffer; - - f = SafeOpenRead (filename); - length = Q_filelength (f); - buffer = malloc (length+1); - ((char *)buffer)[length] = 0; - SafeRead (f, buffer, length); - fclose (f); - - *bufferptr = buffer; - return length; -} - - -/* -============== -LoadFileBlock -- -rounds up memory allocation to 4K boundry -- -============== -*/ -int LoadFileBlock( const char *filename, void **bufferptr ) -{ - FILE *f; - int length, nBlock, nAllocSize; - void *buffer; - - f = SafeOpenRead (filename); - length = Q_filelength (f); - nAllocSize = length; - nBlock = nAllocSize % MEM_BLOCKSIZE; - if ( nBlock > 0) { - nAllocSize += MEM_BLOCKSIZE - nBlock; - } - buffer = malloc (nAllocSize+1); - memset(buffer, 0, nAllocSize+1); - SafeRead (f, buffer, length); - fclose (f); - - *bufferptr = buffer; - return length; -} - - -/* -============== -TryLoadFile - -Allows failure -============== -*/ -int TryLoadFile (const char *filename, void **bufferptr) -{ - FILE *f; - int length; - void *buffer; - - *bufferptr = NULL; - - f = fopen (filename, "rb"); - if (!f) - return -1; - length = Q_filelength (f); - buffer = malloc (length+1); - ((char *)buffer)[length] = 0; - SafeRead (f, buffer, length); - fclose (f); - - *bufferptr = buffer; - return length; -} - - -/* -============== -SaveFile -============== -*/ -void SaveFile (const char *filename, const void *buffer, int count) -{ - FILE *f; - - f = SafeOpenWrite (filename); - SafeWrite (f, buffer, count); - fclose (f); -} - - - -void DefaultExtension (char *path, const char *extension) -{ - char *src; -// -// if path doesnt have a .EXT, append extension -// (extension should include the .) -// - src = path + strlen(path) - 1; - - while (*src != '/' && *src != '\\' && src != path) - { - if (*src == '.') - return; // it has an extension - src--; - } - - strcat (path, extension); -} - - -void DefaultPath (char *path, const char *basepath) -{ - char temp[128]; - - if (path[0] == PATHSEPERATOR) - return; // absolute path location - strcpy (temp,path); - strcpy (path,basepath); - strcat (path,temp); -} - - -void StripFilename (char *path) -{ - int length; - - length = strlen(path)-1; - while (length > 0 && path[length] != PATHSEPERATOR) - length--; - path[length] = 0; -} - -void StripExtension (char *path) -{ - int length; - - length = strlen(path)-1; - while (length > 0 && path[length] != '.') - { - length--; - if (path[length] == '/') - return; // no extension - } - if (length) - path[length] = 0; -} - - -/* -==================== -Extract file parts -==================== -*/ -// FIXME: should include the slash, otherwise -// backing to an empty path will be wrong when appending a slash -void ExtractFilePath (const char *path, char *dest) -{ - const char *src; - - src = path + strlen(path) - 1; - -// -// back up until a \ or the start -// - while (src != path && *(src-1) != '\\' && *(src-1) != '/') - src--; - - memcpy (dest, path, src-path); - dest[src-path] = 0; -} - -void ExtractFileBase (const char *path, char *dest) -{ - const char *src; - - src = path + strlen(path) - 1; - -// -// back up until a \ or the start -// - while (src != path && *(src-1) != PATHSEPERATOR) - src--; - - while (*src && *src != '.') - { - *dest++ = *src++; - } - *dest = 0; -} - -void ExtractFileExtension (const char *path, char *dest) -{ - const char *src; - - src = path + strlen(path) - 1; - -// -// back up until a . or the start -// - while (src != path && *(src-1) != '.') - src--; - if (src == path) - { - *dest = 0; // no extension - return; - } - - strcpy (dest,src); -} - - -/* -============== -ParseNum / ParseHex -============== -*/ -int ParseHex (const char *hex) -{ - const char *str; - int num; - - num = 0; - str = hex; - - while (*str) - { - num <<= 4; - if (*str >= '0' && *str <= '9') - num += *str-'0'; - else if (*str >= 'a' && *str <= 'f') - num += 10 + *str-'a'; - else if (*str >= 'A' && *str <= 'F') - num += 10 + *str-'A'; - else - Error ("Bad hex number: %s",hex); - str++; - } - - return num; -} - - -int ParseNum (const char *str) -{ - if (str[0] == '$') - return ParseHex (str+1); - if (str[0] == '0' && str[1] == 'x') - return ParseHex (str+2); - return atol (str); -} - - - -/* -============================================================================ - - BYTE ORDER FUNCTIONS - -============================================================================ -*/ - -#ifdef _SGI_SOURCE -#define __BIG_ENDIAN__ -#endif - -#ifdef __BIG_ENDIAN__ - -short LittleShort (short l) -{ - byte b1,b2; - - b1 = l&255; - b2 = (l>>8)&255; - - return (b1<<8) + b2; -} - -short BigShort (short l) -{ - return l; -} - - -int LittleLong (int l) -{ - byte b1,b2,b3,b4; - - b1 = l&255; - b2 = (l>>8)&255; - b3 = (l>>16)&255; - b4 = (l>>24)&255; - - return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; -} - -int BigLong (int l) -{ - return l; -} - - -float LittleFloat (float l) -{ - union {byte b[4]; float f;} in, out; - - in.f = l; - out.b[0] = in.b[3]; - out.b[1] = in.b[2]; - out.b[2] = in.b[1]; - out.b[3] = in.b[0]; - - return out.f; -} - -float BigFloat (float l) -{ - return l; -} - - -#else - - -short BigShort (short l) -{ - byte b1,b2; - - b1 = l&255; - b2 = (l>>8)&255; - - return (b1<<8) + b2; -} - -short LittleShort (short l) -{ - return l; -} - - -int BigLong (int l) -{ - byte b1,b2,b3,b4; - - b1 = l&255; - b2 = (l>>8)&255; - b3 = (l>>16)&255; - b4 = (l>>24)&255; - - return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; -} - -int LittleLong (int l) -{ - return l; -} - -float BigFloat (float l) -{ - union {byte b[4]; float f;} in, out; - - in.f = l; - out.b[0] = in.b[3]; - out.b[1] = in.b[2]; - out.b[2] = in.b[1]; - out.b[3] = in.b[0]; - - return out.f; -} - -float LittleFloat (float l) -{ - return l; -} - - -#endif - - -//======================================================= - - -// FIXME: byte swap? - -// this is a 16 bit, non-reflected CRC using the polynomial 0x1021 -// and the initial and final xor values shown below... in other words, the -// CCITT standard CRC used by XMODEM - -#define CRC_INIT_VALUE 0xffff -#define CRC_XOR_VALUE 0x0000 - -static unsigned short crctable[256] = -{ - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, - 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, - 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, - 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, - 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, - 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, - 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, - 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, - 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, - 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, - 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, - 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, - 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, - 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, - 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, - 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, - 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, - 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, - 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, - 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, - 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, - 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, - 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 -}; - -void CRC_Init(unsigned short *crcvalue) -{ - *crcvalue = CRC_INIT_VALUE; -} - -void CRC_ProcessByte(unsigned short *crcvalue, byte data) -{ - *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data]; -} - -unsigned short CRC_Value(unsigned short crcvalue) -{ - return crcvalue ^ CRC_XOR_VALUE; -} -//============================================================================= - -/* -============ -CreatePath -============ -*/ -void CreatePath (const char *path) -{ - const char *ofs; - char c; - char dir[1024]; - -#ifdef _WIN32 - int olddrive = -1; - - if ( path[1] == ':' ) - { - olddrive = _getdrive(); - _chdrive( toupper( path[0] ) - 'A' + 1 ); - } -#endif - - if (path[1] == ':') - path += 2; - - for (ofs = path+1 ; *ofs ; ofs++) - { - c = *ofs; - if (c == '/' || c == '\\') - { // create the directory - memcpy( dir, path, ofs - path ); - dir[ ofs - path ] = 0; - Q_mkdir( dir ); - } - } - -#ifdef _WIN32 - if ( olddrive != -1 ) - { - _chdrive( olddrive ); - } -#endif -} - - -/* -============ -QCopyFile - - Used to archive source files -============ -*/ -void QCopyFile (const char *from, const char *to) -{ - void *buffer; - int length; - - length = LoadFile (from, &buffer); - CreatePath (to); - SaveFile (to, buffer, length); - free (buffer); -} diff --git a/common/cmdlib.h b/common/cmdlib.h deleted file mode 100644 index 0d7dfc3..0000000 --- a/common/cmdlib.h +++ /dev/null @@ -1,160 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// cmdlib.h - -#ifndef __CMDLIB__ -#define __CMDLIB__ - -#ifdef _WIN32 -#pragma warning(disable : 4244) // MIPS -#pragma warning(disable : 4136) // X86 -#pragma warning(disable : 4051) // ALPHA - -#pragma warning(disable : 4018) // signed/unsigned mismatch -#pragma warning(disable : 4305) // truncate from double to float - -#pragma check_stack(off) - -#endif - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <errno.h> -#include <ctype.h> -#include <time.h> -#include <stdarg.h> - -#ifdef _WIN32 - -#pragma intrinsic( memset, memcpy ) - -#endif - -#ifndef __BYTEBOOL__ -#define __BYTEBOOL__ -typedef enum { qfalse, qtrue } qboolean; -typedef unsigned char byte; -#endif - -#define MAX_OS_PATH 1024 -#define MEM_BLOCKSIZE 4096 - -// the dec offsetof macro doesnt work very well... -#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier) - - -// set these before calling CheckParm -extern int myargc; -extern char **myargv; - -char *strupr (char *in); -char *strlower (char *in); -int Q_strncasecmp( const char *s1, const char *s2, int n ); -int Q_stricmp( const char *s1, const char *s2 ); -void Q_getwd( char *out ); - -int Q_filelength (FILE *f); -int FileTime( const char *path ); - -void Q_mkdir( const char *path ); - -extern char qdir[1024]; -extern char gamedir[1024]; -extern char writedir[1024]; -void SetQdirFromPath( const char *path ); -char *ExpandArg( const char *path ); // from cmd line -char *ExpandPath( const char *path ); // from scripts -char *ExpandGamePath (const char *path); -char *ExpandPathAndArchive( const char *path ); - - -double I_FloatTime( void ); - -void Error( const char *error, ... ); -int CheckParm( const char *check ); - -FILE *SafeOpenWrite( const char *filename ); -FILE *SafeOpenRead( const char *filename ); -void SafeRead (FILE *f, void *buffer, int count); -void SafeWrite (FILE *f, const void *buffer, int count); - -int LoadFile( const char *filename, void **bufferptr ); -int LoadFileBlock( const char *filename, void **bufferptr ); -int TryLoadFile( const char *filename, void **bufferptr ); -void SaveFile( const char *filename, const void *buffer, int count ); -qboolean FileExists( const char *filename ); - -void DefaultExtension( char *path, const char *extension ); -void DefaultPath( char *path, const char *basepath ); -void StripFilename( char *path ); -void StripExtension( char *path ); - -void ExtractFilePath( const char *path, char *dest ); -void ExtractFileBase( const char *path, char *dest ); -void ExtractFileExtension( const char *path, char *dest ); - -int ParseNum (const char *str); - -short BigShort (short l); -short LittleShort (short l); -int BigLong (int l); -int LittleLong (int l); -float BigFloat (float l); -float LittleFloat (float l); - - -char *COM_Parse (char *data); - -extern char com_token[1024]; -extern qboolean com_eof; - -char *copystring(const char *s); - - -void CRC_Init(unsigned short *crcvalue); -void CRC_ProcessByte(unsigned short *crcvalue, byte data); -unsigned short CRC_Value(unsigned short crcvalue); - -void CreatePath( const char *path ); -void QCopyFile( const char *from, const char *to ); - -extern qboolean archive; -extern char archivedir[1024]; - - -extern qboolean verbose; -void qprintf( const char *format, ... ); -void _printf( const char *format, ... ); - -void ExpandWildcards( int *argc, char ***argv ); - - -// for compression routines -typedef struct -{ - void *data; - int count, width, height; -} cblock_t; - - -#endif diff --git a/common/imagelib.c b/common/imagelib.c deleted file mode 100644 index b12b34c..0000000 --- a/common/imagelib.c +++ /dev/null @@ -1,1164 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// imagelib.c - -#include "cmdlib.h" -#include "imagelib.h" - - -int fgetLittleShort (FILE *f) -{ - byte b1, b2; - - b1 = fgetc(f); - b2 = fgetc(f); - - return (short)(b1 + b2*256); -} - -int fgetLittleLong (FILE *f) -{ - byte b1, b2, b3, b4; - - b1 = fgetc(f); - b2 = fgetc(f); - b3 = fgetc(f); - b4 = fgetc(f); - - return b1 + (b2<<8) + (b3<<16) + (b4<<24); -} - - - -/* -============================================================================ - - LBM STUFF - -============================================================================ -*/ - - -typedef unsigned char UBYTE; -//conflicts with windows typedef short WORD; -typedef unsigned short UWORD; -typedef long LONG; - -typedef enum -{ - ms_none, - ms_mask, - ms_transcolor, - ms_lasso -} mask_t; - -typedef enum -{ - cm_none, - cm_rle1 -} compress_t; - -typedef struct -{ - UWORD w,h; - short x,y; - UBYTE nPlanes; - UBYTE masking; - UBYTE compression; - UBYTE pad1; - UWORD transparentColor; - UBYTE xAspect,yAspect; - short pageWidth,pageHeight; -} bmhd_t; - -extern bmhd_t bmhd; // will be in native byte order - - - -#define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24)) -#define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24)) -#define PBMID ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24)) -#define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24)) -#define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24)) -#define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24)) - - -bmhd_t bmhd; - -int Align (int l) -{ - if (l&1) - return l+1; - return l; -} - - - -/* -================ -LBMRLEdecompress - -Source must be evenly aligned! -================ -*/ -byte *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth) -{ - int count; - byte b,rept; - - count = 0; - - do - { - rept = *source++; - - if (rept > 0x80) - { - rept = (rept^0xff)+2; - b = *source++; - memset(unpacked,b,rept); - unpacked += rept; - } - else if (rept < 0x80) - { - rept++; - memcpy(unpacked,source,rept); - unpacked += rept; - source += rept; - } - else - rept = 0; // rept of 0x80 is NOP - - count += rept; - - } while (count<bpwidth); - - if (count>bpwidth) - Error ("Decompression exceeded width!\n"); - - - return source; -} - - -/* -================= -LoadLBM -================= -*/ -void LoadLBM (const char *filename, byte **picture, byte **palette) -{ - byte *LBMbuffer, *picbuffer, *cmapbuffer; - int y; - byte *LBM_P, *LBMEND_P; - byte *pic_p; - byte *body_p; - - int formtype,formlength; - int chunktype,chunklength; - -// qiet compiler warnings - picbuffer = NULL; - cmapbuffer = NULL; - -// -// load the LBM -// - LoadFile (filename, (void **)&LBMbuffer); - -// -// parse the LBM header -// - LBM_P = LBMbuffer; - if ( *(int *)LBMbuffer != LittleLong(FORMID) ) - Error ("No FORM ID at start of file!\n"); - - LBM_P += 4; - formlength = BigLong( *(int *)LBM_P ); - LBM_P += 4; - LBMEND_P = LBM_P + Align(formlength); - - formtype = LittleLong(*(int *)LBM_P); - - if (formtype != ILBMID && formtype != PBMID) - Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff - ,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff); - - LBM_P += 4; - -// -// parse chunks -// - - while (LBM_P < LBMEND_P) - { - chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24); - LBM_P += 4; - chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24); - LBM_P += 4; - - switch ( chunktype ) - { - case BMHDID: - memcpy (&bmhd,LBM_P,sizeof(bmhd)); - bmhd.w = BigShort(bmhd.w); - bmhd.h = BigShort(bmhd.h); - bmhd.x = BigShort(bmhd.x); - bmhd.y = BigShort(bmhd.y); - bmhd.pageWidth = BigShort(bmhd.pageWidth); - bmhd.pageHeight = BigShort(bmhd.pageHeight); - break; - - case CMAPID: - cmapbuffer = malloc (768); - memset (cmapbuffer, 0, 768); - memcpy (cmapbuffer, LBM_P, chunklength); - break; - - case BODYID: - body_p = LBM_P; - - pic_p = picbuffer = malloc (bmhd.w*bmhd.h); - if (formtype == PBMID) - { - // - // unpack PBM - // - for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w) - { - if (bmhd.compression == cm_rle1) - body_p = LBMRLEDecompress ((byte *)body_p - , pic_p , bmhd.w); - else if (bmhd.compression == cm_none) - { - memcpy (pic_p,body_p,bmhd.w); - body_p += Align(bmhd.w); - } - } - - } - else - { - // - // unpack ILBM - // - Error ("%s is an interlaced LBM, not packed", filename); - } - break; - } - - LBM_P += Align(chunklength); - } - - free (LBMbuffer); - - *picture = picbuffer; - - if (palette) - *palette = cmapbuffer; -} - - -/* -============================================================================ - - WRITE LBM - -============================================================================ -*/ - -/* -============== -WriteLBMfile -============== -*/ -void WriteLBMfile (const char *filename, byte *data, - int width, int height, byte *palette) -{ - byte *lbm, *lbmptr; - int *formlength, *bmhdlength, *cmaplength, *bodylength; - int length; - bmhd_t basebmhd; - - lbm = lbmptr = malloc (width*height+1000); - -// -// start FORM -// - *lbmptr++ = 'F'; - *lbmptr++ = 'O'; - *lbmptr++ = 'R'; - *lbmptr++ = 'M'; - - formlength = (int*)lbmptr; - lbmptr+=4; // leave space for length - - *lbmptr++ = 'P'; - *lbmptr++ = 'B'; - *lbmptr++ = 'M'; - *lbmptr++ = ' '; - -// -// write BMHD -// - *lbmptr++ = 'B'; - *lbmptr++ = 'M'; - *lbmptr++ = 'H'; - *lbmptr++ = 'D'; - - bmhdlength = (int *)lbmptr; - lbmptr+=4; // leave space for length - - memset (&basebmhd,0,sizeof(basebmhd)); - basebmhd.w = BigShort((short)width); - basebmhd.h = BigShort((short)height); - basebmhd.nPlanes = BigShort(8); - basebmhd.xAspect = BigShort(5); - basebmhd.yAspect = BigShort(6); - basebmhd.pageWidth = BigShort((short)width); - basebmhd.pageHeight = BigShort((short)height); - - memcpy (lbmptr,&basebmhd,sizeof(basebmhd)); - lbmptr += sizeof(basebmhd); - - length = lbmptr-(byte *)bmhdlength-4; - *bmhdlength = BigLong(length); - if (length&1) - *lbmptr++ = 0; // pad chunk to even offset - -// -// write CMAP -// - *lbmptr++ = 'C'; - *lbmptr++ = 'M'; - *lbmptr++ = 'A'; - *lbmptr++ = 'P'; - - cmaplength = (int *)lbmptr; - lbmptr+=4; // leave space for length - - memcpy (lbmptr,palette,768); - lbmptr += 768; - - length = lbmptr-(byte *)cmaplength-4; - *cmaplength = BigLong(length); - if (length&1) - *lbmptr++ = 0; // pad chunk to even offset - -// -// write BODY -// - *lbmptr++ = 'B'; - *lbmptr++ = 'O'; - *lbmptr++ = 'D'; - *lbmptr++ = 'Y'; - - bodylength = (int *)lbmptr; - lbmptr+=4; // leave space for length - - memcpy (lbmptr,data,width*height); - lbmptr += width*height; - - length = lbmptr-(byte *)bodylength-4; - *bodylength = BigLong(length); - if (length&1) - *lbmptr++ = 0; // pad chunk to even offset - -// -// done -// - length = lbmptr-(byte *)formlength-4; - *formlength = BigLong(length); - if (length&1) - *lbmptr++ = 0; // pad chunk to even offset - -// -// write output file -// - SaveFile (filename, lbm, lbmptr-lbm); - free (lbm); -} - - -/* -============================================================================ - -LOAD PCX - -============================================================================ -*/ - -typedef struct -{ - char manufacturer; - char version; - char encoding; - char bits_per_pixel; - unsigned short xmin,ymin,xmax,ymax; - unsigned short hres,vres; - unsigned char palette[48]; - char reserved; - char color_planes; - unsigned short bytes_per_line; - unsigned short palette_type; - char filler[58]; - unsigned char data; // unbounded -} pcx_t; - - -/* -============== -LoadPCX -============== -*/ -void LoadPCX (const char *filename, byte **pic, byte **palette, int *width, int *height) -{ - byte *raw; - pcx_t *pcx; - int x, y; - int len; - int dataByte, runLength; - byte *out, *pix; - - // - // load the file - // - len = LoadFile (filename, (void **)&raw); - - // - // parse the PCX file - // - pcx = (pcx_t *)raw; - raw = &pcx->data; - - pcx->xmin = LittleShort(pcx->xmin); - pcx->ymin = LittleShort(pcx->ymin); - pcx->xmax = LittleShort(pcx->xmax); - pcx->ymax = LittleShort(pcx->ymax); - pcx->hres = LittleShort(pcx->hres); - pcx->vres = LittleShort(pcx->vres); - pcx->bytes_per_line = LittleShort(pcx->bytes_per_line); - pcx->palette_type = LittleShort(pcx->palette_type); - - if (pcx->manufacturer != 0x0a - || pcx->version != 5 - || pcx->encoding != 1 - || pcx->bits_per_pixel != 8 - || pcx->xmax >= 640 - || pcx->ymax >= 480) - Error ("Bad pcx file %s", filename); - - if (palette) - { - *palette = malloc(768); - memcpy (*palette, (byte *)pcx + len - 768, 768); - } - - if (width) - *width = pcx->xmax+1; - if (height) - *height = pcx->ymax+1; - - if (!pic) - return; - - out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) ); - if (!out) - Error ("Skin_Cache: couldn't allocate"); - - *pic = out; - - pix = out; - - for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1) - { - for (x=0 ; x<=pcx->xmax ; ) - { - dataByte = *raw++; - - if((dataByte & 0xC0) == 0xC0) - { - runLength = dataByte & 0x3F; - dataByte = *raw++; - } - else - runLength = 1; - - // FIXME: this shouldn't happen, but it does. Are we decoding the file wrong? - // Truncate runLength so we don't overrun the end of the buffer - if ( ( y == pcx->ymax ) && ( x + runLength > pcx->xmax + 1 ) ) { - runLength = pcx->xmax - x + 1; - } - - while(runLength-- > 0) - pix[x++] = dataByte; - } - - } - - if ( raw - (byte *)pcx > len) - Error ("PCX file %s was malformed", filename); - - free (pcx); -} - -/* -============== -WritePCXfile -============== -*/ -void WritePCXfile (const char *filename, byte *data, - int width, int height, byte *palette) -{ - int i, j, length; - pcx_t *pcx; - byte *pack; - - pcx = malloc (width*height*2+1000); - memset (pcx, 0, sizeof(*pcx)); - - pcx->manufacturer = 0x0a; // PCX id - pcx->version = 5; // 256 color - pcx->encoding = 1; // uncompressed - pcx->bits_per_pixel = 8; // 256 color - pcx->xmin = 0; - pcx->ymin = 0; - pcx->xmax = LittleShort((short)(width-1)); - pcx->ymax = LittleShort((short)(height-1)); - pcx->hres = LittleShort((short)width); - pcx->vres = LittleShort((short)height); - pcx->color_planes = 1; // chunky image - pcx->bytes_per_line = LittleShort((short)width); - pcx->palette_type = LittleShort(1); // not a grey scale - - // pack the image - pack = &pcx->data; - - for (i=0 ; i<height ; i++) - { - for (j=0 ; j<width ; j++) - { - if ( (*data & 0xc0) != 0xc0) - *pack++ = *data++; - else - { - *pack++ = 0xc1; - *pack++ = *data++; - } - } - } - - // write the palette - *pack++ = 0x0c; // palette ID byte - for (i=0 ; i<768 ; i++) - *pack++ = *palette++; - -// write output file - length = pack - (byte *)pcx; - SaveFile (filename, pcx, length); - - free (pcx); -} - -/* -============================================================================ - -LOAD BMP - -============================================================================ -*/ - - -/* - -// we can't just use these structures, because -// compiler structure alignment will not be portable -// on this unaligned stuff - -typedef struct tagBITMAPFILEHEADER { // bmfh - WORD bfType; // BM - DWORD bfSize; - WORD bfReserved1; - WORD bfReserved2; - DWORD bfOffBits; -} BITMAPFILEHEADER; - -typedef struct tagBITMAPINFOHEADER{ // bmih - DWORD biSize; - LONG biWidth; - LONG biHeight; - WORD biPlanes; - WORD biBitCount - DWORD biCompression; - DWORD biSizeImage; - LONG biXPelsPerMeter; - LONG biYPelsPerMeter; - DWORD biClrUsed; - DWORD biClrImportant; -} BITMAPINFOHEADER; - -typedef struct tagBITMAPINFO { // bmi - BITMAPINFOHEADER bmiHeader; - RGBQUAD bmiColors[1]; -} BITMAPINFO; - -typedef struct tagBITMAPCOREHEADER { // bmch - DWORD bcSize; - WORD bcWidth; - WORD bcHeight; - WORD bcPlanes; - WORD bcBitCount; -} BITMAPCOREHEADER; - -typedef struct _BITMAPCOREINFO { // bmci - BITMAPCOREHEADER bmciHeader; - RGBTRIPLE bmciColors[1]; -} BITMAPCOREINFO; - -*/ - -/* -============== -LoadBMP -============== -*/ -void LoadBMP (const char *filename, byte **pic, byte **palette, int *width, int *height) -{ - byte *out; - FILE *fin; - int i; - int bfSize; - int bfOffBits; - int structSize; - int bcWidth; - int bcHeight; - int bcPlanes; - int bcBitCount; - byte bcPalette[1024]; - qboolean flipped; - - fin = fopen (filename, "rb"); - if (!fin) { - Error ("Couldn't read %s", filename); - } - - i = fgetLittleShort (fin); - if (i != 'B' + ('M'<<8) ) { - Error ("%s is not a bmp file", filename); - } - - bfSize = fgetLittleLong (fin); - fgetLittleShort(fin); - fgetLittleShort(fin); - bfOffBits = fgetLittleLong (fin); - - // the size will tell us if it is a - // bitmapinfo or a bitmapcore - structSize = fgetLittleLong (fin); - if (structSize == 40) { - // bitmapinfo - bcWidth = fgetLittleLong(fin); - bcHeight= fgetLittleLong(fin); - bcPlanes = fgetLittleShort(fin); - bcBitCount = fgetLittleShort(fin); - - fseek (fin, 24, SEEK_CUR); - - if (palette) { - fread (bcPalette, 1, 1024, fin); - *palette = malloc(768); - - for (i = 0 ; i < 256 ; i++) { - (*palette)[i * 3 + 0] = bcPalette[i * 4 + 2]; - (*palette)[i * 3 + 1] = bcPalette[i * 4 + 1]; - (*palette)[i * 3 + 2] = bcPalette[i * 4 + 0]; - } - } - } else if (structSize == 12) { - // bitmapcore - bcWidth = fgetLittleShort(fin); - bcHeight= fgetLittleShort(fin); - bcPlanes = fgetLittleShort(fin); - bcBitCount = fgetLittleShort(fin); - - if (palette) { - fread (bcPalette, 1, 768, fin); - *palette = malloc(768); - - for (i = 0 ; i < 256 ; i++) { - (*palette)[i * 3 + 0] = bcPalette[i * 3 + 2]; - (*palette)[i * 3 + 1] = bcPalette[i * 3 + 1]; - (*palette)[i * 3 + 2] = bcPalette[i * 3 + 0]; - } - } - } else { - Error ("%s had strange struct size", filename); - } - - if (bcPlanes != 1) { - Error ("%s was not a single plane image", filename); - } - - if (bcBitCount != 8) { - Error ("%s was not an 8 bit image", filename); - } - - if (bcHeight < 0) { - bcHeight = -bcHeight; - flipped = qtrue; - } else { - flipped = qfalse; - } - - if (width) - *width = bcWidth; - if (height) - *height = bcHeight; - - if (!pic) { - fclose (fin); - return; - } - - out = malloc ( bcWidth * bcHeight ); - *pic = out; - fseek (fin, bfOffBits, SEEK_SET); - - if (flipped) { - for (i = 0 ; i < bcHeight ; i++) { - fread (out + bcWidth * (bcHeight - 1 - i), 1, bcWidth, fin); - } - } else { - fread (out, 1, bcWidth*bcHeight, fin); - } - - fclose (fin); -} - - -/* -============================================================================ - -LOAD IMAGE - -============================================================================ -*/ - -/* -============== -Load256Image - -Will load either an lbm or pcx, depending on extension. -Any of the return pointers can be NULL if you don't want them. -============== -*/ -void Load256Image (const char *name, byte **pixels, byte **palette, - int *width, int *height) -{ - char ext[128]; - - ExtractFileExtension (name, ext); - if (!Q_stricmp (ext, "lbm")) - { - LoadLBM (name, pixels, palette); - if (width) - *width = bmhd.w; - if (height) - *height = bmhd.h; - } - else if (!Q_stricmp (ext, "pcx")) - { - LoadPCX (name, pixels, palette, width, height); - } - else if (!Q_stricmp (ext, "bmp")) - { - LoadBMP (name, pixels, palette, width, height); - } - else - Error ("%s doesn't have a known image extension", name); -} - - -/* -============== -Save256Image - -Will save either an lbm or pcx, depending on extension. -============== -*/ -void Save256Image (const char *name, byte *pixels, byte *palette, - int width, int height) -{ - char ext[128]; - - ExtractFileExtension (name, ext); - if (!Q_stricmp (ext, "lbm")) - { - WriteLBMfile (name, pixels, width, height, palette); - } - else if (!Q_stricmp (ext, "pcx")) - { - WritePCXfile (name, pixels, width, height, palette); - } - else - Error ("%s doesn't have a known image extension", name); -} - - - - -/* -============================================================================ - -TARGA IMAGE - -============================================================================ -*/ - -typedef struct _TargaHeader { - unsigned char id_length, colormap_type, image_type; - unsigned short colormap_index, colormap_length; - unsigned char colormap_size; - unsigned short x_origin, y_origin, width, height; - unsigned char pixel_size, attributes; -} TargaHeader; - -/* -============= -LoadTGABuffer -============= -*/ -void LoadTGABuffer ( byte *buffer, byte **pic, int *width, int *height) -{ - int columns, rows, numPixels; - byte *pixbuf; - int row, column; - byte *buf_p; - TargaHeader targa_header; - byte *targa_rgba; - - *pic = NULL; - - buf_p = buffer; - - targa_header.id_length = *buf_p++; - targa_header.colormap_type = *buf_p++; - targa_header.image_type = *buf_p++; - - targa_header.colormap_index = LittleShort ( *(short *)buf_p ); - buf_p += 2; - targa_header.colormap_length = LittleShort ( *(short *)buf_p ); - buf_p += 2; - targa_header.colormap_size = *buf_p++; - targa_header.x_origin = LittleShort ( *(short *)buf_p ); - buf_p += 2; - targa_header.y_origin = LittleShort ( *(short *)buf_p ); - buf_p += 2; - targa_header.width = LittleShort ( *(short *)buf_p ); - buf_p += 2; - targa_header.height = LittleShort ( *(short *)buf_p ); - buf_p += 2; - targa_header.pixel_size = *buf_p++; - targa_header.attributes = *buf_p++; - - if (targa_header.image_type!=2 - && targa_header.image_type!=10 - && targa_header.image_type != 3 ) - { - Error("LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n"); - } - - if ( targa_header.colormap_type != 0 ) - { - Error("LoadTGA: colormaps not supported\n" ); - } - - if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 ) - { - Error("LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n"); - } - - columns = targa_header.width; - rows = targa_header.height; - numPixels = columns * rows; - - if (width) - *width = columns; - if (height) - *height = rows; - - targa_rgba = malloc (numPixels*4); - *pic = targa_rgba; - - if (targa_header.id_length != 0) - buf_p += targa_header.id_length; // skip TARGA image comment - - if ( targa_header.image_type==2 || targa_header.image_type == 3 ) - { - // Uncompressed RGB or gray scale image - for(row=rows-1; row>=0; row--) - { - pixbuf = targa_rgba + row*columns*4; - for(column=0; column<columns; column++) - { - unsigned char red,green,blue,alphabyte; - switch (targa_header.pixel_size) - { - - case 8: - blue = *buf_p++; - green = blue; - red = blue; - *pixbuf++ = red; - *pixbuf++ = green; - *pixbuf++ = blue; - *pixbuf++ = 255; - break; - - case 24: - blue = *buf_p++; - green = *buf_p++; - red = *buf_p++; - *pixbuf++ = red; - *pixbuf++ = green; - *pixbuf++ = blue; - *pixbuf++ = 255; - break; - case 32: - blue = *buf_p++; - green = *buf_p++; - red = *buf_p++; - alphabyte = *buf_p++; - *pixbuf++ = red; - *pixbuf++ = green; - *pixbuf++ = blue; - *pixbuf++ = alphabyte; - break; - default: - //Error("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name ); - break; - } - } - } - } - else if (targa_header.image_type==10) { // Runlength encoded RGB images - unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j; - - red = 0; - green = 0; - blue = 0; - alphabyte = 0xff; - - for(row=rows-1; row>=0; row--) { - pixbuf = targa_rgba + row*columns*4; - for(column=0; column<columns; ) { - packetHeader= *buf_p++; - packetSize = 1 + (packetHeader & 0x7f); - if (packetHeader & 0x80) { // run-length packet - switch (targa_header.pixel_size) { - case 24: - blue = *buf_p++; - green = *buf_p++; - red = *buf_p++; - alphabyte = 255; - break; - case 32: - blue = *buf_p++; - green = *buf_p++; - red = *buf_p++; - alphabyte = *buf_p++; - break; - default: - //Error("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name ); - break; - } - - for(j=0;j<packetSize;j++) { - *pixbuf++=red; - *pixbuf++=green; - *pixbuf++=blue; - *pixbuf++=alphabyte; - column++; - if (column==columns) { // run spans across rows - column=0; - if (row>0) - row--; - else - goto breakOut; - pixbuf = targa_rgba + row*columns*4; - } - } - } - else { // non run-length packet - for(j=0;j<packetSize;j++) { - switch (targa_header.pixel_size) { - case 24: - blue = *buf_p++; - green = *buf_p++; - red = *buf_p++; - *pixbuf++ = red; - *pixbuf++ = green; - *pixbuf++ = blue; - *pixbuf++ = 255; - break; - case 32: - blue = *buf_p++; - green = *buf_p++; - red = *buf_p++; - alphabyte = *buf_p++; - *pixbuf++ = red; - *pixbuf++ = green; - *pixbuf++ = blue; - *pixbuf++ = alphabyte; - break; - default: - //Sys_Printf("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name ); - break; - } - column++; - if (column==columns) { // pixel packet run spans across rows - column=0; - if (row>0) - row--; - else - goto breakOut; - pixbuf = targa_rgba + row*columns*4; - } - } - } - } - breakOut:; - } - } - - //free(buffer); -} - - - -/* -============= -LoadTGA -============= -*/ -void LoadTGA (const char *name, byte **pixels, int *width, int *height) -{ - byte *buffer; - int nLen; - // - // load the file - // - nLen = LoadFile ( ( char * ) name, (void **)&buffer); - if (nLen == -1) - { - Error ("Couldn't read %s", name); - } - - LoadTGABuffer(buffer, pixels, width, height); - -} - - -/* -================ -WriteTGA -================ -*/ -void WriteTGA (const char *filename, byte *data, int width, int height) { - byte *buffer; - int i; - int c; - FILE *f; - - buffer = malloc(width*height*4 + 18); - memset (buffer, 0, 18); - buffer[2] = 2; // uncompressed type - buffer[12] = width&255; - buffer[13] = width>>8; - buffer[14] = height&255; - buffer[15] = height>>8; - buffer[16] = 32; // pixel size - - // swap rgb to bgr - c = 18 + width * height * 4; - for (i=18 ; i<c ; i+=4) - { - buffer[i] = data[i-18+2]; // blue - buffer[i+1] = data[i-18+1]; // green - buffer[i+2] = data[i-18+0]; // red - buffer[i+3] = data[i-18+3]; // alpha - } - - f = fopen (filename, "wb"); - fwrite (buffer, 1, c, f); - fclose (f); - - free (buffer); -} - -/* -============================================================================ - -LOAD32BITIMAGE - -============================================================================ -*/ - -/* -============== -Load32BitImage - -Any of the return pointers can be NULL if you don't want them. -============== -*/ -void Load32BitImage (const char *name, unsigned **pixels, int *width, int *height) -{ - char ext[128]; - byte *palette; - byte *pixels8; - byte *pixels32; - int size; - int i; - int v; - - ExtractFileExtension (name, ext); - if (!Q_stricmp (ext, "tga")) { - LoadTGA (name, (byte **)pixels, width, height); - } else { - Load256Image (name, &pixels8, &palette, width, height); - if (!pixels) { - return; - } - size = *width * *height; - pixels32 = malloc(size * 4); - *pixels = (unsigned *)pixels32; - for (i = 0 ; i < size ; i++) { - v = pixels8[i]; - pixels32[i*4 + 0] = palette[ v * 3 + 0 ]; - pixels32[i*4 + 1] = palette[ v * 3 + 1 ]; - pixels32[i*4 + 2] = palette[ v * 3 + 2 ]; - pixels32[i*4 + 3] = 0xff; - } - } -} - - diff --git a/common/imagelib.h b/common/imagelib.h deleted file mode 100644 index 63aeb65..0000000 --- a/common/imagelib.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// piclib.h - - -void LoadLBM (const char *filename, byte **picture, byte **palette); -void WriteLBMfile (const char *filename, byte *data, int width, int height - , byte *palette); -void LoadPCX (const char *filename, byte **picture, byte **palette, int *width, int *height); -void WritePCXfile (const char *filename, byte *data, int width, int height - , byte *palette); - -// loads / saves either lbm or pcx, depending on extension -void Load256Image (const char *name, byte **pixels, byte **palette, - int *width, int *height); -void Save256Image (const char *name, byte *pixels, byte *palette, - int width, int height); - - -void LoadTGA (const char *filename, byte **pixels, int *width, int *height); -void LoadTGABuffer ( byte *buffer, byte **pic, int *width, int *height); -void WriteTGA (const char *filename, byte *data, int width, int height); - -void Load32BitImage (const char *name, unsigned **pixels, int *width, int *height); - diff --git a/common/l3dslib.c b/common/l3dslib.c deleted file mode 100644 index 1499e75..0000000 --- a/common/l3dslib.c +++ /dev/null @@ -1,300 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// -// l3dslib.c: library for loading triangles from an Alias triangle file -// - -#include <stdio.h> -#include "cmdlib.h" -#include "mathlib.h" -#include "trilib.h" -#include "l3dslib.h" - -#define MAIN3DS 0x4D4D -#define EDIT3DS 0x3D3D // this is the start of the editor config -#define EDIT_OBJECT 0x4000 -#define OBJ_TRIMESH 0x4100 -#define TRI_VERTEXL 0x4110 -#define TRI_FACEL1 0x4120 - -#define MAXVERTS 2000 - -typedef struct { - int v[4]; -} tri; - -float fverts[MAXVERTS][3]; -tri tris[MAXTRIANGLES]; - -int bytesread, level, numtris, totaltris; -int vertsfound, trisfound; - -triangle_t *ptri; - - -// Alias stores triangles as 3 explicit vertices in .tri files, so even though we -// start out with a vertex pool and vertex indices for triangles, we have to convert -// to raw, explicit triangles -void StoreAliasTriangles (void) -{ - int i, j, k; - - if ((totaltris + numtris) > MAXTRIANGLES) - Error ("Error: Too many triangles"); - - for (i=0; i<numtris ; i++) - { - for (j=0 ; j<3 ; j++) - { - for (k=0 ; k<3 ; k++) - { - ptri[i+totaltris].verts[j][k] = fverts[tris[i].v[j]][k]; - } - } - } - - totaltris += numtris; - numtris = 0; - vertsfound = 0; - trisfound = 0; -} - - -int ParseVertexL (FILE *input) -{ - int i, j, startbytesread, numverts; - unsigned short tshort; - - if (vertsfound) - Error ("Error: Multiple vertex chunks"); - - vertsfound = 1; - startbytesread = bytesread; - - if (feof(input)) - Error ("Error: unexpected end of file"); - - fread(&tshort, sizeof(tshort), 1, input); - bytesread += sizeof(tshort); - numverts = (int)tshort; - - if (numverts > MAXVERTS) - Error ("Error: Too many vertices"); - - for (i=0 ; i<numverts ; i++) - { - for (j=0 ; j<3 ; j++) - { - if (feof(input)) - Error ("Error: unexpected end of file"); - - fread(&fverts[i][j], sizeof(float), 1, input); - bytesread += sizeof(float); - } - } - - if (vertsfound && trisfound) - StoreAliasTriangles (); - - return bytesread - startbytesread; -} - - -int ParseFaceL1 (FILE *input) -{ - - int i, j, startbytesread; - unsigned short tshort; - - if (trisfound) - Error ("Error: Multiple face chunks"); - - trisfound = 1; - startbytesread = bytesread; - - if (feof(input)) - Error ("Error: unexpected end of file"); - - fread(&tshort, sizeof(tshort), 1, input); - bytesread += sizeof(tshort); - numtris = (int)tshort; - - if (numtris > MAXTRIANGLES) - Error ("Error: Too many triangles"); - - for (i=0 ; i<numtris ; i++) - { - for (j=0 ; j<4 ; j++) - { - if (feof(input)) - Error ("Error: unexpected end of file"); - - fread(&tshort, sizeof(tshort), 1, input); - bytesread += sizeof(tshort); - tris[i].v[j] = (int)tshort; - } - } - - if (vertsfound && trisfound) - StoreAliasTriangles (); - - return bytesread - startbytesread; -} - - -int ParseChunk (FILE *input) -{ -#define BLOCK_SIZE 4096 - char temp[BLOCK_SIZE]; - unsigned short type; - int i, length, w, t, retval; - - level++; - retval = 0; - -// chunk type - if (feof(input)) - Error ("Error: unexpected end of file"); - - fread(&type, sizeof(type), 1, input); - bytesread += sizeof(type); - -// chunk length - if (feof(input)) - Error ("Error: unexpected end of file"); - - fread (&length, sizeof(length), 1, input); - bytesread += sizeof(length); - w = length - 6; - -// process chunk if we care about it, otherwise skip it - switch (type) - { - case TRI_VERTEXL: - w -= ParseVertexL (input); - goto ParseSubchunk; - - case TRI_FACEL1: - w -= ParseFaceL1 (input); - goto ParseSubchunk; - - case EDIT_OBJECT: - // read the name - i = 0; - - do - { - if (feof(input)) - Error ("Error: unexpected end of file"); - - fread (&temp[i], 1, 1, input); - i++; - w--; - bytesread++; - } while (temp[i-1]); - - case MAIN3DS: - case OBJ_TRIMESH: - case EDIT3DS: - // parse through subchunks -ParseSubchunk: - while (w > 0) - { - w -= ParseChunk (input); - } - - retval = length; - goto Done; - - default: - // skip other chunks - while (w > 0) - { - t = w; - - if (t > BLOCK_SIZE) - t = BLOCK_SIZE; - - if (feof(input)) - Error ("Error: unexpected end of file"); - - fread (&temp, t, 1, input); - bytesread += t; - - w -= t; - } - - retval = length; - goto Done; - } - -Done: - level--; - return retval; -} - - -void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles) -{ - FILE *input; - short int tshort; - - bytesread = 0; - level = 0; - numtris = 0; - totaltris = 0; - vertsfound = 0; - trisfound = 0; - - if ((input = fopen(filename, "rb")) == 0) { - fprintf(stderr,"reader: could not open file '%s'\n", filename); - exit(0); - } - - fread(&tshort, sizeof(tshort), 1, input); - -// should only be MAIN3DS, but some files seem to start with EDIT3DS, with -// no MAIN3DS - if ((tshort != MAIN3DS) && (tshort != EDIT3DS)) { - fprintf(stderr,"File is not a 3DS file.\n"); - exit(0); - } - -// back to top of file so we can parse the first chunk descriptor - fseek(input, 0, SEEK_SET); - - ptri = malloc (MAXTRIANGLES * sizeof(triangle_t)); - - *pptri = ptri; - -// parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT | -// OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks - ParseChunk (input); - - if (vertsfound || trisfound) - Error ("Incomplete triangle set"); - - *numtriangles = totaltris; - - fclose (input); -} - diff --git a/common/l3dslib.h b/common/l3dslib.h deleted file mode 100644 index 41b647d..0000000 --- a/common/l3dslib.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// -// l3dslib.h: header file for loading triangles from a 3DS triangle file -// -void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles); - diff --git a/common/mathlib.c b/common/mathlib.c deleted file mode 100644 index 353cd25..0000000 --- a/common/mathlib.c +++ /dev/null @@ -1,434 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// mathlib.c -- math primitives - -#include "cmdlib.h" -#include "mathlib.h" - -#ifdef _WIN32 -//Improve floating-point consistency. -//without this option weird floating point issues occur -#pragma optimize( "p", on ) -#endif - - -vec3_t vec3_origin = {0,0,0}; - -/* -** NormalToLatLong -** -** We use two byte encoded normals in some space critical applications. -** Lat = 0 at (1,0,0) to 360 (-1,0,0), encoded in 8-bit sine table format -** Lng = 0 at (0,0,1) to 180 (0,0,-1), encoded in 8-bit sine table format -** -*/ -void NormalToLatLong( const vec3_t normal, byte bytes[2] ) { - // check for singularities - if ( normal[0] == 0 && normal[1] == 0 ) { - if ( normal[2] > 0 ) { - bytes[0] = 0; - bytes[1] = 0; // lat = 0, long = 0 - } else { - bytes[0] = 128; - bytes[1] = 0; // lat = 0, long = 128 - } - } else { - int a, b; - - a = RAD2DEG( atan2( normal[1], normal[0] ) ) * (255.0f / 360.0f ); - a &= 0xff; - - b = RAD2DEG( acos( normal[2] ) ) * ( 255.0f / 360.0f ); - b &= 0xff; - - bytes[0] = b; // longitude - bytes[1] = a; // lattitude - } -} - -/* -===================== -PlaneFromPoints - -Returns false if the triangle is degenrate. -The normal will point out of the clock for clockwise ordered points -===================== -*/ -qboolean PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c ) { - vec3_t d1, d2; - - VectorSubtract( b, a, d1 ); - VectorSubtract( c, a, d2 ); - CrossProduct( d2, d1, plane ); - if ( VectorNormalize( plane, plane ) == 0 ) { - return qfalse; - } - - plane[3] = DotProduct( a, plane ); - return qtrue; -} - -/* -================ -MakeNormalVectors - -Given a normalized forward vector, create two -other perpendicular vectors -================ -*/ -void MakeNormalVectors (vec3_t forward, vec3_t right, vec3_t up) -{ - float d; - - // this rotate and negate guarantees a vector - // not colinear with the original - right[1] = -forward[0]; - right[2] = forward[1]; - right[0] = forward[2]; - - d = DotProduct (right, forward); - VectorMA (right, -d, forward, right); - VectorNormalize (right, right); - CrossProduct (right, forward, up); -} - - -void Vec10Copy( vec_t *in, vec_t *out ) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[4] = in[4]; - out[5] = in[5]; - out[6] = in[6]; - out[7] = in[7]; - out[8] = in[8]; - out[9] = in[9]; -} - - -void VectorRotate3x3( vec3_t v, float r[3][3], vec3_t d ) -{ - d[0] = v[0] * r[0][0] + v[1] * r[1][0] + v[2] * r[2][0]; - d[1] = v[0] * r[0][1] + v[1] * r[1][1] + v[2] * r[2][1]; - d[2] = v[0] * r[0][2] + v[1] * r[1][2] + v[2] * r[2][2]; -} - -double VectorLength( const vec3_t v ) { - int i; - double length; - - length = 0; - for (i=0 ; i< 3 ; i++) - length += v[i]*v[i]; - length = sqrt (length); // FIXME - - return length; -} - -qboolean VectorCompare( const vec3_t v1, const vec3_t v2 ) { - int i; - - for (i=0 ; i<3 ; i++) - if (fabs(v1[i]-v2[i]) > EQUAL_EPSILON) - return qfalse; - - return qtrue; -} - -vec_t Q_rint (vec_t in) -{ - return floor (in + 0.5); -} - -void VectorMA( const vec3_t va, double scale, const vec3_t vb, vec3_t vc ) { - vc[0] = va[0] + scale*vb[0]; - vc[1] = va[1] + scale*vb[1]; - vc[2] = va[2] + scale*vb[2]; -} - -void CrossProduct( const vec3_t v1, const vec3_t v2, vec3_t cross ) { - cross[0] = v1[1]*v2[2] - v1[2]*v2[1]; - cross[1] = v1[2]*v2[0] - v1[0]*v2[2]; - cross[2] = v1[0]*v2[1] - v1[1]*v2[0]; -} - -vec_t _DotProduct (vec3_t v1, vec3_t v2) -{ - return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; -} - -void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out) -{ - out[0] = va[0]-vb[0]; - out[1] = va[1]-vb[1]; - out[2] = va[2]-vb[2]; -} - -void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out) -{ - out[0] = va[0]+vb[0]; - out[1] = va[1]+vb[1]; - out[2] = va[2]+vb[2]; -} - -void _VectorCopy (vec3_t in, vec3_t out) -{ - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; -} - -void _VectorScale (vec3_t v, vec_t scale, vec3_t out) -{ - out[0] = v[0] * scale; - out[1] = v[1] * scale; - out[2] = v[2] * scale; -} - -vec_t VectorNormalize( const vec3_t in, vec3_t out ) { - vec_t length, ilength; - - length = sqrt (in[0]*in[0] + in[1]*in[1] + in[2]*in[2]); - if (length == 0) - { - VectorClear (out); - return 0; - } - - ilength = 1.0/length; - out[0] = in[0]*ilength; - out[1] = in[1]*ilength; - out[2] = in[2]*ilength; - - return length; -} - -vec_t ColorNormalize( const vec3_t in, vec3_t out ) { - float max, scale; - - max = in[0]; - if (in[1] > max) - max = in[1]; - if (in[2] > max) - max = in[2]; - - if (max == 0) { - out[0] = out[1] = out[2] = 1.0; - return 0; - } - - scale = 1.0 / max; - - VectorScale (in, scale, out); - - return max; -} - - - -void VectorInverse (vec3_t v) -{ - v[0] = -v[0]; - v[1] = -v[1]; - v[2] = -v[2]; -} - -void ClearBounds (vec3_t mins, vec3_t maxs) -{ - mins[0] = mins[1] = mins[2] = 99999; - maxs[0] = maxs[1] = maxs[2] = -99999; -} - -void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs ) { - int i; - vec_t val; - - for (i=0 ; i<3 ; i++) - { - val = v[i]; - if (val < mins[i]) - mins[i] = val; - if (val > maxs[i]) - maxs[i] = val; - } -} - - -/* -================= -PlaneTypeForNormal -================= -*/ -int PlaneTypeForNormal (vec3_t normal) { - if (normal[0] == 1.0 || normal[0] == -1.0) - return PLANE_X; - if (normal[1] == 1.0 || normal[1] == -1.0) - return PLANE_Y; - if (normal[2] == 1.0 || normal[2] == -1.0) - return PLANE_Z; - - return PLANE_NON_AXIAL; -} - -/* -================ -MatrixMultiply -================ -*/ -void MatrixMultiply(float in1[3][3], float in2[3][3], float out[3][3]) { - out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + - in1[0][2] * in2[2][0]; - out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + - in1[0][2] * in2[2][1]; - out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + - in1[0][2] * in2[2][2]; - out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + - in1[1][2] * in2[2][0]; - out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + - in1[1][2] * in2[2][1]; - out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + - in1[1][2] * in2[2][2]; - out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + - in1[2][2] * in2[2][0]; - out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + - in1[2][2] * in2[2][1]; - out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + - in1[2][2] * in2[2][2]; -} - -void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal ) -{ - float d; - vec3_t n; - float inv_denom; - - inv_denom = 1.0F / DotProduct( normal, normal ); - - d = DotProduct( normal, p ) * inv_denom; - - n[0] = normal[0] * inv_denom; - n[1] = normal[1] * inv_denom; - n[2] = normal[2] * inv_denom; - - dst[0] = p[0] - d * n[0]; - dst[1] = p[1] - d * n[1]; - dst[2] = p[2] - d * n[2]; -} - -/* -** assumes "src" is normalized -*/ -void PerpendicularVector( vec3_t dst, const vec3_t src ) -{ - int pos; - int i; - float minelem = 1.0F; - vec3_t tempvec; - - /* - ** find the smallest magnitude axially aligned vector - */ - for ( pos = 0, i = 0; i < 3; i++ ) - { - if ( fabs( src[i] ) < minelem ) - { - pos = i; - minelem = fabs( src[i] ); - } - } - tempvec[0] = tempvec[1] = tempvec[2] = 0.0F; - tempvec[pos] = 1.0F; - - /* - ** project the point onto the plane defined by src - */ - ProjectPointOnPlane( dst, tempvec, src ); - - /* - ** normalize the result - */ - VectorNormalize( dst, dst ); -} - -/* -=============== -RotatePointAroundVector - -This is not implemented very well... -=============== -*/ -void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, - float degrees ) { - float m[3][3]; - float im[3][3]; - float zrot[3][3]; - float tmpmat[3][3]; - float rot[3][3]; - int i; - vec3_t vr, vup, vf; - float rad; - - vf[0] = dir[0]; - vf[1] = dir[1]; - vf[2] = dir[2]; - - PerpendicularVector( vr, dir ); - CrossProduct( vr, vf, vup ); - - m[0][0] = vr[0]; - m[1][0] = vr[1]; - m[2][0] = vr[2]; - - m[0][1] = vup[0]; - m[1][1] = vup[1]; - m[2][1] = vup[2]; - - m[0][2] = vf[0]; - m[1][2] = vf[1]; - m[2][2] = vf[2]; - - memcpy( im, m, sizeof( im ) ); - - im[0][1] = m[1][0]; - im[0][2] = m[2][0]; - im[1][0] = m[0][1]; - im[1][2] = m[2][1]; - im[2][0] = m[0][2]; - im[2][1] = m[1][2]; - - memset( zrot, 0, sizeof( zrot ) ); - zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F; - - rad = DEG2RAD( degrees ); - zrot[0][0] = cos( rad ); - zrot[0][1] = sin( rad ); - zrot[1][0] = -sin( rad ); - zrot[1][1] = cos( rad ); - - MatrixMultiply( m, zrot, tmpmat ); - MatrixMultiply( tmpmat, im, rot ); - - for ( i = 0; i < 3; i++ ) { - dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2]; - } -} diff --git a/common/mathlib.h b/common/mathlib.h deleted file mode 100644 index 6327f2a..0000000 --- a/common/mathlib.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#ifndef __MATHLIB__ -#define __MATHLIB__ - -// mathlib.h - -#include <math.h> - -#ifdef DOUBLEVEC_T -typedef double vec_t; -#else -typedef float vec_t; -#endif -typedef vec_t vec2_t[3]; -typedef vec_t vec3_t[3]; -typedef vec_t vec4_t[4]; - -#define SIDE_FRONT 0 -#define SIDE_ON 2 -#define SIDE_BACK 1 -#define SIDE_CROSS -2 - -#define Q_PI 3.14159265358979323846 -#define DEG2RAD( a ) ( ( (a) * Q_PI ) / 180.0F ) -#define RAD2DEG( a ) ( ( (a) * 180.0f ) / Q_PI ) - -extern vec3_t vec3_origin; - -#define EQUAL_EPSILON 0.001 - -// plane types are used to speed some tests -// 0-2 are axial planes -#define PLANE_X 0 -#define PLANE_Y 1 -#define PLANE_Z 2 -#define PLANE_NON_AXIAL 3 - -qboolean VectorCompare( const vec3_t v1, const vec3_t v2 ); - -#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2]) -#define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];} -#define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];} -#define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];} -#define VectorScale(a,b,c) {c[0]=b*a[0];c[1]=b*a[1];c[2]=b*a[2];} -#define VectorClear(x) {x[0] = x[1] = x[2] = 0;} -#define VectorNegate(x) {x[0]=-x[0];x[1]=-x[1];x[2]=-x[2];} -void Vec10Copy( vec_t *in, vec_t *out ); - -vec_t Q_rint (vec_t in); -vec_t _DotProduct (vec3_t v1, vec3_t v2); -void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out); -void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out); -void _VectorCopy (vec3_t in, vec3_t out); -void _VectorScale (vec3_t v, vec_t scale, vec3_t out); - -double VectorLength( const vec3_t v ); - -void VectorMA( const vec3_t va, double scale, const vec3_t vb, vec3_t vc ); - -void CrossProduct( const vec3_t v1, const vec3_t v2, vec3_t cross ); -vec_t VectorNormalize( const vec3_t in, vec3_t out ); -vec_t ColorNormalize( const vec3_t in, vec3_t out ); -void VectorInverse (vec3_t v); - -void ClearBounds (vec3_t mins, vec3_t maxs); -void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs ); - -qboolean PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c ); - -void NormalToLatLong( const vec3_t normal, byte bytes[2] ); - -int PlaneTypeForNormal (vec3_t normal); - -void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, - float degrees ); -#endif diff --git a/common/md4.c b/common/md4.c deleted file mode 100644 index 5b6e01a..0000000 --- a/common/md4.c +++ /dev/null @@ -1,277 +0,0 @@ -/* GLOBAL.H - RSAREF types and constants */ - -#include <string.h> - -/* POINTER defines a generic pointer type */ -typedef unsigned char *POINTER; - -/* UINT2 defines a two byte word */ -typedef unsigned short int UINT2; - -/* UINT4 defines a four byte word */ -typedef unsigned long int UINT4; - - -/* MD4.H - header file for MD4C.C */ - -/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. - -All rights reserved. - -License to copy and use this software is granted provided that it is identified as the “RSA Data Security, Inc. MD4 Message-Digest Algorithm” in all material mentioning or referencing this software or this function. -License is also granted to make and use derivative works provided that such works are identified as “derived from the RSA Data Security, Inc. MD4 Message-Digest Algorithm” in all material mentioning or referencing the derived work. -RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided “as is” without express or implied warranty of any kind. - -These notices must be retained in any copies of any part of this documentation and/or software. */ - -/* MD4 context. */ -typedef struct { - UINT4 state[4]; /* state (ABCD) */ - UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ - unsigned char buffer[64]; /* input buffer */ -} MD4_CTX; - -void MD4Init (MD4_CTX *); -void MD4Update (MD4_CTX *, unsigned char *, unsigned int); -void MD4Final (unsigned char [16], MD4_CTX *); - - - -/* MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm */ -/* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved. - -License to copy and use this software is granted provided that it is identified as the -RSA Data Security, Inc. MD4 Message-Digest Algorithm - in all material mentioning or referencing this software or this function. -License is also granted to make and use derivative works provided that such works are identified as -derived from the RSA Data Security, Inc. MD4 Message-Digest Algorithm -in all material mentioning or referencing the derived work. -RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided -as is without express or implied warranty of any kind. - -These notices must be retained in any copies of any part of this documentation and/or software. */ - -/* Constants for MD4Transform routine. */ -#define S11 3 -#define S12 7 -#define S13 11 -#define S14 19 -#define S21 3 -#define S22 5 -#define S23 9 -#define S24 13 -#define S31 3 -#define S32 9 -#define S33 11 -#define S34 15 - -static void MD4Transform (UINT4 [4], unsigned char [64]); -static void Encode (unsigned char *, UINT4 *, unsigned int); -static void Decode (UINT4 *, unsigned char *, unsigned int); -static void MD4_memcpy (POINTER, POINTER, unsigned int); -static void MD4_memset (POINTER, int, unsigned int); - -static unsigned char PADDING[64] = { -0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* F, G and H are basic MD4 functions. */ -#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) -#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) - -/* ROTATE_LEFT rotates x left n bits. */ -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) - -/* FF, GG and HH are transformations for rounds 1, 2 and 3 */ -/* Rotation is separate from addition to prevent recomputation */ -#define FF(a, b, c, d, x, s) {(a) += F ((b), (c), (d)) + (x); (a) = ROTATE_LEFT ((a), (s));} - -#define GG(a, b, c, d, x, s) {(a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; (a) = ROTATE_LEFT ((a), (s));} - -#define HH(a, b, c, d, x, s) {(a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; (a) = \ -ROTATE_LEFT ((a), (s)); } - - -/* MD4 initialization. Begins an MD4 operation, writing a new context. */ -void MD4Init (MD4_CTX *context) -{ - context->count[0] = context->count[1] = 0; - -/* Load magic initialization constants.*/ -context->state[0] = 0x67452301; -context->state[1] = 0xefcdab89; -context->state[2] = 0x98badcfe; -context->state[3] = 0x10325476; -} - -/* MD4 block update operation. Continues an MD4 message-digest operation, processing another message block, and updating the context. */ -void MD4Update (MD4_CTX *context, unsigned char *input, unsigned int inputLen) -{ - unsigned int i, index, partLen; - - /* Compute number of bytes mod 64 */ - index = (unsigned int)((context->count[0] >> 3) & 0x3F); - - /* Update number of bits */ - if ((context->count[0] += ((UINT4)inputLen << 3))< ((UINT4)inputLen << 3)) - context->count[1]++; - - context->count[1] += ((UINT4)inputLen >> 29); - - partLen = 64 - index; - - /* Transform as many times as possible.*/ - if (inputLen >= partLen) - { - memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen); - MD4Transform (context->state, context->buffer); - - for (i = partLen; i + 63 < inputLen; i += 64) - MD4Transform (context->state, &input[i]); - - index = 0; - } - else - i = 0; - - /* Buffer remaining input */ - memcpy ((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i); -} - - -/* MD4 finalization. Ends an MD4 message-digest operation, writing the the message digest and zeroizing the context. */ -void MD4Final (unsigned char digest[16], MD4_CTX *context) -{ - unsigned char bits[8]; - unsigned int index, padLen; - - /* Save number of bits */ - Encode (bits, context->count, 8); - - /* Pad out to 56 mod 64.*/ - index = (unsigned int)((context->count[0] >> 3) & 0x3f); - padLen = (index < 56) ? (56 - index) : (120 - index); - MD4Update (context, PADDING, padLen); - - /* Append length (before padding) */ - MD4Update (context, bits, 8); - - /* Store state in digest */ - Encode (digest, context->state, 16); - - /* Zeroize sensitive information.*/ - memset ((POINTER)context, 0, sizeof (*context)); -} - - -/* MD4 basic transformation. Transforms state based on block. */ -static void MD4Transform (UINT4 state[4], unsigned char block[64]) -{ - UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; - - Decode (x, block, 64); - -/* Round 1 */ -FF (a, b, c, d, x[ 0], S11); /* 1 */ -FF (d, a, b, c, x[ 1], S12); /* 2 */ -FF (c, d, a, b, x[ 2], S13); /* 3 */ -FF (b, c, d, a, x[ 3], S14); /* 4 */ -FF (a, b, c, d, x[ 4], S11); /* 5 */ -FF (d, a, b, c, x[ 5], S12); /* 6 */ -FF (c, d, a, b, x[ 6], S13); /* 7 */ -FF (b, c, d, a, x[ 7], S14); /* 8 */ -FF (a, b, c, d, x[ 8], S11); /* 9 */ -FF (d, a, b, c, x[ 9], S12); /* 10 */ -FF (c, d, a, b, x[10], S13); /* 11 */ -FF (b, c, d, a, x[11], S14); /* 12 */ -FF (a, b, c, d, x[12], S11); /* 13 */ -FF (d, a, b, c, x[13], S12); /* 14 */ -FF (c, d, a, b, x[14], S13); /* 15 */ -FF (b, c, d, a, x[15], S14); /* 16 */ - -/* Round 2 */ -GG (a, b, c, d, x[ 0], S21); /* 17 */ -GG (d, a, b, c, x[ 4], S22); /* 18 */ -GG (c, d, a, b, x[ 8], S23); /* 19 */ -GG (b, c, d, a, x[12], S24); /* 20 */ -GG (a, b, c, d, x[ 1], S21); /* 21 */ -GG (d, a, b, c, x[ 5], S22); /* 22 */ -GG (c, d, a, b, x[ 9], S23); /* 23 */ -GG (b, c, d, a, x[13], S24); /* 24 */ -GG (a, b, c, d, x[ 2], S21); /* 25 */ -GG (d, a, b, c, x[ 6], S22); /* 26 */ -GG (c, d, a, b, x[10], S23); /* 27 */ -GG (b, c, d, a, x[14], S24); /* 28 */ -GG (a, b, c, d, x[ 3], S21); /* 29 */ -GG (d, a, b, c, x[ 7], S22); /* 30 */ -GG (c, d, a, b, x[11], S23); /* 31 */ -GG (b, c, d, a, x[15], S24); /* 32 */ - -/* Round 3 */ -HH (a, b, c, d, x[ 0], S31); /* 33 */ -HH (d, a, b, c, x[ 8], S32); /* 34 */ -HH (c, d, a, b, x[ 4], S33); /* 35 */ -HH (b, c, d, a, x[12], S34); /* 36 */ -HH (a, b, c, d, x[ 2], S31); /* 37 */ -HH (d, a, b, c, x[10], S32); /* 38 */ -HH (c, d, a, b, x[ 6], S33); /* 39 */ -HH (b, c, d, a, x[14], S34); /* 40 */ -HH (a, b, c, d, x[ 1], S31); /* 41 */ -HH (d, a, b, c, x[ 9], S32); /* 42 */ -HH (c, d, a, b, x[ 5], S33); /* 43 */ -HH (b, c, d, a, x[13], S34); /* 44 */ -HH (a, b, c, d, x[ 3], S31); /* 45 */ -HH (d, a, b, c, x[11], S32); /* 46 */ -HH (c, d, a, b, x[ 7], S33); /* 47 */ -HH (b, c, d, a, x[15], S34); /* 48 */ - -state[0] += a; -state[1] += b; -state[2] += c; -state[3] += d; - - /* Zeroize sensitive information.*/ - memset ((POINTER)x, 0, sizeof (x)); -} - - -/* Encodes input (UINT4) into output (unsigned char). Assumes len is a multiple of 4. */ -static void Encode (unsigned char *output, UINT4 *input, unsigned int len) -{ - unsigned int i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) { - output[j] = (unsigned char)(input[i] & 0xff); - output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); - output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); - output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); - } -} - - -/* Decodes input (unsigned char) into output (UINT4). Assumes len is a multiple of 4. */ -static void Decode (UINT4 *output, unsigned char *input, unsigned int len) -{ -unsigned int i, j; - -for (i = 0, j = 0; j < len; i++, j += 4) - output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); -} - -//=================================================================== - -unsigned Com_BlockChecksum (void *buffer, int length) -{ - int digest[4]; - unsigned val; - MD4_CTX ctx; - - MD4Init (&ctx); - MD4Update (&ctx, (unsigned char *)buffer, length); - MD4Final ( (unsigned char *)digest, &ctx); - - val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3]; - - return val; -} diff --git a/common/mutex.c b/common/mutex.c deleted file mode 100644 index 0611eca..0000000 --- a/common/mutex.c +++ /dev/null @@ -1,197 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "cmdlib.h" -#include "threads.h" -#include "mutex.h" - -/* -=================================================================== - -WIN32 - -=================================================================== -*/ -#ifdef WIN32 - -#define USED - -#include <windows.h> - -void MutexLock (mutex_t *m) -{ - CRITICAL_SECTION *crit; - - if (!m) - return; - crit = (CRITICAL_SECTION *) m; - EnterCriticalSection (crit); -} - -void MutexUnlock (mutex_t *m) -{ - CRITICAL_SECTION *crit; - - if (!m) - return; - crit = (CRITICAL_SECTION *) m; - LeaveCriticalSection (crit); -} - -mutex_t *MutexAlloc(void) -{ - CRITICAL_SECTION *crit; - - if (numthreads == 1) - return NULL; - crit = (CRITICAL_SECTION *) malloc(sizeof(CRITICAL_SECTION)); - InitializeCriticalSection (crit); - return (void *) crit; -} - -#endif - -/* -=================================================================== - -OSF1 - -=================================================================== -*/ - -#ifdef __osf__ -#define USED - -#include <pthread.h> - -void MutexLock (mutex_t *m) -{ - pthread_mutex_t *my_mutex; - - if (!m) - return; - my_mutex = (pthread_mutex_t *) m; - pthread_mutex_lock (my_mutex); -} - -void MutexUnlock (mutex_t *m) -{ - pthread_mutex_t *my_mutex; - - if (!m) - return; - my_mutex = (pthread_mutex_t *) m; - pthread_mutex_unlock (my_mutex); -} - -mutex_t *MutexAlloc(void) -{ - pthread_mutex_t *my_mutex; - pthread_mutexattr_t mattrib; - - if (numthreads == 1) - return NULL; - my_mutex = malloc (sizeof(*my_mutex)); - if (pthread_mutexattr_create (&mattrib) == -1) - Error ("pthread_mutex_attr_create failed"); - if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1) - Error ("pthread_mutexattr_setkind_np failed"); - if (pthread_mutex_init (my_mutex, mattrib) == -1) - Error ("pthread_mutex_init failed"); - return (void *) my_mutex; -} - -#endif - -/* -=================================================================== - -IRIX - -=================================================================== -*/ - -#ifdef _MIPS_ISA -#define USED - -#include <task.h> -#include <abi_mutex.h> -#include <sys/types.h> -#include <sys/prctl.h> - -void MutexLock (mutex_t *m) -{ - abilock_t *lck; - - if (!m) - return; - lck = (abilock_t *) m; - spin_lock (lck); -} - -void MutexUnlock (mutex_t *m) -{ - abilock_t *lck; - - if (!m) - return; - lck = (abilock_t *) m; - release_lock (lck); -} - -mutex_t *MutexAlloc(void) -{ - abilock_t *lck; - - if (numthreads == 1) - return NULL; - lck = (abilock_t *) malloc(sizeof(abilock_t)); - init_lock (lck); - return (void *) lck; -} - -#endif - -/* -======================================================================= - - SINGLE THREAD - -======================================================================= -*/ - -#ifndef USED - -void MutexLock (mutex_t *m) -{ -} - -void MutexUnlock (mutex_t *m) -{ -} - -mutex_t *MutexAlloc(void) -{ - return NULL; -} - -#endif diff --git a/common/mutex.h b/common/mutex.h deleted file mode 100644 index 373491d..0000000 --- a/common/mutex.h +++ /dev/null @@ -1,28 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - - -typedef void *mutex_t; - -void MutexLock (mutex_t *m); -void MutexUnlock (mutex_t *m); -mutex_t *MutexAlloc(void); diff --git a/common/polylib.c b/common/polylib.c deleted file mode 100644 index 2acf0f5..0000000 --- a/common/polylib.c +++ /dev/null @@ -1,740 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "cmdlib.h" -#include "mathlib.h" -#include "polylib.h" -#include "qfiles.h" - - -extern int numthreads; - -// counters are only bumped when running single threaded, -// because they are an awefull coherence problem -int c_active_windings; -int c_peak_windings; -int c_winding_allocs; -int c_winding_points; - -#define BOGUS_RANGE WORLD_SIZE - -void pw(winding_t *w) -{ - int i; - for (i=0 ; i<w->numpoints ; i++) - printf ("(%5.1f, %5.1f, %5.1f)\n",w->p[i][0], w->p[i][1],w->p[i][2]); -} - - -/* -============= -AllocWinding -============= -*/ -winding_t *AllocWinding (int points) -{ - winding_t *w; - int s; - - if (numthreads == 1) - { - c_winding_allocs++; - c_winding_points += points; - c_active_windings++; - if (c_active_windings > c_peak_windings) - c_peak_windings = c_active_windings; - } - s = sizeof(vec_t)*3*points + sizeof(int); - w = malloc (s); - memset (w, 0, s); - return w; -} - -void FreeWinding (winding_t *w) -{ - if (*(unsigned *)w == 0xdeaddead) - Error ("FreeWinding: freed a freed winding"); - *(unsigned *)w = 0xdeaddead; - - if (numthreads == 1) - c_active_windings--; - free (w); -} - -/* -============ -RemoveColinearPoints -============ -*/ -int c_removed; - -void RemoveColinearPoints (winding_t *w) -{ - int i, j, k; - vec3_t v1, v2; - int nump; - vec3_t p[MAX_POINTS_ON_WINDING]; - - nump = 0; - for (i=0 ; i<w->numpoints ; i++) - { - j = (i+1)%w->numpoints; - k = (i+w->numpoints-1)%w->numpoints; - VectorSubtract (w->p[j], w->p[i], v1); - VectorSubtract (w->p[i], w->p[k], v2); - VectorNormalize(v1,v1); - VectorNormalize(v2,v2); - if (DotProduct(v1, v2) < 0.999) - { - VectorCopy (w->p[i], p[nump]); - nump++; - } - } - - if (nump == w->numpoints) - return; - - if (numthreads == 1) - c_removed += w->numpoints - nump; - w->numpoints = nump; - memcpy (w->p, p, nump*sizeof(p[0])); -} - -/* -============ -WindingPlane -============ -*/ -void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist) -{ - vec3_t v1, v2; - - VectorSubtract (w->p[1], w->p[0], v1); - VectorSubtract (w->p[2], w->p[0], v2); - CrossProduct (v2, v1, normal); - VectorNormalize (normal, normal); - *dist = DotProduct (w->p[0], normal); - -} - -/* -============= -WindingArea -============= -*/ -vec_t WindingArea (winding_t *w) -{ - int i; - vec3_t d1, d2, cross; - vec_t total; - - total = 0; - for (i=2 ; i<w->numpoints ; i++) - { - VectorSubtract (w->p[i-1], w->p[0], d1); - VectorSubtract (w->p[i], w->p[0], d2); - CrossProduct (d1, d2, cross); - total += 0.5 * VectorLength ( cross ); - } - return total; -} - -void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs) -{ - vec_t v; - int i,j; - - mins[0] = mins[1] = mins[2] = 99999; - maxs[0] = maxs[1] = maxs[2] = -99999; - - for (i=0 ; i<w->numpoints ; i++) - { - for (j=0 ; j<3 ; j++) - { - v = w->p[i][j]; - if (v < mins[j]) - mins[j] = v; - if (v > maxs[j]) - maxs[j] = v; - } - } -} - -/* -============= -WindingCenter -============= -*/ -void WindingCenter (winding_t *w, vec3_t center) -{ - int i; - float scale; - - VectorCopy (vec3_origin, center); - for (i=0 ; i<w->numpoints ; i++) - VectorAdd (w->p[i], center, center); - - scale = 1.0/w->numpoints; - VectorScale (center, scale, center); -} - -/* -================= -BaseWindingForPlane -================= -*/ -winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist) -{ - int i, x; - vec_t max, v; - vec3_t org, vright, vup; - winding_t *w; - -// find the major axis - - max = -BOGUS_RANGE; - x = -1; - for (i=0 ; i<3; i++) - { - v = fabs(normal[i]); - if (v > max) - { - x = i; - max = v; - } - } - if (x==-1) - Error ("BaseWindingForPlane: no axis found"); - - VectorCopy (vec3_origin, vup); - switch (x) - { - case 0: - case 1: - vup[2] = 1; - break; - case 2: - vup[0] = 1; - break; - } - - v = DotProduct (vup, normal); - VectorMA (vup, -v, normal, vup); - VectorNormalize (vup, vup); - - VectorScale (normal, dist, org); - - CrossProduct (vup, normal, vright); - - VectorScale (vup, MAX_WORLD_COORD, vup); - VectorScale (vright, MAX_WORLD_COORD, vright); - -// project a really big axis aligned box onto the plane - w = AllocWinding (4); - - VectorSubtract (org, vright, w->p[0]); - VectorAdd (w->p[0], vup, w->p[0]); - - VectorAdd (org, vright, w->p[1]); - VectorAdd (w->p[1], vup, w->p[1]); - - VectorAdd (org, vright, w->p[2]); - VectorSubtract (w->p[2], vup, w->p[2]); - - VectorSubtract (org, vright, w->p[3]); - VectorSubtract (w->p[3], vup, w->p[3]); - - w->numpoints = 4; - - return w; -} - -/* -================== -CopyWinding -================== -*/ -winding_t *CopyWinding (winding_t *w) -{ - int size; - winding_t *c; - - c = AllocWinding (w->numpoints); - size = (int)((winding_t *)0)->p[w->numpoints]; - memcpy (c, w, size); - return c; -} - -/* -================== -ReverseWinding -================== -*/ -winding_t *ReverseWinding (winding_t *w) -{ - int i; - winding_t *c; - - c = AllocWinding (w->numpoints); - for (i=0 ; i<w->numpoints ; i++) - { - VectorCopy (w->p[w->numpoints-1-i], c->p[i]); - } - c->numpoints = w->numpoints; - return c; -} - - -/* -============= -ClipWindingEpsilon -============= -*/ -void ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, - vec_t epsilon, winding_t **front, winding_t **back) -{ - vec_t dists[MAX_POINTS_ON_WINDING+4]; - int sides[MAX_POINTS_ON_WINDING+4]; - int counts[3]; - static vec_t dot; // VC 4.2 optimizer bug if not static - int i, j; - vec_t *p1, *p2; - vec3_t mid; - winding_t *f, *b; - int maxpts; - - counts[0] = counts[1] = counts[2] = 0; - -// determine sides for each point - for (i=0 ; i<in->numpoints ; i++) - { - dot = DotProduct (in->p[i], normal); - dot -= dist; - dists[i] = dot; - if (dot > epsilon) - sides[i] = SIDE_FRONT; - else if (dot < -epsilon) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - sides[i] = sides[0]; - dists[i] = dists[0]; - - *front = *back = NULL; - - if (!counts[0]) - { - *back = CopyWinding (in); - return; - } - if (!counts[1]) - { - *front = CopyWinding (in); - return; - } - - maxpts = in->numpoints+4; // cant use counts[0]+2 because - // of fp grouping errors - - *front = f = AllocWinding (maxpts); - *back = b = AllocWinding (maxpts); - - for (i=0 ; i<in->numpoints ; i++) - { - p1 = in->p[i]; - - if (sides[i] == SIDE_ON) - { - VectorCopy (p1, f->p[f->numpoints]); - f->numpoints++; - VectorCopy (p1, b->p[b->numpoints]); - b->numpoints++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, f->p[f->numpoints]); - f->numpoints++; - } - if (sides[i] == SIDE_BACK) - { - VectorCopy (p1, b->p[b->numpoints]); - b->numpoints++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - // generate a split point - p2 = in->p[(i+1)%in->numpoints]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (normal[j] == 1) - mid[j] = dist; - else if (normal[j] == -1) - mid[j] = -dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, f->p[f->numpoints]); - f->numpoints++; - VectorCopy (mid, b->p[b->numpoints]); - b->numpoints++; - } - - if (f->numpoints > maxpts || b->numpoints > maxpts) - Error ("ClipWinding: points exceeded estimate"); - if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING) - Error ("ClipWinding: MAX_POINTS_ON_WINDING"); -} - - -/* -============= -ChopWindingInPlace -============= -*/ -void ChopWindingInPlace (winding_t **inout, vec3_t normal, vec_t dist, vec_t epsilon) -{ - winding_t *in; - vec_t dists[MAX_POINTS_ON_WINDING+4]; - int sides[MAX_POINTS_ON_WINDING+4]; - int counts[3]; - static vec_t dot; // VC 4.2 optimizer bug if not static - int i, j; - vec_t *p1, *p2; - vec3_t mid; - winding_t *f; - int maxpts; - - in = *inout; - counts[0] = counts[1] = counts[2] = 0; - -// determine sides for each point - for (i=0 ; i<in->numpoints ; i++) - { - dot = DotProduct (in->p[i], normal); - dot -= dist; - dists[i] = dot; - if (dot > epsilon) - sides[i] = SIDE_FRONT; - else if (dot < -epsilon) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - sides[i] = sides[0]; - dists[i] = dists[0]; - - if (!counts[0]) - { - FreeWinding (in); - *inout = NULL; - return; - } - if (!counts[1]) - return; // inout stays the same - - maxpts = in->numpoints+4; // cant use counts[0]+2 because - // of fp grouping errors - - f = AllocWinding (maxpts); - - for (i=0 ; i<in->numpoints ; i++) - { - p1 = in->p[i]; - - if (sides[i] == SIDE_ON) - { - VectorCopy (p1, f->p[f->numpoints]); - f->numpoints++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, f->p[f->numpoints]); - f->numpoints++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - // generate a split point - p2 = in->p[(i+1)%in->numpoints]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (normal[j] == 1) - mid[j] = dist; - else if (normal[j] == -1) - mid[j] = -dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, f->p[f->numpoints]); - f->numpoints++; - } - - if (f->numpoints > maxpts) - Error ("ClipWinding: points exceeded estimate"); - if (f->numpoints > MAX_POINTS_ON_WINDING) - Error ("ClipWinding: MAX_POINTS_ON_WINDING"); - - FreeWinding (in); - *inout = f; -} - - -/* -================= -ChopWinding - -Returns the fragment of in that is on the front side -of the cliping plane. The original is freed. -================= -*/ -winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist) -{ - winding_t *f, *b; - - ClipWindingEpsilon (in, normal, dist, ON_EPSILON, &f, &b); - FreeWinding (in); - if (b) - FreeWinding (b); - return f; -} - - -/* -================= -CheckWinding - -================= -*/ -void CheckWinding (winding_t *w) -{ - int i, j; - vec_t *p1, *p2; - vec_t d, edgedist; - vec3_t dir, edgenormal, facenormal; - vec_t area; - vec_t facedist; - - if (w->numpoints < 3) - Error ("CheckWinding: %i points",w->numpoints); - - area = WindingArea(w); - if (area < 1) - Error ("CheckWinding: %f area", area); - - WindingPlane (w, facenormal, &facedist); - - for (i=0 ; i<w->numpoints ; i++) - { - p1 = w->p[i]; - - for (j=0 ; j<3 ; j++) - if (p1[j] > MAX_WORLD_COORD || p1[j] < MIN_WORLD_COORD) - Error ("CheckFace: BUGUS_RANGE: %f",p1[j]); - - j = i+1 == w->numpoints ? 0 : i+1; - - // check the point is on the face plane - d = DotProduct (p1, facenormal) - facedist; - if (d < -ON_EPSILON || d > ON_EPSILON) - Error ("CheckWinding: point off plane"); - - // check the edge isnt degenerate - p2 = w->p[j]; - VectorSubtract (p2, p1, dir); - - if (VectorLength (dir) < ON_EPSILON) - Error ("CheckWinding: degenerate edge"); - - CrossProduct (facenormal, dir, edgenormal); - VectorNormalize (edgenormal, edgenormal); - edgedist = DotProduct (p1, edgenormal); - edgedist += ON_EPSILON; - - // all other points must be on front side - for (j=0 ; j<w->numpoints ; j++) - { - if (j == i) - continue; - d = DotProduct (w->p[j], edgenormal); - if (d > edgedist) - Error ("CheckWinding: non-convex"); - } - } -} - - -/* -============ -WindingOnPlaneSide -============ -*/ -int WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist) -{ - qboolean front, back; - int i; - vec_t d; - - front = qfalse; - back = qfalse; - for (i=0 ; i<w->numpoints ; i++) - { - d = DotProduct (w->p[i], normal) - dist; - if (d < -ON_EPSILON) - { - if (front) - return SIDE_CROSS; - back = qtrue; - continue; - } - if (d > ON_EPSILON) - { - if (back) - return SIDE_CROSS; - front = qtrue; - continue; - } - } - - if (back) - return SIDE_BACK; - if (front) - return SIDE_FRONT; - return SIDE_ON; -} - - -/* -================= -AddWindingToConvexHull - -Both w and *hull are on the same plane -================= -*/ -#define MAX_HULL_POINTS 128 -void AddWindingToConvexHull( winding_t *w, winding_t **hull, vec3_t normal ) { - int i, j, k; - float *p, *copy; - vec3_t dir; - float d; - int numHullPoints, numNew; - vec3_t hullPoints[MAX_HULL_POINTS]; - vec3_t newHullPoints[MAX_HULL_POINTS]; - vec3_t hullDirs[MAX_HULL_POINTS]; - qboolean hullSide[MAX_HULL_POINTS]; - qboolean outside; - - if ( !*hull ) { - *hull = CopyWinding( w ); - return; - } - - numHullPoints = (*hull)->numpoints; - memcpy( hullPoints, (*hull)->p, numHullPoints * sizeof(vec3_t) ); - - for ( i = 0 ; i < w->numpoints ; i++ ) { - p = w->p[i]; - - // calculate hull side vectors - for ( j = 0 ; j < numHullPoints ; j++ ) { - k = ( j + 1 ) % numHullPoints; - - VectorSubtract( hullPoints[k], hullPoints[j], dir ); - VectorNormalize( dir, dir ); - CrossProduct( normal, dir, hullDirs[j] ); - } - - outside = qfalse; - for ( j = 0 ; j < numHullPoints ; j++ ) { - VectorSubtract( p, hullPoints[j], dir ); - d = DotProduct( dir, hullDirs[j] ); - if ( d >= ON_EPSILON ) { - outside = qtrue; - } - if ( d >= -ON_EPSILON ) { - hullSide[j] = qtrue; - } else { - hullSide[j] = qfalse; - } - } - - // if the point is effectively inside, do nothing - if ( !outside ) { - continue; - } - - // find the back side to front side transition - for ( j = 0 ; j < numHullPoints ; j++ ) { - if ( !hullSide[ j % numHullPoints ] && hullSide[ (j + 1) % numHullPoints ] ) { - break; - } - } - if ( j == numHullPoints ) { - continue; - } - - // insert the point here - VectorCopy( p, newHullPoints[0] ); - numNew = 1; - - // copy over all points that aren't double fronts - j = (j+1)%numHullPoints; - for ( k = 0 ; k < numHullPoints ; k++ ) { - if ( hullSide[ (j+k) % numHullPoints ] && hullSide[ (j+k+1) % numHullPoints ] ) { - continue; - } - copy = hullPoints[ (j+k+1) % numHullPoints ]; - VectorCopy( copy, newHullPoints[numNew] ); - numNew++; - } - - numHullPoints = numNew; - memcpy( hullPoints, newHullPoints, numHullPoints * sizeof(vec3_t) ); - } - - FreeWinding( *hull ); - w = AllocWinding( numHullPoints ); - w->numpoints = numHullPoints; - *hull = w; - memcpy( w->p, hullPoints, numHullPoints * sizeof(vec3_t) ); -} - - diff --git a/common/polylib.h b/common/polylib.h deleted file mode 100644 index 5feb932..0000000 --- a/common/polylib.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -typedef struct -{ - int numpoints; - vec3_t p[4]; // variable sized -} winding_t; - -#define MAX_POINTS_ON_WINDING 64 - -// you can define on_epsilon in the makefile as tighter -#ifndef ON_EPSILON -#define ON_EPSILON 0.1 -#endif - -winding_t *AllocWinding (int points); -vec_t WindingArea (winding_t *w); -void WindingCenter (winding_t *w, vec3_t center); -void ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, - vec_t epsilon, winding_t **front, winding_t **back); -winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist); -winding_t *CopyWinding (winding_t *w); -winding_t *ReverseWinding (winding_t *w); -winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist); -void CheckWinding (winding_t *w); -void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist); -void RemoveColinearPoints (winding_t *w); -int WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist); -void FreeWinding (winding_t *w); -void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs); - -void AddWindingToConvexHull( winding_t *w, winding_t **hull, vec3_t normal ); - -void ChopWindingInPlace (winding_t **w, vec3_t normal, vec_t dist, vec_t epsilon); -// frees the original if clipped - -void pw(winding_t *w); diff --git a/common/polyset.h b/common/polyset.h deleted file mode 100644 index 7b42f6e..0000000 --- a/common/polyset.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#ifndef __POLYSET_H__ -#define __POLYSET_H__ - -#define POLYSET_MAXTRIANGLES 4096 -#define POLYSET_MAXPOLYSETS 64 - -typedef float st_t[2]; -typedef float rgb_t[3]; - -typedef struct { - vec3_t verts[3]; - vec3_t normals[3]; - st_t texcoords[3]; -} triangle_t; - -typedef struct -{ - char name[100]; - char materialname[100]; - triangle_t *triangles; - int numtriangles; -} polyset_t; - -polyset_t *Polyset_LoadSets( const char *file, int *numpolysets, int maxTrisPerSet ); -polyset_t *Polyset_CollapseSets( polyset_t *psets, int numpolysets ); -polyset_t *Polyset_SplitSets( polyset_t *psets, int numpolysets, int *pNumNewPolysets, int maxTris ); -void Polyset_SnapSets( polyset_t *psets, int numpolysets ); -void Polyset_ComputeNormals( polyset_t *psets, int numpolysets ); - -#endif diff --git a/common/qfiles.h b/common/qfiles.h deleted file mode 100644 index 72590a5..0000000 --- a/common/qfiles.h +++ /dev/null @@ -1,489 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#ifndef __QFILES_H__ -#define __QFILES_H__ - -// -// qfiles.h: quake file formats -// This file must be identical in the quake and utils directories -// - -// surface geometry should not exceed these limits -#define SHADER_MAX_VERTEXES 1000 -#define SHADER_MAX_INDEXES (6*SHADER_MAX_VERTEXES) - - -// the maximum size of game reletive pathnames -#define MAX_QPATH 64 - - -/* -======================================================================== - -QVM files - -======================================================================== -*/ - -#define VM_MAGIC 0x12721444 -typedef struct { - int vmMagic; - - int instructionCount; - - int codeOffset; - int codeLength; - - int dataOffset; - int dataLength; - int litLength; // ( dataLength - litLength ) should be byteswapped on load - int bssLength; // zero filled memory appended to datalength -} vmHeader_t; - -/* -======================================================================== - -PCX files are used for 8 bit images - -======================================================================== -*/ - -typedef struct { - char manufacturer; - char version; - char encoding; - char bits_per_pixel; - unsigned short xmin,ymin,xmax,ymax; - unsigned short hres,vres; - unsigned char palette[48]; - char reserved; - char color_planes; - unsigned short bytes_per_line; - unsigned short palette_type; - char filler[58]; - unsigned char data; // unbounded -} pcx_t; - - -/* -======================================================================== - -TGA files are used for 24/32 bit images - -======================================================================== -*/ - -typedef struct _TargaHeader { - unsigned char id_length, colormap_type, image_type; - unsigned short colormap_index, colormap_length; - unsigned char colormap_size; - unsigned short x_origin, y_origin, width, height; - unsigned char pixel_size, attributes; -} TargaHeader; - - - -/* -======================================================================== - -.MD3 triangle model file format - -======================================================================== -*/ - -#define MD3_IDENT (('3'<<24)+('P'<<16)+('D'<<8)+'I') -#define MD3_VERSION 15 - -// limits -#define MD3_MAX_LODS 4 -#define MD3_MAX_TRIANGLES 8192 // per surface -#define MD3_MAX_VERTS 4096 // per surface -#define MD3_MAX_SHADERS 256 // per surface -#define MD3_MAX_FRAMES 1024 // per model -#define MD3_MAX_SURFACES 32 // per model -#define MD3_MAX_TAGS 16 // per frame - -// vertex scales -#define MD3_XYZ_SCALE (1.0/64) - -typedef struct md3Frame_s { - vec3_t bounds[2]; - vec3_t localOrigin; - float radius; - char name[16]; -} md3Frame_t; - -typedef struct md3Tag_s { - char name[MAX_QPATH]; // tag name - vec3_t origin; - vec3_t axis[3]; -} md3Tag_t; - -/* -** md3Surface_t -** -** CHUNK SIZE -** header sizeof( md3Surface_t ) -** shaders sizeof( md3Shader_t ) * numShaders -** triangles[0] sizeof( md3Triangle_t ) * numTriangles -** st sizeof( md3St_t ) * numVerts -** XyzNormals sizeof( md3XyzNormal_t ) * numVerts * numFrames -*/ -typedef struct { - int ident; // - - char name[MAX_QPATH]; // polyset name - - int flags; - int numFrames; // all surfaces in a model should have the same - - int numShaders; // all surfaces in a model should have the same - int numVerts; - - int numTriangles; - int ofsTriangles; - - int ofsShaders; // offset from start of md3Surface_t - int ofsSt; // texture coords are common for all frames - int ofsXyzNormals; // numVerts * numFrames - - int ofsEnd; // next surface follows -} md3Surface_t; - -typedef struct { - char name[MAX_QPATH]; - int shaderIndex; // for in-game use -} md3Shader_t; - -typedef struct { - int indexes[3]; -} md3Triangle_t; - -typedef struct { - float st[2]; -} md3St_t; - -typedef struct { - short xyz[3]; - short normal; -} md3XyzNormal_t; - -typedef struct { - int ident; - int version; - - char name[MAX_QPATH]; // model name - - int flags; - - int numFrames; - int numTags; - int numSurfaces; - - int numSkins; - - int ofsFrames; // offset for first frame - int ofsTags; // numFrames * numTags - int ofsSurfaces; // first surface, others follow - - int ofsEnd; // end of file -} md3Header_t; - - -/* -============================================================================== - -MD4 file format - -============================================================================== -*/ - -#define MD4_IDENT (('4'<<24)+('P'<<16)+('D'<<8)+'I') -#define MD4_VERSION 1 -#define MD4_MAX_BONES 128 - -typedef struct { - int boneIndex; // these are indexes into the boneReferences, - float boneWeight; // not the global per-frame bone list -} md4Weight_t; - -typedef struct { - vec3_t vertex; - vec3_t normal; - float texCoords[2]; - int numWeights; - md4Weight_t weights[1]; // variable sized -} md4Vertex_t; - -typedef struct { - int indexes[3]; -} md4Triangle_t; - -typedef struct { - int ident; - - char name[MAX_QPATH]; // polyset name - char shader[MAX_QPATH]; - int shaderIndex; // for in-game use - - int ofsHeader; // this will be a negative number - - int numVerts; - int ofsVerts; - - int numTriangles; - int ofsTriangles; - - // Bone references are a set of ints representing all the bones - // present in any vertex weights for this surface. This is - // needed because a model may have surfaces that need to be - // drawn at different sort times, and we don't want to have - // to re-interpolate all the bones for each surface. - int numBoneReferences; - int ofsBoneReferences; - - int ofsEnd; // next surface follows -} md4Surface_t; - -typedef struct { - float matrix[3][4]; -} md4Bone_t; - -typedef struct { - vec3_t bounds[2]; // bounds of all surfaces of all LOD's for this frame - vec3_t localOrigin; // midpoint of bounds, used for sphere cull - float radius; // dist from localOrigin to corner - char name[16]; - md4Bone_t bones[1]; // [numBones] -} md4Frame_t; - -typedef struct { - int numSurfaces; - int ofsSurfaces; // first surface, others follow - int ofsEnd; // next lod follows -} md4LOD_t; - -typedef struct { - int ident; - int version; - - char name[MAX_QPATH]; // model name - - // frames and bones are shared by all levels of detail - int numFrames; - int numBones; - int ofsFrames; // md4Frame_t[numFrames] - - // each level of detail has completely separate sets of surfaces - int numLODs; - int ofsLODs; - - int ofsEnd; // end of file -} md4Header_t; - - -/* -============================================================================== - - .BSP file format - -============================================================================== -*/ - - -#define BSP_IDENT (('P'<<24)+('S'<<16)+('B'<<8)+'I') - // little-endian "IBSP" - -#define BSP_VERSION 46 - - -// there shouldn't be any problem with increasing these values at the -// expense of more memory allocation in the utilities -#define MAX_MAP_MODELS 0x400 -#define MAX_MAP_BRUSHES 0x8000 -#define MAX_MAP_ENTITIES 0x800 -#define MAX_MAP_ENTSTRING 0x40000 -#define MAX_MAP_SHADERS 0x400 - -#define MAX_MAP_AREAS 0x100 // MAX_MAP_AREA_BYTES in q_shared must match! -#define MAX_MAP_FOGS 0x100 -#define MAX_MAP_PLANES 0x20000 -#define MAX_MAP_NODES 0x20000 -#define MAX_MAP_BRUSHSIDES 0x20000 -#define MAX_MAP_LEAFS 0x20000 -#define MAX_MAP_LEAFFACES 0x20000 -#define MAX_MAP_LEAFBRUSHES 0x40000 -#define MAX_MAP_PORTALS 0x20000 -#define MAX_MAP_LIGHTING 0x800000 -#define MAX_MAP_LIGHTGRID 0x800000 -#define MAX_MAP_VISIBILITY 0x200000 - -#define MAX_MAP_DRAW_SURFS 0x20000 -#define MAX_MAP_DRAW_VERTS 0x80000 -#define MAX_MAP_DRAW_INDEXES 0x80000 - - -// key / value pair sizes in the entities lump -#define MAX_KEY 32 -#define MAX_VALUE 1024 - -// the editor uses these predefined yaw angles to orient entities up or down -#define ANGLE_UP -1 -#define ANGLE_DOWN -2 - -#define LIGHTMAP_WIDTH 128 -#define LIGHTMAP_HEIGHT 128 - -#define MAX_WORLD_COORD ( 128*1024 ) -#define MIN_WORLD_COORD ( -128*1024 ) -#define WORLD_SIZE ( MAX_WORLD_COORD - MIN_WORLD_COORD ) - -//============================================================================= - - -typedef struct { - int fileofs, filelen; -} lump_t; - -#define LUMP_ENTITIES 0 -#define LUMP_SHADERS 1 -#define LUMP_PLANES 2 -#define LUMP_NODES 3 -#define LUMP_LEAFS 4 -#define LUMP_LEAFSURFACES 5 -#define LUMP_LEAFBRUSHES 6 -#define LUMP_MODELS 7 -#define LUMP_BRUSHES 8 -#define LUMP_BRUSHSIDES 9 -#define LUMP_DRAWVERTS 10 -#define LUMP_DRAWINDEXES 11 -#define LUMP_FOGS 12 -#define LUMP_SURFACES 13 -#define LUMP_LIGHTMAPS 14 -#define LUMP_LIGHTGRID 15 -#define LUMP_VISIBILITY 16 -#define HEADER_LUMPS 17 - -typedef struct { - int ident; - int version; - - lump_t lumps[HEADER_LUMPS]; -} dheader_t; - -typedef struct { - float mins[3], maxs[3]; - int firstSurface, numSurfaces; - int firstBrush, numBrushes; -} dmodel_t; - -typedef struct { - char shader[MAX_QPATH]; - int surfaceFlags; - int contentFlags; -} dshader_t; - -// planes x^1 is allways the opposite of plane x - -typedef struct { - float normal[3]; - float dist; -} dplane_t; - -typedef struct { - int planeNum; - int children[2]; // negative numbers are -(leafs+1), not nodes - int mins[3]; // for frustom culling - int maxs[3]; -} dnode_t; - -typedef struct { - int cluster; // -1 = opaque cluster (do I still store these?) - int area; - - int mins[3]; // for frustum culling - int maxs[3]; - - int firstLeafSurface; - int numLeafSurfaces; - - int firstLeafBrush; - int numLeafBrushes; -} dleaf_t; - -typedef struct { - int planeNum; // positive plane side faces out of the leaf - int shaderNum; -} dbrushside_t; - -typedef struct { - int firstSide; - int numSides; - int shaderNum; // the shader that determines the contents flags -} dbrush_t; - -typedef struct { - char shader[MAX_QPATH]; - int brushNum; - int visibleSide; // the brush side that ray tests need to clip against (-1 == none) -} dfog_t; - -typedef struct { - vec3_t xyz; - float st[2]; - float lightmap[2]; - vec3_t normal; - byte color[4]; -} drawVert_t; - -typedef enum { - MST_BAD, - MST_PLANAR, - MST_PATCH, - MST_TRIANGLE_SOUP, - MST_FLARE -} mapSurfaceType_t; - -typedef struct { - int shaderNum; - int fogNum; - int surfaceType; - - int firstVert; - int numVerts; - - int firstIndex; - int numIndexes; - - int lightmapNum; - int lightmapX, lightmapY; - int lightmapWidth, lightmapHeight; - - vec3_t lightmapOrigin; - vec3_t lightmapVecs[3]; // for patches, [0] and [1] are lodbounds - - int patchWidth; - int patchHeight; -} dsurface_t; - - -#endif diff --git a/common/scriplib.c b/common/scriplib.c deleted file mode 100644 index 9d1f32c..0000000 --- a/common/scriplib.c +++ /dev/null @@ -1,375 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// scriplib.c - -#include "cmdlib.h" -#include "scriplib.h" - -/* -============================================================================= - - PARSING STUFF - -============================================================================= -*/ - -typedef struct -{ - char filename[1024]; - char *buffer,*script_p,*end_p; - int line; -} script_t; - -#define MAX_INCLUDES 8 -script_t scriptstack[MAX_INCLUDES]; -script_t *script; -int scriptline; - -char token[MAXTOKEN]; -qboolean endofscript; -qboolean tokenready; // only qtrue if UnGetToken was just called - -/* -============== -AddScriptToStack -============== -*/ -void AddScriptToStack( const char *filename ) { - int size; - - script++; - if (script == &scriptstack[MAX_INCLUDES]) - Error ("script file exceeded MAX_INCLUDES"); - strcpy (script->filename, ExpandPath (filename) ); - - size = LoadFile (script->filename, (void **)&script->buffer); - - printf ("entering %s\n", script->filename); - - script->line = 1; - - script->script_p = script->buffer; - script->end_p = script->buffer + size; -} - - -/* -============== -LoadScriptFile -============== -*/ -void LoadScriptFile( const char *filename ) { - script = scriptstack; - AddScriptToStack (filename); - - endofscript = qfalse; - tokenready = qfalse; -} - - -/* -============== -ParseFromMemory -============== -*/ -void ParseFromMemory (char *buffer, int size) -{ - script = scriptstack; - script++; - if (script == &scriptstack[MAX_INCLUDES]) - Error ("script file exceeded MAX_INCLUDES"); - strcpy (script->filename, "memory buffer" ); - - script->buffer = buffer; - script->line = 1; - script->script_p = script->buffer; - script->end_p = script->buffer + size; - - endofscript = qfalse; - tokenready = qfalse; -} - - -/* -============== -UnGetToken - -Signals that the current token was not used, and should be reported -for the next GetToken. Note that - -GetToken (qtrue); -UnGetToken (); -GetToken (qfalse); - -could cross a line boundary. -============== -*/ -void UnGetToken (void) -{ - tokenready = qtrue; -} - - -qboolean EndOfScript (qboolean crossline) -{ - if (!crossline) - Error ("Line %i is incomplete\n",scriptline); - - if (!strcmp (script->filename, "memory buffer")) - { - endofscript = qtrue; - return qfalse; - } - - free (script->buffer); - if (script == scriptstack+1) - { - endofscript = qtrue; - return qfalse; - } - script--; - scriptline = script->line; - printf ("returning to %s\n", script->filename); - return GetToken (crossline); -} - -/* -============== -GetToken -============== -*/ -qboolean GetToken (qboolean crossline) -{ - char *token_p; - - if (tokenready) // is a token allready waiting? - { - tokenready = qfalse; - return qtrue; - } - - if (script->script_p >= script->end_p) - return EndOfScript (crossline); - -// -// skip space -// -skipspace: - while (*script->script_p <= 32) - { - if (script->script_p >= script->end_p) - return EndOfScript (crossline); - if (*script->script_p++ == '\n') - { - if (!crossline) - Error ("Line %i is incomplete\n",scriptline); - scriptline = script->line++; - } - } - - if (script->script_p >= script->end_p) - return EndOfScript (crossline); - - // ; # // comments - if (*script->script_p == ';' || *script->script_p == '#' - || ( script->script_p[0] == '/' && script->script_p[1] == '/') ) - { - if (!crossline) - Error ("Line %i is incomplete\n",scriptline); - while (*script->script_p++ != '\n') - if (script->script_p >= script->end_p) - return EndOfScript (crossline); - scriptline = script->line++; - goto skipspace; - } - - // /* */ comments - if (script->script_p[0] == '/' && script->script_p[1] == '*') - { - if (!crossline) - Error ("Line %i is incomplete\n",scriptline); - script->script_p+=2; - while (script->script_p[0] != '*' && script->script_p[1] != '/') - { - if ( *script->script_p == '\n' ) { - scriptline = script->line++; - } - script->script_p++; - if (script->script_p >= script->end_p) - return EndOfScript (crossline); - } - script->script_p += 2; - goto skipspace; - } - -// -// copy token -// - token_p = token; - - if (*script->script_p == '"') - { - // quoted token - script->script_p++; - while (*script->script_p != '"') - { - *token_p++ = *script->script_p++; - if (script->script_p == script->end_p) - break; - if (token_p == &token[MAXTOKEN]) - Error ("Token too large on line %i\n",scriptline); - } - script->script_p++; - } - else // regular token - while ( *script->script_p > 32 && *script->script_p != ';') - { - *token_p++ = *script->script_p++; - if (script->script_p == script->end_p) - break; - if (token_p == &token[MAXTOKEN]) - Error ("Token too large on line %i\n",scriptline); - } - - *token_p = 0; - - if (!strcmp (token, "$include")) - { - GetToken (qfalse); - AddScriptToStack (token); - return GetToken (crossline); - } - - return qtrue; -} - - -/* -============== -TokenAvailable - -Returns qtrue if there is another token on the line -============== -*/ -qboolean TokenAvailable (void) { - int oldLine; - qboolean r; - - oldLine = script->line; - r = GetToken( qtrue ); - if ( !r ) { - return qfalse; - } - UnGetToken(); - if ( oldLine == script->line ) { - return qtrue; - } - return qfalse; -} - - -//===================================================================== - - -void MatchToken( char *match ) { - GetToken( qtrue ); - - if ( strcmp( token, match ) ) { - Error( "MatchToken( \"%s\" ) failed at line %i", match, scriptline ); - } -} - - -void Parse1DMatrix (int x, vec_t *m) { - int i; - - MatchToken( "(" ); - - for (i = 0 ; i < x ; i++) { - GetToken( qfalse ); - m[i] = atof(token); - } - - MatchToken( ")" ); -} - -void Parse2DMatrix (int y, int x, vec_t *m) { - int i; - - MatchToken( "(" ); - - for (i = 0 ; i < y ; i++) { - Parse1DMatrix (x, m + i * x); - } - - MatchToken( ")" ); -} - -void Parse3DMatrix (int z, int y, int x, vec_t *m) { - int i; - - MatchToken( "(" ); - - for (i = 0 ; i < z ; i++) { - Parse2DMatrix (y, x, m + i * x*y); - } - - MatchToken( ")" ); -} - - -void Write1DMatrix (FILE *f, int x, vec_t *m) { - int i; - - fprintf (f, "( "); - for (i = 0 ; i < x ; i++) { - if (m[i] == (int)m[i] ) { - fprintf (f, "%i ", (int)m[i]); - } else { - fprintf (f, "%f ", m[i]); - } - } - fprintf (f, ")"); -} - -void Write2DMatrix (FILE *f, int y, int x, vec_t *m) { - int i; - - fprintf (f, "( "); - for (i = 0 ; i < y ; i++) { - Write1DMatrix (f, x, m + i*x); - fprintf (f, " "); - } - fprintf (f, ")\n"); -} - - -void Write3DMatrix (FILE *f, int z, int y, int x, vec_t *m) { - int i; - - fprintf (f, "(\n"); - for (i = 0 ; i < z ; i++) { - Write2DMatrix (f, y, x, m + i*(x*y) ); - } - fprintf (f, ")\n"); -} - diff --git a/common/scriplib.h b/common/scriplib.h deleted file mode 100644 index b68076b..0000000 --- a/common/scriplib.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// scriplib.h - -#ifndef __CMDLIB__ -#include "cmdlib.h" -#endif -#ifndef __MATHLIB__ -#include "mathlib.h" -#endif - -#define MAXTOKEN 1024 - -extern char token[MAXTOKEN]; -extern char *scriptbuffer,*script_p,*scriptend_p; -extern int grabbed; -extern int scriptline; -extern qboolean endofscript; - - -void LoadScriptFile( const char *filename ); -void ParseFromMemory (char *buffer, int size); - -qboolean GetToken (qboolean crossline); -void UnGetToken (void); -qboolean TokenAvailable (void); - -void MatchToken( char *match ); - -void Parse1DMatrix (int x, vec_t *m); -void Parse2DMatrix (int y, int x, vec_t *m); -void Parse3DMatrix (int z, int y, int x, vec_t *m); - -void Write1DMatrix (FILE *f, int x, vec_t *m); -void Write2DMatrix (FILE *f, int y, int x, vec_t *m); -void Write3DMatrix (FILE *f, int z, int y, int x, vec_t *m); diff --git a/common/surfaceflags.h b/common/surfaceflags.h deleted file mode 100644 index 99c397b..0000000 --- a/common/surfaceflags.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// This file must be identical in the quake and utils directories - -// contents flags are seperate bits -// a given brush can contribute multiple content bits - -// these definitions also need to be in q_shared.h! - -#define CONTENTS_SOLID 1 // an eye is never valid in a solid -#define CONTENTS_LAVA 8 -#define CONTENTS_SLIME 16 -#define CONTENTS_WATER 32 -#define CONTENTS_FOG 64 - -#define CONTENTS_AREAPORTAL 0x8000 - -#define CONTENTS_PLAYERCLIP 0x10000 -#define CONTENTS_MONSTERCLIP 0x20000 -//bot specific contents types -#define CONTENTS_TELEPORTER 0x40000 -#define CONTENTS_JUMPPAD 0x80000 -#define CONTENTS_CLUSTERPORTAL 0x100000 -#define CONTENTS_DONOTENTER 0x200000 - -#define CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity - -#define CONTENTS_BODY 0x2000000 // should never be on a brush, only in game -#define CONTENTS_CORPSE 0x4000000 -#define CONTENTS_DETAIL 0x8000000 // brushes not used for the bsp -#define CONTENTS_STRUCTURAL 0x10000000 // brushes used for the bsp -#define CONTENTS_TRANSLUCENT 0x20000000 // don't consume surface fragments inside -#define CONTENTS_TRIGGER 0x40000000 -#define CONTENTS_NODROP 0x80000000 // don't leave bodies or items (death fog, lava) - -#define SURF_NODAMAGE 0x1 // never give falling damage -#define SURF_SLICK 0x2 // effects game physics -#define SURF_SKY 0x4 // lighting from environment map -#define SURF_LADDER 0x8 -#define SURF_NOIMPACT 0x10 // don't make missile explosions -#define SURF_NOMARKS 0x20 // don't leave missile marks -#define SURF_FLESH 0x40 // make flesh sounds and effects -#define SURF_NODRAW 0x80 // don't generate a drawsurface at all -#define SURF_HINT 0x100 // make a primary bsp splitter -#define SURF_SKIP 0x200 // completely ignore, allowing non-closed brushes -#define SURF_NOLIGHTMAP 0x400 // surface doesn't need a lightmap -#define SURF_POINTLIGHT 0x800 // generate lighting info at vertexes -#define SURF_METALSTEPS 0x1000 // clanking footsteps -#define SURF_NOSTEPS 0x2000 // no footstep sounds -#define SURF_NONSOLID 0x4000 // don't collide against curves with this set -#define SURF_LIGHTFILTER 0x8000 // act as a light filter during q3map -light -#define SURF_ALPHASHADOW 0x10000 // do per-pixel light shadow casting in q3map -#define SURF_NODLIGHT 0x20000 // never add dynamic lights diff --git a/common/threads.c b/common/threads.c deleted file mode 100644 index 4284f73..0000000 --- a/common/threads.c +++ /dev/null @@ -1,441 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "cmdlib.h" -#include "threads.h" - -#define MAX_THREADS 64 - -int dispatch; -int workcount; -int oldf; -qboolean pacifier; - -qboolean threaded; - -/* -============= -GetThreadWork - -============= -*/ -int GetThreadWork (void) -{ - int r; - int f; - - ThreadLock (); - - if (dispatch == workcount) - { - ThreadUnlock (); - return -1; - } - - f = 10*dispatch / workcount; - if (f != oldf) - { - oldf = f; - if (pacifier) - _printf ("%i...", f); - } - - r = dispatch; - dispatch++; - ThreadUnlock (); - - return r; -} - - -void (*workfunction) (int); - -void ThreadWorkerFunction (int threadnum) -{ - int work; - - while (1) - { - work = GetThreadWork (); - if (work == -1) - break; -//_printf ("thread %i, work %i\n", threadnum, work); - workfunction(work); - } -} - -void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int)) -{ - if (numthreads == -1) - ThreadSetDefault (); - workfunction = func; - RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction); -} - - -/* -=================================================================== - -WIN32 - -=================================================================== -*/ -#ifdef WIN32 - -#define USED - -#include <windows.h> - -int numthreads = -1; -CRITICAL_SECTION crit; -static int enter; - -void ThreadSetDefault (void) -{ - SYSTEM_INFO info; - - if (numthreads == -1) // not set manually - { - GetSystemInfo (&info); - numthreads = info.dwNumberOfProcessors; - if (numthreads < 1 || numthreads > 32) - numthreads = 1; - } - - qprintf ("%i threads\n", numthreads); -} - - -void ThreadLock (void) -{ - if (!threaded) - return; - EnterCriticalSection (&crit); - if (enter) - Error ("Recursive ThreadLock\n"); - enter = 1; -} - -void ThreadUnlock (void) -{ - if (!threaded) - return; - if (!enter) - Error ("ThreadUnlock without lock\n"); - enter = 0; - LeaveCriticalSection (&crit); -} - -/* -============= -RunThreadsOn -============= -*/ -void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int)) -{ - int threadid[MAX_THREADS]; - HANDLE threadhandle[MAX_THREADS]; - int i; - int start, end; - - start = I_FloatTime (); - dispatch = 0; - workcount = workcnt; - oldf = -1; - pacifier = showpacifier; - threaded = qtrue; - - // - // run threads in parallel - // - InitializeCriticalSection (&crit); - - if (numthreads == 1) - { // use same thread - func (0); - } - else - { - for (i=0 ; i<numthreads ; i++) - { - threadhandle[i] = CreateThread( - NULL, // LPSECURITY_ATTRIBUTES lpsa, - 0, // DWORD cbStack, - (LPTHREAD_START_ROUTINE)func, // LPTHREAD_START_ROUTINE lpStartAddr, - (LPVOID)i, // LPVOID lpvThreadParm, - 0, // DWORD fdwCreate, - &threadid[i]); - } - - for (i=0 ; i<numthreads ; i++) - WaitForSingleObject (threadhandle[i], INFINITE); - } - DeleteCriticalSection (&crit); - - threaded = qfalse; - end = I_FloatTime (); - if (pacifier) - _printf (" (%i)\n", end-start); -} - - -#endif - -/* -=================================================================== - -OSF1 - -=================================================================== -*/ - -#ifdef __osf__ -#define USED - -int numthreads = 4; - -void ThreadSetDefault (void) -{ - if (numthreads == -1) // not set manually - { - numthreads = 4; - } -} - - -#include <pthread.h> - -pthread_mutex_t *my_mutex; - -void ThreadLock (void) -{ - if (my_mutex) - pthread_mutex_lock (my_mutex); -} - -void ThreadUnlock (void) -{ - if (my_mutex) - pthread_mutex_unlock (my_mutex); -} - - -/* -============= -RunThreadsOn -============= -*/ -void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int)) -{ - int i; - pthread_t work_threads[MAX_THREADS]; - pthread_addr_t status; - pthread_attr_t attrib; - pthread_mutexattr_t mattrib; - int start, end; - - start = I_FloatTime (); - dispatch = 0; - workcount = workcnt; - oldf = -1; - pacifier = showpacifier; - threaded = qtrue; - - if (pacifier) - setbuf (stdout, NULL); - - if (!my_mutex) - { - my_mutex = malloc (sizeof(*my_mutex)); - if (pthread_mutexattr_create (&mattrib) == -1) - Error ("pthread_mutex_attr_create failed"); - if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1) - Error ("pthread_mutexattr_setkind_np failed"); - if (pthread_mutex_init (my_mutex, mattrib) == -1) - Error ("pthread_mutex_init failed"); - } - - if (pthread_attr_create (&attrib) == -1) - Error ("pthread_attr_create failed"); - if (pthread_attr_setstacksize (&attrib, 0x100000) == -1) - Error ("pthread_attr_setstacksize failed"); - - for (i=0 ; i<numthreads ; i++) - { - if (pthread_create(&work_threads[i], attrib - , (pthread_startroutine_t)func, (pthread_addr_t)i) == -1) - Error ("pthread_create failed"); - } - - for (i=0 ; i<numthreads ; i++) - { - if (pthread_join (work_threads[i], &status) == -1) - Error ("pthread_join failed"); - } - - threaded = qfalse; - - end = I_FloatTime (); - if (pacifier) - _printf (" (%i)\n", end-start); -} - - -#endif - -/* -=================================================================== - -IRIX - -=================================================================== -*/ - -#ifdef _MIPS_ISA -#define USED - -#include <task.h> -#include <abi_mutex.h> -#include <sys/types.h> -#include <sys/prctl.h> - - -int numthreads = -1; -abilock_t lck; - -void ThreadSetDefault (void) -{ - if (numthreads == -1) - numthreads = prctl(PR_MAXPPROCS); - _printf ("%i threads\n", numthreads); - usconfig (CONF_INITUSERS, numthreads); -} - - -void ThreadLock (void) -{ - spin_lock (&lck); -} - -void ThreadUnlock (void) -{ - release_lock (&lck); -} - - -/* -============= -RunThreadsOn -============= -*/ -void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int)) -{ - int i; - int pid[MAX_THREADS]; - int start, end; - - start = I_FloatTime (); - dispatch = 0; - workcount = workcnt; - oldf = -1; - pacifier = showpacifier; - threaded = qtrue; - - if (pacifier) - setbuf (stdout, NULL); - - init_lock (&lck); - - for (i=0 ; i<numthreads-1 ; i++) - { - pid[i] = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)i - , NULL, 0x200000); // 2 meg stacks - if (pid[i] == -1) - { - perror ("sproc"); - Error ("sproc failed"); - } - } - - func(i); - - for (i=0 ; i<numthreads-1 ; i++) - wait (NULL); - - threaded = qfalse; - - end = I_FloatTime (); - if (pacifier) - _printf (" (%i)\n", end-start); -} - - -#endif - -/* -======================================================================= - - SINGLE THREAD - -======================================================================= -*/ - -#ifndef USED - -int numthreads = 1; - -void ThreadSetDefault (void) -{ - numthreads = 1; -} - -void ThreadLock (void) -{ -} - -void ThreadUnlock (void) -{ -} - -/* -============= -RunThreadsOn -============= -*/ -void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int)) -{ - int i; - int start, end; - - dispatch = 0; - workcount = workcnt; - oldf = -1; - pacifier = showpacifier; - start = I_FloatTime (); - func(0); - - end = I_FloatTime (); - if (pacifier) - _printf (" (%i)\n", end-start); -} - -#endif diff --git a/common/threads.h b/common/threads.h deleted file mode 100644 index 189620f..0000000 --- a/common/threads.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -extern int numthreads; - -void ThreadSetDefault (void); -int GetThreadWork (void); -void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int)); -void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int)); -void ThreadLock (void); -void ThreadUnlock (void); - diff --git a/common/trilib.c b/common/trilib.c deleted file mode 100644 index 07f5fdb..0000000 --- a/common/trilib.c +++ /dev/null @@ -1,231 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// -// trilib.c: library for loading triangles from an Alias triangle file -// - -#include <stdio.h> -#include "cmdlib.h" -#include "mathlib.h" -#include "polyset.h" -#include "trilib.h" - -// on disk representation of a face - - -#define FLOAT_START 99999.0 -#define FLOAT_END -FLOAT_START -#define MAGIC 123322 - -//#define NOISY 1 - -typedef struct { - float v[3]; -} vector; - -typedef struct -{ - vector n; /* normal */ - vector p; /* point */ - vector c; /* color */ - float u; /* u */ - float v; /* v */ -} aliaspoint_t; - -typedef struct { - aliaspoint_t pt[3]; -} tf_triangle; - - -static void ByteSwapTri (tf_triangle *tri) -{ - int i; - - for (i=0 ; i<sizeof(tf_triangle)/4 ; i++) - { - ((int *)tri)[i] = BigLong (((int *)tri)[i]); - } -} - -static void ReadPolysetGeometry( triangle_t *tripool, FILE *input, int count, triangle_t *ptri ) -{ - tf_triangle tri; - int i; - - for (i = 0; i < count; ++i) { - int j; - - fread( &tri, sizeof(tf_triangle), 1, input ); - ByteSwapTri (&tri); - for (j=0 ; j<3 ; j++) - { - int k; - - for (k=0 ; k<3 ; k++) - { - ptri->verts[j][k] = tri.pt[j].p.v[k]; - ptri->normals[j][k] = tri.pt[j].n.v[k]; -// ptri->colors[j][k] = tri.pt[j].c.v[k]; - } - - ptri->texcoords[j][0] = tri.pt[j].u; - ptri->texcoords[j][1] = tri.pt[j].v; - } - - ptri++; - if ((ptri - tripool ) >= POLYSET_MAXTRIANGLES) - Error ("Error: too many triangles; increase POLYSET_MAXTRIANGLES\n"); - } -} - -void TRI_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets ) -{ - FILE *input; - float start; - char name[256], tex[256]; - int i, count, magic, pset = 0; - triangle_t *ptri; - polyset_t *pPSET; - int iLevel; - int exitpattern; - float t; - - t = -FLOAT_START; - *((unsigned char *)&exitpattern + 0) = *((unsigned char *)&t + 3); - *((unsigned char *)&exitpattern + 1) = *((unsigned char *)&t + 2); - *((unsigned char *)&exitpattern + 2) = *((unsigned char *)&t + 1); - *((unsigned char *)&exitpattern + 3) = *((unsigned char *)&t + 0); - - if ((input = fopen(filename, "rb")) == 0) - Error ("reader: could not open file '%s'", filename); - - iLevel = 0; - - fread(&magic, sizeof(int), 1, input); - if (BigLong(magic) != MAGIC) - Error ("%s is not a Alias object separated triangle file, magic number is wrong.", filename); - - pPSET = calloc( 1, POLYSET_MAXPOLYSETS * sizeof( polyset_t ) ); - ptri = calloc( 1, POLYSET_MAXTRIANGLES * sizeof( triangle_t ) ); - - *ppPSET = pPSET; - - while (feof(input) == 0) { - if (fread(&start, sizeof(float), 1, input) < 1) - break; - *(int *)&start = BigLong(*(int *)&start); - if (*(int *)&start != exitpattern) - { - if (start == FLOAT_START) { - /* Start of an object or group of objects. */ - i = -1; - do { - /* There are probably better ways to read a string from */ - /* a file, but this does allow you to do error checking */ - /* (which I'm not doing) on a per character basis. */ - ++i; - fread( &(name[i]), sizeof( char ), 1, input); - } while( name[i] != '\0' ); - - if ( i != 0 ) - strncpy( pPSET[pset].name, name, sizeof( pPSET[pset].name ) - 1 ); - else - strcpy( pPSET[pset].name , "(unnamed)" ); - strlwr( pPSET[pset].name ); - -// indent(); -// fprintf(stdout,"OBJECT START: %s\n",name); - fread( &count, sizeof(int), 1, input); - count = BigLong(count); - ++iLevel; - if (count != 0) { -// indent(); -// fprintf(stdout,"NUMBER OF TRIANGLES: %d\n",count); - - i = -1; - do { - ++i; - fread( &(tex[i]), sizeof( char ), 1, input); - } while( tex[i] != '\0' ); - -/* - if ( i != 0 ) - strncpy( pPSET[pset].texname, tex, sizeof( pPSET[pset].texname ) - 1 ); - else - strcpy( pPSET[pset].texname, "(unnamed)" ); - strlwr( pPSET[pset].texname ); -*/ - -// indent(); -// fprintf(stdout," Object texture name: '%s'\n",tex); - } - - /* Else (count == 0) this is the start of a group, and */ - /* no texture name is present. */ - } - else if (start == FLOAT_END) { - /* End of an object or group. Yes, the name should be */ - /* obvious from context, but it is in here just to be */ - /* safe and to provide a little extra information for */ - /* those who do not wish to write a recursive reader. */ - /* Mea culpa. */ - --iLevel; - i = -1; - do { - ++i; - fread( &(name[i]), sizeof( char ), 1, input); - } while( name[i] != '\0' ); - - if ( i != 0 ) - strncpy( pPSET[pset].name, name, sizeof( pPSET[pset].name ) - 1 ); - else - strcpy( pPSET[pset].name , "(unnamed)" ); - - strlwr( pPSET[pset].name ); - -// indent(); -// fprintf(stdout,"OBJECT END: %s\n",name); - continue; - } - } - -// -// read the triangles -// - if ( count > 0 ) - { - pPSET[pset].triangles = ptri; - ReadPolysetGeometry( pPSET[0].triangles, input, count, ptri ); - ptri += count; - pPSET[pset].numtriangles = count; - if ( ++pset >= POLYSET_MAXPOLYSETS ) - { - Error ("Error: too many polysets; increase POLYSET_MAXPOLYSETS\n"); - } - } - } - - *numpsets = pset; - - fclose (input); -} - diff --git a/common/trilib.h b/common/trilib.h deleted file mode 100644 index 8938ac4..0000000 --- a/common/trilib.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// -// trilib.h: header file for loading triangles from an Alias triangle file -// -void TRI_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets ); - diff --git a/libs/cmdlib.h b/libs/cmdlib.h deleted file mode 100644 index 9c95d03..0000000 --- a/libs/cmdlib.h +++ /dev/null @@ -1,97 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// -// start of shared cmdlib stuff -// - -#ifndef __CMDLIB__ -#define __CMDLIB__ - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <errno.h> -#include <ctype.h> -#include <time.h> -#include <stdarg.h> - -#ifndef __BYTEBOOL__ -#define __BYTEBOOL__ - -#ifndef __cplusplus - typedef enum {false, true} boolean; -#else - typedef unsigned char boolean; -#endif - - -typedef unsigned char byte; -//typedef unsigned char byte; -#endif - -FILE *SafeOpenWrite (const char *filename); -FILE *SafeOpenRead (const char *filename); -void SafeRead (FILE *f, void *buffer, int count); -void SafeWrite (FILE *f, const void *buffer, int count); -int LoadFile (const char *filename, void **bufferptr); -int LoadFileNoCrash (const char *filename, void **bufferptr); -void SaveFile (const char *filename, void *buffer, int count); -void DefaultExtension (char *path, char *extension); -void DefaultPath (char *path, char *basepath); -void StripFilename (char *path); -void StripExtension (char *path); -void ExtractFilePath (const char *path, char *dest); -void ExtractFileName (const char *path, char *dest); -void ExtractFileBase (const char *path, char *dest); -void ExtractFileExtension (const char *path, char *dest); -short BigShort (short l); -short LittleShort (short l); -int BigLong (int l); -int LittleLong (int l); -float BigFloat (float l); -float LittleFloat (float l); -void *qmalloc (size_t size); -void* qblockmalloc(size_t nSize); - - - -// error and printf functions -typedef void (PFN_ERR)(const char *pFormat, ...); -typedef void (PFN_PRINTF)(const char *pFormat, ...); -typedef void (PFN_ERR_NUM)(int nNum, const char *pFormat, ...); -typedef void (PFN_PRINTF_NUM)(int nNum, const char *pFormat, ...); - -void Error(const char *pFormat, ...); -void Printf(const char *pFormat, ...); -void ErrorNum(int n, const char *pFormat, ...); -void PrintfNum(int n, const char *pFormat, ...); - -void SetErrorHandler(PFN_ERR pe); -void SetPrintfHandler(PFN_PRINTF pe); -void SetErrorHandlerNum(PFN_ERR_NUM pe); -void SetPrintfHandlerNum(PFN_PRINTF_NUM pe); -void ConvertDOSToUnixName( char *dst, const char *src ); -char* StrDup(char* pStr); -char* StrDup(const char* pStr); - - -#endif
\ No newline at end of file diff --git a/libs/cmdlib/cmdlib.cpp b/libs/cmdlib/cmdlib.cpp deleted file mode 100644 index 15cf3f6..0000000 --- a/libs/cmdlib/cmdlib.cpp +++ /dev/null @@ -1,550 +0,0 @@ -// -// start of shared cmdlib stuff -// - - -#include "cmdlib.h" -#include "windows.h" - -#define PATHSEPERATOR '/' - -// rad additions -// 11.29.99 -PFN_ERR *g_pfnError = NULL; -PFN_PRINTF *g_pfnPrintf = NULL; -PFN_ERR_NUM *g_pfnErrorNum = NULL; -PFN_PRINTF_NUM *g_pfnPrintfNum = NULL; - - -void Error(const char *pFormat, ...) -{ - if (g_pfnError) - { - va_list arg_ptr; - va_start(arg_ptr, pFormat); - g_pfnError(pFormat, arg_ptr); - va_end(arg_ptr); - } -} - -void Printf(const char *pFormat, ...) -{ - if (g_pfnPrintf) - { - va_list arg_ptr; - va_start(arg_ptr, pFormat); - g_pfnPrintf(pFormat, arg_ptr); - va_end(arg_ptr); - } -} - -void ErrorNum(int nErr, const char *pFormat, ...) -{ - if (g_pfnErrorNum) - { - va_list arg_ptr; - va_start(arg_ptr, pFormat); - g_pfnErrorNum(nErr, pFormat, arg_ptr); - va_end(arg_ptr); - } -} - -void PrintfNum(int nErr, const char *pFormat, ...) -{ - if (g_pfnPrintfNum) - { - va_list arg_ptr; - va_start(arg_ptr, pFormat); - g_pfnPrintfNum(nErr, pFormat, arg_ptr); - va_end(arg_ptr); - } -} - - - -void SetErrorHandler(PFN_ERR pe) -{ - g_pfnError = pe; -} - -void SetPrintfHandler(PFN_PRINTF pe) -{ - g_pfnPrintf = pe; -} - -void SetErrorHandlerNum(PFN_ERR_NUM pe) -{ - g_pfnErrorNum = pe; -} - -void SetPrintfHandler(PFN_PRINTF_NUM pe) -{ - g_pfnPrintfNum = pe; -} - - - -// rad end - -#define MEM_BLOCKSIZE 4096 -void* qblockmalloc(size_t nSize) -{ - void *b; - // round up to threshold - int nAllocSize = nSize % MEM_BLOCKSIZE; - if ( nAllocSize > 0) - { - nSize += MEM_BLOCKSIZE - nAllocSize; - } - b = malloc(nSize + 1); - memset (b, 0, nSize); - return b; -} - -void* qmalloc (size_t nSize) -{ - void *b; - b = malloc(nSize + 1); - memset (b, 0, nSize); - return b; -} - -/* -================ -Q_filelength -================ -*/ -int Q_filelength (FILE *f) -{ - int pos; - int end; - - pos = ftell (f); - fseek (f, 0, SEEK_END); - end = ftell (f); - fseek (f, pos, SEEK_SET); - - return end; -} - - -// FIXME: need error handler -FILE *SafeOpenWrite (const char *filename) -{ - FILE *f; - - f = fopen(filename, "wb"); - - if (!f) - { - Error ("Error opening %s: %s",filename,strerror(errno)); - } - - return f; -} - -FILE *SafeOpenRead (const char *filename) -{ - FILE *f; - - f = fopen(filename, "rb"); - - if (!f) - { - Error ("Error opening %s: %s",filename,strerror(errno)); - } - - return f; -} - - -void SafeRead (FILE *f, void *buffer, int count) -{ - if ( (int)fread (buffer, 1, count, f) != count) - Error ("File read failure"); -} - - -void SafeWrite (FILE *f, const void *buffer, int count) -{ - if ( (int)fwrite (buffer, 1, count, f) != count) - Error ("File read failure"); -} - - - -/* -============== -LoadFile -============== -*/ -int LoadFile (const char *filename, void **bufferptr) -{ - FILE *f; - int length; - void *buffer; - - *bufferptr = NULL; - - if (filename == NULL || strlen(filename) == 0) - { - return -1; - } - - f = fopen (filename, "rb"); - if (!f) - { - return -1; - } - length = Q_filelength (f); - buffer = qblockmalloc (length+1); - ((char *)buffer)[length] = 0; - SafeRead (f, buffer, length); - fclose (f); - - *bufferptr = buffer; - return length; -} - - -/* -============== -LoadFileNoCrash - -returns -1 length if not present -============== -*/ -int LoadFileNoCrash (const char *filename, void **bufferptr) -{ - FILE *f; - int length; - void *buffer; - - f = fopen (filename, "rb"); - if (!f) - return -1; - length = Q_filelength (f); - buffer = qmalloc (length+1); - ((char *)buffer)[length] = 0; - SafeRead (f, buffer, length); - fclose (f); - - *bufferptr = buffer; - return length; -} - - -/* -============== -SaveFile -============== -*/ -void SaveFile (const char *filename, void *buffer, int count) -{ - FILE *f; - - f = SafeOpenWrite (filename); - SafeWrite (f, buffer, count); - fclose (f); -} - - - -void DefaultExtension (char *path, char *extension) -{ - char *src; -// -// if path doesn't have a .EXT, append extension -// (extension should include the .) -// - src = path + strlen(path) - 1; - - while (*src != PATHSEPERATOR && src != path) - { - if (*src == '.') - return; // it has an extension - src--; - } - - strcat (path, extension); -} - - -void DefaultPath (char *path, char *basepath) -{ - char temp[128]; - - if (path[0] == PATHSEPERATOR) - return; // absolute path location - strcpy (temp,path); - strcpy (path,basepath); - strcat (path,temp); -} - - -void StripFilename (char *path) -{ - int length; - - length = strlen(path)-1; - while (length > 0 && path[length] != PATHSEPERATOR) - length--; - path[length] = 0; -} - -void StripExtension (char *path) -{ - int length; - - length = strlen(path)-1; - while (length > 0 && path[length] != '.') - { - length--; - if (path[length] == '/') - return; // no extension - } - if (length) - path[length] = 0; -} - - -/* -==================== -Extract file parts -==================== -*/ -void ExtractFilePath (const char *path, char *dest) -{ - const char *src; - - src = path + strlen(path) - 1; - -// -// back up until a \ or the start -// - while (src != path && *(src-1) != PATHSEPERATOR) - src--; - - memcpy (dest, path, src-path); - dest[src-path] = 0; -} - -void ExtractFileName (const char *path, char *dest) -{ - const char *src; - - src = path + strlen(path) - 1; - -// -// back up until a \ or the start -// - while (src != path && *(src-1) != '/' - && *(src-1) != '\\' ) - src--; - - while (*src) - { - *dest++ = *src++; - } - *dest = 0; -} - -void ExtractFileBase (const char *path, char *dest) -{ - const char *src; - - src = path + strlen(path) - 1; - -// -// back up until a \ or the start -// - while (src != path && *(src-1) != '/' - && *(src-1) != '\\' ) - src--; - - while (*src && *src != '.') - { - *dest++ = *src++; - } - *dest = 0; -} - -void ExtractFileExtension (const char *path, char *dest) -{ - const char *src; - - src = path + strlen(path) - 1; - -// -// back up until a . or the start -// - while (src != path && *(src-1) != '.') - src--; - if (src == path) - { - *dest = 0; // no extension - return; - } - - strcpy (dest,src); -} - - -void ConvertDOSToUnixName( char *dst, const char *src ) -{ - while ( *src ) - { - if ( *src == '\\' ) - *dst = '/'; - else - *dst = *src; - dst++; src++; - } - *dst = 0; -} - - -char* StrDup(char* pStr) -{ - if (pStr) - { - return strcpy(new char[strlen(pStr)+1], pStr); - } - return NULL; -} - -char* StrDup(const char* pStr) -{ - if (pStr) - { - return strcpy(new char[strlen(pStr)+1], pStr); - } - return NULL; -} - - -/* -============================================================================ - - BYTE ORDER FUNCTIONS - -============================================================================ -*/ - -#ifdef _SGI_SOURCE -#define __BIG_ENDIAN__ -#endif - -#ifdef __BIG_ENDIAN__ - -short LittleShort (short l) -{ - byte b1,b2; - - b1 = l&255; - b2 = (l>>8)&255; - - return (b1<<8) + b2; -} - -short BigShort (short l) -{ - return l; -} - - -int LittleLong (int l) -{ - byte b1,b2,b3,b4; - - b1 = l&255; - b2 = (l>>8)&255; - b3 = (l>>16)&255; - b4 = (l>>24)&255; - - return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; -} - -int BigLong (int l) -{ - return l; -} - - -float LittleFloat (float l) -{ - union {byte b[4]; float f;} in, out; - - in.f = l; - out.b[0] = in.b[3]; - out.b[1] = in.b[2]; - out.b[2] = in.b[1]; - out.b[3] = in.b[0]; - - return out.f; -} - -float BigFloat (float l) -{ - return l; -} - - -#else - - -short BigShort (short l) -{ - byte b1,b2; - - b1 = l&255; - b2 = (l>>8)&255; - - return (b1<<8) + b2; -} - -short LittleShort (short l) -{ - return l; -} - - -int BigLong (int l) -{ - byte b1,b2,b3,b4; - - b1 = l&255; - b2 = (l>>8)&255; - b3 = (l>>16)&255; - b4 = (l>>24)&255; - - return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; -} - -int LittleLong (int l) -{ - return l; -} - -float BigFloat (float l) -{ - union {byte b[4]; float f;} in, out; - - in.f = l; - out.b[0] = in.b[3]; - out.b[1] = in.b[2]; - out.b[2] = in.b[1]; - out.b[3] = in.b[0]; - - return out.f; -} - -float LittleFloat (float l) -{ - return l; -} - - - -#endif - diff --git a/libs/cmdlib/cmdlib.vcproj b/libs/cmdlib/cmdlib.vcproj deleted file mode 100644 index b5a58d8..0000000 --- a/libs/cmdlib/cmdlib.vcproj +++ /dev/null @@ -1,156 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="7.10" - Name="cmdlib" - SccProjectName=""$/source/q3radiant", FEFAAAAA" - SccLocalPath="..\..\q3radiant"> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <Configurations> - <Configuration - Name="Release|Win32" - OutputDirectory=".\Release" - IntermediateDirectory=".\Release" - ConfigurationType="4" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - InlineFunctionExpansion="1" - AdditionalIncludeDirectories=".." - PreprocessorDefinitions="WIN32;NDEBUG;_LIB" - StringPooling="TRUE" - RuntimeLibrary="0" - EnableFunctionLevelLinking="TRUE" - RuntimeTypeInfo="TRUE" - UsePrecompiledHeader="2" - PrecompiledHeaderFile=".\Release/cmdlib.pch" - AssemblerListingLocation=".\Release/" - ObjectFile=".\Release/" - ProgramDataBaseFileName=".\Release/" - WarningLevel="3" - SuppressStartupBanner="TRUE" - CompileAs="0"/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCLibrarianTool" - OutputFile="..\cmdlib.lib" - SuppressStartupBanner="TRUE"/> - <Tool - Name="VCMIDLTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="NDEBUG" - Culture="1033"/> - <Tool - Name="VCWebServiceProxyGeneratorTool"/> - <Tool - Name="VCXMLDataGeneratorTool"/> - <Tool - Name="VCManagedWrapperGeneratorTool"/> - <Tool - Name="VCAuxiliaryManagedWrapperGeneratorTool"/> - </Configuration> - <Configuration - Name="Debug|Win32" - OutputDirectory=".\Debug" - IntermediateDirectory=".\Debug" - ConfigurationType="4" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories=".." - PreprocessorDefinitions="WIN32;_DEBUG;_LIB" - BasicRuntimeChecks="3" - RuntimeLibrary="1" - RuntimeTypeInfo="TRUE" - UsePrecompiledHeader="2" - PrecompiledHeaderFile=".\Debug/cmdlib.pch" - AssemblerListingLocation=".\Debug/" - ObjectFile=".\Debug/" - ProgramDataBaseFileName=".\Debug/" - WarningLevel="3" - SuppressStartupBanner="TRUE" - DebugInformationFormat="4" - CompileAs="0"/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCLibrarianTool" - OutputFile="..\cmdlibd.lib" - SuppressStartupBanner="TRUE"/> - <Tool - Name="VCMIDLTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="_DEBUG" - Culture="1033"/> - <Tool - Name="VCWebServiceProxyGeneratorTool"/> - <Tool - Name="VCXMLDataGeneratorTool"/> - <Tool - Name="VCManagedWrapperGeneratorTool"/> - <Tool - Name="VCAuxiliaryManagedWrapperGeneratorTool"/> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="Source Files" - Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"> - <File - RelativePath="cmdlib.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - </Filter> - <Filter - Name="Header Files" - Filter="h;hpp;hxx;hm;inl"> - <File - RelativePath="..\cmdlib.h"> - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/libs/jpeg6/README b/libs/jpeg6/README deleted file mode 100644 index 86cc206..0000000 --- a/libs/jpeg6/README +++ /dev/null @@ -1,385 +0,0 @@ -The Independent JPEG Group's JPEG software -========================================== - -README for release 6b of 27-Mar-1998 -==================================== - -This distribution contains the sixth public release of the Independent JPEG -Group's free JPEG software. You are welcome to redistribute this software and -to use it for any purpose, subject to the conditions under LEGAL ISSUES, below. - -Serious users of this software (particularly those incorporating it into -larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to -our electronic mailing list. Mailing list members are notified of updates -and have a chance to participate in technical discussions, etc. - -This software is the work of Tom Lane, Philip Gladstone, Jim Boucher, -Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, -Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG -Group. - -IJG is not affiliated with the official ISO JPEG standards committee. - - -DOCUMENTATION ROADMAP -===================== - -This file contains the following sections: - -OVERVIEW General description of JPEG and the IJG software. -LEGAL ISSUES Copyright, lack of warranty, terms of distribution. -REFERENCES Where to learn more about JPEG. -ARCHIVE LOCATIONS Where to find newer versions of this software. -RELATED SOFTWARE Other stuff you should get. -FILE FORMAT WARS Software *not* to get. -TO DO Plans for future IJG releases. - -Other documentation files in the distribution are: - -User documentation: - install.doc How to configure and install the IJG software. - usage.doc Usage instructions for cjpeg, djpeg, jpegtran, - rdjpgcom, and wrjpgcom. - *.1 Unix-style man pages for programs (same info as usage.doc). - wizard.doc Advanced usage instructions for JPEG wizards only. - change.log Version-to-version change highlights. -Programmer and internal documentation: - libjpeg.doc How to use the JPEG library in your own programs. - example.c Sample code for calling the JPEG library. - structure.doc Overview of the JPEG library's internal structure. - filelist.doc Road map of IJG files. - coderules.doc Coding style rules --- please read if you contribute code. - -Please read at least the files install.doc and usage.doc. Useful information -can also be found in the JPEG FAQ (Frequently Asked Questions) article. See -ARCHIVE LOCATIONS below to find out where to obtain the FAQ article. - -If you want to understand how the JPEG code works, we suggest reading one or -more of the REFERENCES, then looking at the documentation files (in roughly -the order listed) before diving into the code. - - -OVERVIEW -======== - -This package contains C software to implement JPEG image compression and -decompression. JPEG (pronounced "jay-peg") is a standardized compression -method for full-color and gray-scale images. JPEG is intended for compressing -"real-world" scenes; line drawings, cartoons and other non-realistic images -are not its strong suit. JPEG is lossy, meaning that the output image is not -exactly identical to the input image. Hence you must not use JPEG if you -have to have identical output bits. However, on typical photographic images, -very good compression levels can be obtained with no visible change, and -remarkably high compression levels are possible if you can tolerate a -low-quality image. For more details, see the references, or just experiment -with various compression settings. - -This software implements JPEG baseline, extended-sequential, and progressive -compression processes. Provision is made for supporting all variants of these -processes, although some uncommon parameter settings aren't implemented yet. -For legal reasons, we are not distributing code for the arithmetic-coding -variants of JPEG; see LEGAL ISSUES. We have made no provision for supporting -the hierarchical or lossless processes defined in the standard. - -We provide a set of library routines for reading and writing JPEG image files, -plus two sample applications "cjpeg" and "djpeg", which use the library to -perform conversion between JPEG and some other popular image file formats. -The library is intended to be reused in other applications. - -In order to support file conversion and viewing software, we have included -considerable functionality beyond the bare JPEG coding/decoding capability; -for example, the color quantization modules are not strictly part of JPEG -decoding, but they are essential for output to colormapped file formats or -colormapped displays. These extra functions can be compiled out of the -library if not required for a particular application. We have also included -"jpegtran", a utility for lossless transcoding between different JPEG -processes, and "rdjpgcom" and "wrjpgcom", two simple applications for -inserting and extracting textual comments in JFIF files. - -The emphasis in designing this software has been on achieving portability and -flexibility, while also making it fast enough to be useful. In particular, -the software is not intended to be read as a tutorial on JPEG. (See the -REFERENCES section for introductory material.) Rather, it is intended to -be reliable, portable, industrial-strength code. We do not claim to have -achieved that goal in every aspect of the software, but we strive for it. - -We welcome the use of this software as a component of commercial products. -No royalty is required, but we do ask for an acknowledgement in product -documentation, as described under LEGAL ISSUES. - - -LEGAL ISSUES -============ - -In plain English: - -1. We don't promise that this software works. (But if you find any bugs, - please let us know!) -2. You can use this software for whatever you want. You don't have to pay us. -3. You may not pretend that you wrote this software. If you use it in a - program, you must acknowledge somewhere in your documentation that - you've used the IJG code. - -In legalese: - -The authors make NO WARRANTY or representation, either express or implied, -with respect to this software, its quality, accuracy, merchantability, or -fitness for a particular purpose. This software is provided "AS IS", and you, -its user, assume the entire risk as to its quality and accuracy. - -This software is copyright (C) 1991-1998, Thomas G. Lane. -All Rights Reserved except as specified below. - -Permission is hereby granted to use, copy, modify, and distribute this -software (or portions thereof) for any purpose, without fee, subject to these -conditions: -(1) If any part of the source code for this software is distributed, then this -README file must be included, with this copyright and no-warranty notice -unaltered; and any additions, deletions, or changes to the original files -must be clearly indicated in accompanying documentation. -(2) If only executable code is distributed, then the accompanying -documentation must state that "this software is based in part on the work of -the Independent JPEG Group". -(3) Permission for use of this software is granted only if the user accepts -full responsibility for any undesirable consequences; the authors accept -NO LIABILITY for damages of any kind. - -These conditions apply to any software derived from or based on the IJG code, -not just to the unmodified library. If you use our work, you ought to -acknowledge us. - -Permission is NOT granted for the use of any IJG author's name or company name -in advertising or publicity relating to this software or products derived from -it. This software may be referred to only as "the Independent JPEG Group's -software". - -We specifically permit and encourage the use of this software as the basis of -commercial products, provided that all warranty or liability claims are -assumed by the product vendor. - - -ansi2knr.c is included in this distribution by permission of L. Peter Deutsch, -sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA. -ansi2knr.c is NOT covered by the above copyright and conditions, but instead -by the usual distribution terms of the Free Software Foundation; principally, -that you must include source code if you redistribute it. (See the file -ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part -of any program generated from the IJG code, this does not limit you more than -the foregoing paragraphs do. - -The Unix configuration script "configure" was produced with GNU Autoconf. -It is copyright by the Free Software Foundation but is freely distributable. -The same holds for its supporting scripts (config.guess, config.sub, -ltconfig, ltmain.sh). Another support script, install-sh, is copyright -by M.I.T. but is also freely distributable. - -It appears that the arithmetic coding option of the JPEG spec is covered by -patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot -legally be used without obtaining one or more licenses. For this reason, -support for arithmetic coding has been removed from the free JPEG software. -(Since arithmetic coding provides only a marginal gain over the unpatented -Huffman mode, it is unlikely that very many implementations will support it.) -So far as we are aware, there are no patent restrictions on the remaining -code. - -The IJG distribution formerly included code to read and write GIF files. -To avoid entanglement with the Unisys LZW patent, GIF reading support has -been removed altogether, and the GIF writer has been simplified to produce -"uncompressed GIFs". This technique does not use the LZW algorithm; the -resulting GIF files are larger than usual, but are readable by all standard -GIF decoders. - -We are required to state that - "The Graphics Interchange Format(c) is the Copyright property of - CompuServe Incorporated. GIF(sm) is a Service Mark property of - CompuServe Incorporated." - - -REFERENCES -========== - -We highly recommend reading one or more of these references before trying to -understand the innards of the JPEG software. - -The best short technical introduction to the JPEG compression algorithm is - Wallace, Gregory K. "The JPEG Still Picture Compression Standard", - Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44. -(Adjacent articles in that issue discuss MPEG motion picture compression, -applications of JPEG, and related topics.) If you don't have the CACM issue -handy, a PostScript file containing a revised version of Wallace's article is -available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz. The file (actually -a preprint for an article that appeared in IEEE Trans. Consumer Electronics) -omits the sample images that appeared in CACM, but it includes corrections -and some added material. Note: the Wallace article is copyright ACM and IEEE, -and it may not be used for commercial purposes. - -A somewhat less technical, more leisurely introduction to JPEG can be found in -"The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by -M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides -good explanations and example C code for a multitude of compression methods -including JPEG. It is an excellent source if you are comfortable reading C -code but don't know much about data compression in general. The book's JPEG -sample code is far from industrial-strength, but when you are ready to look -at a full implementation, you've got one here... - -The best full description of JPEG is the textbook "JPEG Still Image Data -Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published -by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp. -The book includes the complete text of the ISO JPEG standards (DIS 10918-1 -and draft DIS 10918-2). This is by far the most complete exposition of JPEG -in existence, and we highly recommend it. - -The JPEG standard itself is not available electronically; you must order a -paper copy through ISO or ITU. (Unless you feel a need to own a certified -official copy, we recommend buying the Pennebaker and Mitchell book instead; -it's much cheaper and includes a great deal of useful explanatory material.) -In the USA, copies of the standard may be ordered from ANSI Sales at (212) -642-4900, or from Global Engineering Documents at (800) 854-7179. (ANSI -doesn't take credit card orders, but Global does.) It's not cheap: as of -1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7% -shipping/handling. The standard is divided into two parts, Part 1 being the -actual specification, while Part 2 covers compliance testing methods. Part 1 -is titled "Digital Compression and Coding of Continuous-tone Still Images, -Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS -10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of -Continuous-tone Still Images, Part 2: Compliance testing" and has document -numbers ISO/IEC IS 10918-2, ITU-T T.83. - -Some extensions to the original JPEG standard are defined in JPEG Part 3, -a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84. IJG -currently does not support any Part 3 extensions. - -The JPEG standard does not specify all details of an interchangeable file -format. For the omitted details we follow the "JFIF" conventions, revision -1.02. A copy of the JFIF spec is available from: - Literature Department - C-Cube Microsystems, Inc. - 1778 McCarthy Blvd. - Milpitas, CA 95035 - phone (408) 944-6300, fax (408) 944-6314 -A PostScript version of this document is available by FTP at -ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz. There is also a plain text -version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing -the figures. - -The TIFF 6.0 file format specification can be obtained by FTP from -ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme -found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems. -IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6). -Instead, we recommend the JPEG design proposed by TIFF Technical Note #2 -(Compression tag 7). Copies of this Note can be obtained from ftp.sgi.com or -from ftp://ftp.uu.net/graphics/jpeg/. It is expected that the next revision -of the TIFF spec will replace the 6.0 JPEG design with the Note's design. -Although IJG's own code does not support TIFF/JPEG, the free libtiff library -uses our library to implement TIFF/JPEG per the Note. libtiff is available -from ftp://ftp.sgi.com/graphics/tiff/. - - -ARCHIVE LOCATIONS -================= - -The "official" archive site for this software is ftp.uu.net (Internet -address 192.48.96.9). The most recent released version can always be found -there in directory graphics/jpeg. This particular version will be archived -as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. If you don't have -direct Internet access, UUNET's archives are also available via UUCP; contact -help@uunet.uu.net for information on retrieving files that way. - -Numerous Internet sites maintain copies of the UUNET files. However, only -ftp.uu.net is guaranteed to have the latest official version. - -You can also obtain this software in DOS-compatible "zip" archive format from -the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or -on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12 -"JPEG Tools". Again, these versions may sometimes lag behind the ftp.uu.net -release. - -The JPEG FAQ (Frequently Asked Questions) article is a useful source of -general information about JPEG. It is updated constantly and therefore is -not included in this distribution. The FAQ is posted every two weeks to -Usenet newsgroups comp.graphics.misc, news.answers, and other groups. -It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/ -and other news.answers archive sites, including the official news.answers -archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/. -If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu -with body - send usenet/news.answers/jpeg-faq/part1 - send usenet/news.answers/jpeg-faq/part2 - - -RELATED SOFTWARE -================ - -Numerous viewing and image manipulation programs now support JPEG. (Quite a -few of them use this library to do so.) The JPEG FAQ described above lists -some of the more popular free and shareware viewers, and tells where to -obtain them on Internet. - -If you are on a Unix machine, we highly recommend Jef Poskanzer's free -PBMPLUS software, which provides many useful operations on PPM-format image -files. In particular, it can convert PPM images to and from a wide range of -other formats, thus making cjpeg/djpeg considerably more useful. The latest -version is distributed by the NetPBM group, and is available from numerous -sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/. -Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is; -you are likely to have difficulty making it work on any non-Unix machine. - -A different free JPEG implementation, written by the PVRG group at Stanford, -is available from ftp://havefun.stanford.edu/pub/jpeg/. This program -is designed for research and experimentation rather than production use; -it is slower, harder to use, and less portable than the IJG code, but it -is easier to read and modify. Also, the PVRG code supports lossless JPEG, -which we do not. (On the other hand, it doesn't do progressive JPEG.) - - -FILE FORMAT WARS -================ - -Some JPEG programs produce files that are not compatible with our library. -The root of the problem is that the ISO JPEG committee failed to specify a -concrete file format. Some vendors "filled in the blanks" on their own, -creating proprietary formats that no one else could read. (For example, none -of the early commercial JPEG implementations for the Macintosh were able to -exchange compressed files.) - -The file format we have adopted is called JFIF (see REFERENCES). This format -has been agreed to by a number of major commercial JPEG vendors, and it has -become the de facto standard. JFIF is a minimal or "low end" representation. -We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF -Technical Note #2) for "high end" applications that need to record a lot of -additional data about an image. TIFF/JPEG is fairly new and not yet widely -supported, unfortunately. - -The upcoming JPEG Part 3 standard defines a file format called SPIFF. -SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should -be able to read the most common variant of SPIFF. SPIFF has some technical -advantages over JFIF, but its major claim to fame is simply that it is an -official standard rather than an informal one. At this point it is unclear -whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto -standard. IJG intends to support SPIFF once the standard is frozen, but we -have not decided whether it should become our default output format or not. -(In any case, our decoder will remain capable of reading JFIF indefinitely.) - -Various proprietary file formats incorporating JPEG compression also exist. -We have little or no sympathy for the existence of these formats. Indeed, -one of the original reasons for developing this free software was to help -force convergence on common, open format standards for JPEG files. Don't -use a proprietary file format! - - -TO DO -===== - -The major thrust for v7 will probably be improvement of visual quality. -The current method for scaling the quantization tables is known not to be -very good at low Q values. We also intend to investigate block boundary -smoothing, "poor man's variable quantization", and other means of improving -quality-vs-file-size performance without sacrificing compatibility. - -In future versions, we are considering supporting some of the upcoming JPEG -Part 3 extensions --- principally, variable quantization and the SPIFF file -format. - -As always, speeding things up is of great interest. - -Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net. diff --git a/libs/jpeg6/jchuff.h b/libs/jpeg6/jchuff.h deleted file mode 100644 index f43d571..0000000 --- a/libs/jpeg6/jchuff.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * jchuff.h - * - * Copyright (C) 1991-1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains declarations for Huffman entropy encoding routines - * that are shared between the sequential encoder (jchuff.c) and the - * progressive encoder (jcphuff.c). No other modules need to see these. - */ - -/* Derived data constructed for each Huffman table */ - -typedef struct { - unsigned int ehufco[256]; /* code for each symbol */ - char ehufsi[256]; /* length of code for each symbol */ - /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ -} c_derived_tbl; - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_make_c_derived_tbl jMkCDerived -#define jpeg_gen_optimal_table jGenOptTbl -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - -/* Expand a Huffman table definition into the derived format */ -EXTERN void jpeg_make_c_derived_tbl JPP((j_compress_ptr cinfo, - JHUFF_TBL * htbl, c_derived_tbl ** pdtbl)); - -/* Generate an optimal table definition given the specified counts */ -EXTERN void jpeg_gen_optimal_table JPP((j_compress_ptr cinfo, - JHUFF_TBL * htbl, long freq[])); diff --git a/libs/jpeg6/jcomapi.cpp b/libs/jpeg6/jcomapi.cpp deleted file mode 100644 index c10903f..0000000 --- a/libs/jpeg6/jcomapi.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * jcomapi.c - * - * Copyright (C) 1994, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains application interface routines that are used for both - * compression and decompression. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * Abort processing of a JPEG compression or decompression operation, - * but don't destroy the object itself. - * - * For this, we merely clean up all the nonpermanent memory pools. - * Note that temp files (virtual arrays) are not allowed to belong to - * the permanent pool, so we will be able to close all temp files here. - * Closing a data source or destination, if necessary, is the application's - * responsibility. - */ - -GLOBAL void -jpeg_abort (j_common_ptr cinfo) -{ - int pool; - - /* Releasing pools in reverse order might help avoid fragmentation - * with some (brain-damaged) malloc libraries. - */ - for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) { - (*cinfo->mem->free_pool) (cinfo, pool); - } - - /* Reset overall state for possible reuse of object */ - cinfo->global_state = (cinfo->is_decompressor ? DSTATE_START : CSTATE_START); -} - - -/* - * Destruction of a JPEG object. - * - * Everything gets deallocated except the master jpeg_compress_struct itself - * and the error manager struct. Both of these are supplied by the application - * and must be freed, if necessary, by the application. (Often they are on - * the stack and so don't need to be freed anyway.) - * Closing a data source or destination, if necessary, is the application's - * responsibility. - */ - -GLOBAL void -jpeg_destroy (j_common_ptr cinfo) -{ - /* We need only tell the memory manager to release everything. */ - /* NB: mem pointer is NULL if memory mgr failed to initialize. */ - if (cinfo->mem != NULL) - (*cinfo->mem->self_destruct) (cinfo); - cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */ - cinfo->global_state = 0; /* mark it destroyed */ -} - - -/* - * Convenience routines for allocating quantization and Huffman tables. - * (Would jutils.c be a more reasonable place to put these?) - */ - -GLOBAL JQUANT_TBL * -jpeg_alloc_quant_table (j_common_ptr cinfo) -{ - JQUANT_TBL *tbl; - - tbl = (JQUANT_TBL *) - (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL)); - tbl->sent_table = FALSE; /* make sure this is false in any new table */ - return tbl; -} - - -GLOBAL JHUFF_TBL * -jpeg_alloc_huff_table (j_common_ptr cinfo) -{ - JHUFF_TBL *tbl; - - tbl = (JHUFF_TBL *) - (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL)); - tbl->sent_table = FALSE; /* make sure this is false in any new table */ - return tbl; -} diff --git a/libs/jpeg6/jconfig.h b/libs/jpeg6/jconfig.h deleted file mode 100644 index 7d2f733..0000000 --- a/libs/jpeg6/jconfig.h +++ /dev/null @@ -1,41 +0,0 @@ -/* jconfig.wat --- jconfig.h for Watcom C/C++ on MS-DOS or OS/2. */ -/* see jconfig.doc for explanations */ - -#define HAVE_PROTOTYPES -#define HAVE_UNSIGNED_CHAR -#define HAVE_UNSIGNED_SHORT -/* #define void char */ -/* #define const */ -#define CHAR_IS_UNSIGNED -#define HAVE_STDDEF_H -#define HAVE_STDLIB_H -#undef NEED_BSD_STRINGS -#undef NEED_SYS_TYPES_H -#undef NEED_FAR_POINTERS /* Watcom uses flat 32-bit addressing */ -#undef NEED_SHORT_EXTERNAL_NAMES -#undef INCOMPLETE_TYPES_BROKEN - -#define JDCT_DEFAULT JDCT_FLOAT -#define JDCT_FASTEST JDCT_FLOAT - -#ifdef JPEG_INTERNALS - -#undef RIGHT_SHIFT_IS_UNSIGNED - -#endif /* JPEG_INTERNALS */ - -#ifdef JPEG_CJPEG_DJPEG - -#define BMP_SUPPORTED /* BMP image file format */ -#define GIF_SUPPORTED /* GIF image file format */ -#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ -#undef RLE_SUPPORTED /* Utah RLE image file format */ -#define TARGA_SUPPORTED /* Targa image file format */ - -#undef TWO_FILE_COMMANDLINE /* optional */ -#define USE_SETMODE /* Needed to make one-file style work in Watcom */ -#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */ -#undef DONT_USE_B_MODE -#undef PROGRESS_REPORT /* optional */ - -#endif /* JPEG_CJPEG_DJPEG */ diff --git a/libs/jpeg6/jdapimin.cpp b/libs/jpeg6/jdapimin.cpp deleted file mode 100644 index 1ea7ef1..0000000 --- a/libs/jpeg6/jdapimin.cpp +++ /dev/null @@ -1,400 +0,0 @@ -/* - * jdapimin.c - * - * Copyright (C) 1994-1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains application interface code for the decompression half - * of the JPEG library. These are the "minimum" API routines that may be - * needed in either the normal full-decompression case or the - * transcoding-only case. - * - * Most of the routines intended to be called directly by an application - * are in this file or in jdapistd.c. But also see jcomapi.c for routines - * shared by compression and decompression, and jdtrans.c for the transcoding - * case. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * Initialization of a JPEG decompression object. - * The error manager must already be set up (in case memory manager fails). - */ - -GLOBAL void -jpeg_create_decompress (j_decompress_ptr cinfo) -{ - int i; - - /* For debugging purposes, zero the whole master structure. - * But error manager pointer is already there, so save and restore it. - */ - { - struct jpeg_error_mgr * err = cinfo->err; - i = sizeof(struct jpeg_decompress_struct); - i = SIZEOF(struct jpeg_decompress_struct); - MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct)); - cinfo->err = err; - } - cinfo->is_decompressor = TRUE; - - /* Initialize a memory manager instance for this object */ - jinit_memory_mgr((j_common_ptr) cinfo); - - /* Zero out pointers to permanent structures. */ - cinfo->progress = NULL; - cinfo->src = NULL; - - for (i = 0; i < NUM_QUANT_TBLS; i++) - cinfo->quant_tbl_ptrs[i] = NULL; - - for (i = 0; i < NUM_HUFF_TBLS; i++) { - cinfo->dc_huff_tbl_ptrs[i] = NULL; - cinfo->ac_huff_tbl_ptrs[i] = NULL; - } - - /* Initialize marker processor so application can override methods - * for COM, APPn markers before calling jpeg_read_header. - */ - jinit_marker_reader(cinfo); - - /* And initialize the overall input controller. */ - jinit_input_controller(cinfo); - - /* OK, I'm ready */ - cinfo->global_state = DSTATE_START; -} - - -/* - * Destruction of a JPEG decompression object - */ - -GLOBAL void -jpeg_destroy_decompress (j_decompress_ptr cinfo) -{ - jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ -} - - -/* - * Abort processing of a JPEG decompression operation, - * but don't destroy the object itself. - */ - -GLOBAL void -jpeg_abort_decompress (j_decompress_ptr cinfo) -{ - jpeg_abort((j_common_ptr) cinfo); /* use common routine */ -} - - -/* - * Install a special processing method for COM or APPn markers. - */ - -GLOBAL void -jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code, - jpeg_marker_parser_method routine) -{ - if (marker_code == JPEG_COM) - cinfo->marker->process_COM = routine; - else if (marker_code >= JPEG_APP0 && marker_code <= JPEG_APP0+15) - cinfo->marker->process_APPn[marker_code-JPEG_APP0] = routine; - else - ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); -} - - -/* - * Set default decompression parameters. - */ - -LOCAL void -default_decompress_parms (j_decompress_ptr cinfo) -{ - /* Guess the input colorspace, and set output colorspace accordingly. */ - /* (Wish JPEG committee had provided a real way to specify this...) */ - /* Note application may override our guesses. */ - switch (cinfo->num_components) { - case 1: - cinfo->jpeg_color_space = JCS_GRAYSCALE; - cinfo->out_color_space = JCS_GRAYSCALE; - break; - - case 3: - if (cinfo->saw_JFIF_marker) { - cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */ - } else if (cinfo->saw_Adobe_marker) { - switch (cinfo->Adobe_transform) { - case 0: - cinfo->jpeg_color_space = JCS_RGB; - break; - case 1: - cinfo->jpeg_color_space = JCS_YCbCr; - break; - default: - WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); - cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ - break; - } - } else { - /* Saw no special markers, try to guess from the component IDs */ - int cid0 = cinfo->comp_info[0].component_id; - int cid1 = cinfo->comp_info[1].component_id; - int cid2 = cinfo->comp_info[2].component_id; - - if (cid0 == 1 && cid1 == 2 && cid2 == 3) - cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */ - else if (cid0 == 82 && cid1 == 71 && cid2 == 66) - cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ - else { - TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2); - cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ - } - } - /* Always guess RGB is proper output colorspace. */ - cinfo->out_color_space = JCS_RGB; - break; - - case 4: - if (cinfo->saw_Adobe_marker) { - switch (cinfo->Adobe_transform) { - case 0: - cinfo->jpeg_color_space = JCS_CMYK; - break; - case 2: - cinfo->jpeg_color_space = JCS_YCCK; - break; - default: - WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); - cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ - break; - } - } else { - /* No special markers, assume straight CMYK. */ - cinfo->jpeg_color_space = JCS_CMYK; - } - cinfo->out_color_space = JCS_CMYK; - break; - - default: - cinfo->jpeg_color_space = JCS_UNKNOWN; - cinfo->out_color_space = JCS_UNKNOWN; - break; - } - - /* Set defaults for other decompression parameters. */ - cinfo->scale_num = 1; /* 1:1 scaling */ - cinfo->scale_denom = 1; - cinfo->output_gamma = 1.0; - cinfo->buffered_image = FALSE; - cinfo->raw_data_out = FALSE; - cinfo->dct_method = JDCT_DEFAULT; - cinfo->do_fancy_upsampling = TRUE; - cinfo->do_block_smoothing = TRUE; - cinfo->quantize_colors = FALSE; - /* We set these in case application only sets quantize_colors. */ - cinfo->dither_mode = JDITHER_FS; -#ifdef QUANT_2PASS_SUPPORTED - cinfo->two_pass_quantize = TRUE; -#else - cinfo->two_pass_quantize = FALSE; -#endif - cinfo->desired_number_of_colors = 256; - cinfo->colormap = NULL; - /* Initialize for no mode change in buffered-image mode. */ - cinfo->enable_1pass_quant = FALSE; - cinfo->enable_external_quant = FALSE; - cinfo->enable_2pass_quant = FALSE; -} - - -/* - * Decompression startup: read start of JPEG datastream to see what's there. - * Need only initialize JPEG object and supply a data source before calling. - * - * This routine will read as far as the first SOS marker (ie, actual start of - * compressed data), and will save all tables and parameters in the JPEG - * object. It will also initialize the decompression parameters to default - * values, and finally return JPEG_HEADER_OK. On return, the application may - * adjust the decompression parameters and then call jpeg_start_decompress. - * (Or, if the application only wanted to determine the image parameters, - * the data need not be decompressed. In that case, call jpeg_abort or - * jpeg_destroy to release any temporary space.) - * If an abbreviated (tables only) datastream is presented, the routine will - * return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then - * re-use the JPEG object to read the abbreviated image datastream(s). - * It is unnecessary (but OK) to call jpeg_abort in this case. - * The JPEG_SUSPENDED return code only occurs if the data source module - * requests suspension of the decompressor. In this case the application - * should load more source data and then re-call jpeg_read_header to resume - * processing. - * If a non-suspending data source is used and require_image is TRUE, then the - * return code need not be inspected since only JPEG_HEADER_OK is possible. - * - * This routine is now just a front end to jpeg_consume_input, with some - * extra error checking. - */ - -GLOBAL int -jpeg_read_header (j_decompress_ptr cinfo, boolean require_image) -{ - int retcode; - - if (cinfo->global_state != DSTATE_START && - cinfo->global_state != DSTATE_INHEADER) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - retcode = jpeg_consume_input(cinfo); - - switch (retcode) { - case JPEG_REACHED_SOS: - retcode = JPEG_HEADER_OK; - break; - case JPEG_REACHED_EOI: - if (require_image) /* Complain if application wanted an image */ - ERREXIT(cinfo, JERR_NO_IMAGE); - /* Reset to start state; it would be safer to require the application to - * call jpeg_abort, but we can't change it now for compatibility reasons. - * A side effect is to free any temporary memory (there shouldn't be any). - */ - jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */ - retcode = JPEG_HEADER_TABLES_ONLY; - break; - case JPEG_SUSPENDED: - /* no work */ - break; - } - - return retcode; -} - - -/* - * Consume data in advance of what the decompressor requires. - * This can be called at any time once the decompressor object has - * been created and a data source has been set up. - * - * This routine is essentially a state machine that handles a couple - * of critical state-transition actions, namely initial setup and - * transition from header scanning to ready-for-start_decompress. - * All the actual input is done via the input controller's consume_input - * method. - */ - -GLOBAL int -jpeg_consume_input (j_decompress_ptr cinfo) -{ - int retcode = JPEG_SUSPENDED; - - /* NB: every possible DSTATE value should be listed in this switch */ - switch (cinfo->global_state) { - case DSTATE_START: - /* Start-of-datastream actions: reset appropriate modules */ - (*cinfo->inputctl->reset_input_controller) (cinfo); - /* Initialize application's data source module */ - (*cinfo->src->init_source) (cinfo); - cinfo->global_state = DSTATE_INHEADER; - /*FALLTHROUGH*/ - case DSTATE_INHEADER: - retcode = (*cinfo->inputctl->consume_input) (cinfo); - if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */ - /* Set up default parameters based on header data */ - default_decompress_parms(cinfo); - /* Set global state: ready for start_decompress */ - cinfo->global_state = DSTATE_READY; - } - break; - case DSTATE_READY: - /* Can't advance past first SOS until start_decompress is called */ - retcode = JPEG_REACHED_SOS; - break; - case DSTATE_PRELOAD: - case DSTATE_PRESCAN: - case DSTATE_SCANNING: - case DSTATE_RAW_OK: - case DSTATE_BUFIMAGE: - case DSTATE_BUFPOST: - case DSTATE_STOPPING: - retcode = (*cinfo->inputctl->consume_input) (cinfo); - break; - default: - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - } - return retcode; -} - - -/* - * Have we finished reading the input file? - */ - -GLOBAL boolean -jpeg_input_complete (j_decompress_ptr cinfo) -{ - /* Check for valid jpeg object */ - if (cinfo->global_state < DSTATE_START || - cinfo->global_state > DSTATE_STOPPING) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - return cinfo->inputctl->eoi_reached; -} - - -/* - * Is there more than one scan? - */ - -GLOBAL boolean -jpeg_has_multiple_scans (j_decompress_ptr cinfo) -{ - /* Only valid after jpeg_read_header completes */ - if (cinfo->global_state < DSTATE_READY || - cinfo->global_state > DSTATE_STOPPING) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - return cinfo->inputctl->has_multiple_scans; -} - - -/* - * Finish JPEG decompression. - * - * This will normally just verify the file trailer and release temp storage. - * - * Returns FALSE if suspended. The return value need be inspected only if - * a suspending data source is used. - */ - -GLOBAL boolean -jpeg_finish_decompress (j_decompress_ptr cinfo) -{ - if ((cinfo->global_state == DSTATE_SCANNING || - cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) { - /* Terminate final pass of non-buffered mode */ - if (cinfo->output_scanline < cinfo->output_height) - ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); - (*cinfo->master->finish_output_pass) (cinfo); - cinfo->global_state = DSTATE_STOPPING; - } else if (cinfo->global_state == DSTATE_BUFIMAGE) { - /* Finishing after a buffered-image operation */ - cinfo->global_state = DSTATE_STOPPING; - } else if (cinfo->global_state != DSTATE_STOPPING) { - /* STOPPING = repeat call after a suspension, anything else is error */ - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - } - /* Read until EOI */ - while (! cinfo->inputctl->eoi_reached) { - if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) - return FALSE; /* Suspend, come back later */ - } - /* Do final cleanup */ - (*cinfo->src->term_source) (cinfo); - /* We can use jpeg_abort to release memory and reset global_state */ - jpeg_abort((j_common_ptr) cinfo); - return TRUE; -} diff --git a/libs/jpeg6/jdapistd.cpp b/libs/jpeg6/jdapistd.cpp deleted file mode 100644 index e36f25c..0000000 --- a/libs/jpeg6/jdapistd.cpp +++ /dev/null @@ -1,275 +0,0 @@ -/* - * jdapistd.c - * - * Copyright (C) 1994-1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains application interface code for the decompression half - * of the JPEG library. These are the "standard" API routines that are - * used in the normal full-decompression case. They are not used by a - * transcoding-only application. Note that if an application links in - * jpeg_start_decompress, it will end up linking in the entire decompressor. - * We thus must separate this file from jdapimin.c to avoid linking the - * whole decompression library into a transcoder. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Forward declarations */ -LOCAL boolean output_pass_setup JPP((j_decompress_ptr cinfo)); - - -/* - * Decompression initialization. - * jpeg_read_header must be completed before calling this. - * - * If a multipass operating mode was selected, this will do all but the - * last pass, and thus may take a great deal of time. - * - * Returns FALSE if suspended. The return value need be inspected only if - * a suspending data source is used. - */ - -GLOBAL boolean -jpeg_start_decompress (j_decompress_ptr cinfo) -{ - if (cinfo->global_state == DSTATE_READY) { - /* First call: initialize master control, select active modules */ - jinit_master_decompress(cinfo); - if (cinfo->buffered_image) { - /* No more work here; expecting jpeg_start_output next */ - cinfo->global_state = DSTATE_BUFIMAGE; - return TRUE; - } - cinfo->global_state = DSTATE_PRELOAD; - } - if (cinfo->global_state == DSTATE_PRELOAD) { - /* If file has multiple scans, absorb them all into the coef buffer */ - if (cinfo->inputctl->has_multiple_scans) { -#ifdef D_MULTISCAN_FILES_SUPPORTED - for (;;) { - int retcode; - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - /* Absorb some more input */ - retcode = (*cinfo->inputctl->consume_input) (cinfo); - if (retcode == JPEG_SUSPENDED) - return FALSE; - if (retcode == JPEG_REACHED_EOI) - break; - /* Advance progress counter if appropriate */ - if (cinfo->progress != NULL && - (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { - if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { - /* jdmaster underestimated number of scans; ratchet up one scan */ - cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; - } - } - } -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif /* D_MULTISCAN_FILES_SUPPORTED */ - } - cinfo->output_scan_number = cinfo->input_scan_number; - } else if (cinfo->global_state != DSTATE_PRESCAN) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - /* Perform any dummy output passes, and set up for the final pass */ - return output_pass_setup(cinfo); -} - - -/* - * Set up for an output pass, and perform any dummy pass(es) needed. - * Common subroutine for jpeg_start_decompress and jpeg_start_output. - * Entry: global_state = DSTATE_PRESCAN only if previously suspended. - * Exit: If done, returns TRUE and sets global_state for proper output mode. - * If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN. - */ - -LOCAL boolean -output_pass_setup (j_decompress_ptr cinfo) -{ - if (cinfo->global_state != DSTATE_PRESCAN) { - /* First call: do pass setup */ - (*cinfo->master->prepare_for_output_pass) (cinfo); - cinfo->output_scanline = 0; - cinfo->global_state = DSTATE_PRESCAN; - } - /* Loop over any required dummy passes */ - while (cinfo->master->is_dummy_pass) { -#ifdef QUANT_2PASS_SUPPORTED - /* Crank through the dummy pass */ - while (cinfo->output_scanline < cinfo->output_height) { - JDIMENSION last_scanline; - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->output_scanline; - cinfo->progress->pass_limit = (long) cinfo->output_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - } - /* Process some data */ - last_scanline = cinfo->output_scanline; - (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL, - &cinfo->output_scanline, (JDIMENSION) 0); - if (cinfo->output_scanline == last_scanline) - return FALSE; /* No progress made, must suspend */ - } - /* Finish up dummy pass, and set up for another one */ - (*cinfo->master->finish_output_pass) (cinfo); - (*cinfo->master->prepare_for_output_pass) (cinfo); - cinfo->output_scanline = 0; -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif /* QUANT_2PASS_SUPPORTED */ - } - /* Ready for application to drive output pass through - * jpeg_read_scanlines or jpeg_read_raw_data. - */ - cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING; - return TRUE; -} - - -/* - * Read some scanlines of data from the JPEG decompressor. - * - * The return value will be the number of lines actually read. - * This may be less than the number requested in several cases, - * including bottom of image, data source suspension, and operating - * modes that emit multiple scanlines at a time. - * - * Note: we warn about excess calls to jpeg_read_scanlines() since - * this likely signals an application programmer error. However, - * an oversize buffer (max_lines > scanlines remaining) is not an error. - */ - -GLOBAL JDIMENSION -jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, - JDIMENSION max_lines) -{ - JDIMENSION row_ctr; - - if (cinfo->global_state != DSTATE_SCANNING) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - if (cinfo->output_scanline >= cinfo->output_height) { - WARNMS(cinfo, JWRN_TOO_MUCH_DATA); - return 0; - } - - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->output_scanline; - cinfo->progress->pass_limit = (long) cinfo->output_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - } - - /* Process some data */ - row_ctr = 0; - (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines); - cinfo->output_scanline += row_ctr; - return row_ctr; -} - - -/* - * Alternate entry point to read raw data. - * Processes exactly one iMCU row per call, unless suspended. - */ - -GLOBAL JDIMENSION -jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, - JDIMENSION max_lines) -{ - JDIMENSION lines_per_iMCU_row; - - if (cinfo->global_state != DSTATE_RAW_OK) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - if (cinfo->output_scanline >= cinfo->output_height) { - WARNMS(cinfo, JWRN_TOO_MUCH_DATA); - return 0; - } - - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->output_scanline; - cinfo->progress->pass_limit = (long) cinfo->output_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - } - - /* Verify that at least one iMCU row can be returned. */ - lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size; - if (max_lines < lines_per_iMCU_row) - ERREXIT(cinfo, JERR_BUFFER_SIZE); - - /* Decompress directly into user's buffer. */ - if (! (*cinfo->coef->decompress_data) (cinfo, data)) - return 0; /* suspension forced, can do nothing more */ - - /* OK, we processed one iMCU row. */ - cinfo->output_scanline += lines_per_iMCU_row; - return lines_per_iMCU_row; -} - - -/* Additional entry points for buffered-image mode. */ - -#ifdef D_MULTISCAN_FILES_SUPPORTED - -/* - * Initialize for an output pass in buffered-image mode. - */ - -GLOBAL boolean -jpeg_start_output (j_decompress_ptr cinfo, int scan_number) -{ - if (cinfo->global_state != DSTATE_BUFIMAGE && - cinfo->global_state != DSTATE_PRESCAN) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - /* Limit scan number to valid range */ - if (scan_number <= 0) - scan_number = 1; - if (cinfo->inputctl->eoi_reached && - scan_number > cinfo->input_scan_number) - scan_number = cinfo->input_scan_number; - cinfo->output_scan_number = scan_number; - /* Perform any dummy output passes, and set up for the real pass */ - return output_pass_setup(cinfo); -} - - -/* - * Finish up after an output pass in buffered-image mode. - * - * Returns FALSE if suspended. The return value need be inspected only if - * a suspending data source is used. - */ - -GLOBAL boolean -jpeg_finish_output (j_decompress_ptr cinfo) -{ - if ((cinfo->global_state == DSTATE_SCANNING || - cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) { - /* Terminate this pass. */ - /* We do not require the whole pass to have been completed. */ - (*cinfo->master->finish_output_pass) (cinfo); - cinfo->global_state = DSTATE_BUFPOST; - } else if (cinfo->global_state != DSTATE_BUFPOST) { - /* BUFPOST = repeat call after a suspension, anything else is error */ - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - } - /* Read markers looking for SOS or EOI */ - while (cinfo->input_scan_number <= cinfo->output_scan_number && - ! cinfo->inputctl->eoi_reached) { - if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) - return FALSE; /* Suspend, come back later */ - } - cinfo->global_state = DSTATE_BUFIMAGE; - return TRUE; -} - -#endif /* D_MULTISCAN_FILES_SUPPORTED */ diff --git a/libs/jpeg6/jdatasrc.cpp b/libs/jpeg6/jdatasrc.cpp deleted file mode 100644 index 0bf7866..0000000 --- a/libs/jpeg6/jdatasrc.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * jdatasrc.c - * - * Copyright (C) 1994, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains decompression data source routines for the case of - * reading JPEG data from a file (or any stdio stream). While these routines - * are sufficient for most applications, some will want to use a different - * source manager. - * IMPORTANT: we assume that fread() will correctly transcribe an array of - * JOCTETs from 8-bit-wide elements on external storage. If char is wider - * than 8 bits on your machine, you may need to do some tweaking. - */ - - -/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ -#include "jinclude.h" -#include "jpeglib.h" -#include "jerror.h" - - -/* Expanded data source object for stdio input */ - -typedef struct { - struct jpeg_source_mgr pub; /* public fields */ - - unsigned char *infile; /* source stream */ - JOCTET * buffer; /* start of buffer */ - boolean start_of_file; /* have we gotten any data yet? */ -} my_source_mgr; - -typedef my_source_mgr * my_src_ptr; - -#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ - - -/* - * Initialize source --- called by jpeg_read_header - * before any data is actually read. - */ - -METHODDEF void -init_source (j_decompress_ptr cinfo) -{ - my_src_ptr src = (my_src_ptr) cinfo->src; - - /* We reset the empty-input-file flag for each image, - * but we don't clear the input buffer. - * This is correct behavior for reading a series of images from one source. - */ - src->start_of_file = TRUE; -} - - -/* - * Fill the input buffer --- called whenever buffer is emptied. - * - * In typical applications, this should read fresh data into the buffer - * (ignoring the current state of next_input_byte & bytes_in_buffer), - * reset the pointer & count to the start of the buffer, and return TRUE - * indicating that the buffer has been reloaded. It is not necessary to - * fill the buffer entirely, only to obtain at least one more byte. - * - * There is no such thing as an EOF return. If the end of the file has been - * reached, the routine has a choice of ERREXIT() or inserting fake data into - * the buffer. In most cases, generating a warning message and inserting a - * fake EOI marker is the best course of action --- this will allow the - * decompressor to output however much of the image is there. However, - * the resulting error message is misleading if the real problem is an empty - * input file, so we handle that case specially. - * - * In applications that need to be able to suspend compression due to input - * not being available yet, a FALSE return indicates that no more data can be - * obtained right now, but more may be forthcoming later. In this situation, - * the decompressor will return to its caller (with an indication of the - * number of scanlines it has read, if any). The application should resume - * decompression after it has loaded more data into the input buffer. Note - * that there are substantial restrictions on the use of suspension --- see - * the documentation. - * - * When suspending, the decompressor will back up to a convenient restart point - * (typically the start of the current MCU). next_input_byte & bytes_in_buffer - * indicate where the restart point will be if the current call returns FALSE. - * Data beyond this point must be rescanned after resumption, so move it to - * the front of the buffer rather than discarding it. - */ - -METHODDEF boolean -fill_input_buffer (j_decompress_ptr cinfo) -{ - my_src_ptr src = (my_src_ptr) cinfo->src; - - memcpy( src->buffer, src->infile, INPUT_BUF_SIZE ); - - src->infile += INPUT_BUF_SIZE; - - src->pub.next_input_byte = src->buffer; - src->pub.bytes_in_buffer = INPUT_BUF_SIZE; - src->start_of_file = FALSE; - - return TRUE; -} - - -/* - * Skip data --- used to skip over a potentially large amount of - * uninteresting data (such as an APPn marker). - * - * Writers of suspendable-input applications must note that skip_input_data - * is not granted the right to give a suspension return. If the skip extends - * beyond the data currently in the buffer, the buffer can be marked empty so - * that the next read will cause a fill_input_buffer call that can suspend. - * Arranging for additional bytes to be discarded before reloading the input - * buffer is the application writer's problem. - */ - -METHODDEF void -skip_input_data (j_decompress_ptr cinfo, long num_bytes) -{ - my_src_ptr src = (my_src_ptr) cinfo->src; - - /* Just a dumb implementation for now. Could use fseek() except - * it doesn't work on pipes. Not clear that being smart is worth - * any trouble anyway --- large skips are infrequent. - */ - if (num_bytes > 0) { - while (num_bytes > (long) src->pub.bytes_in_buffer) { - num_bytes -= (long) src->pub.bytes_in_buffer; - (void) fill_input_buffer(cinfo); - /* note we assume that fill_input_buffer will never return FALSE, - * so suspension need not be handled. - */ - } - src->pub.next_input_byte += (size_t) num_bytes; - src->pub.bytes_in_buffer -= (size_t) num_bytes; - } -} - - -/* - * An additional method that can be provided by data source modules is the - * resync_to_restart method for error recovery in the presence of RST markers. - * For the moment, this source module just uses the default resync method - * provided by the JPEG library. That method assumes that no backtracking - * is possible. - */ - - -/* - * Terminate source --- called by jpeg_finish_decompress - * after all data has been read. Often a no-op. - * - * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding - * application must deal with any cleanup that should happen even - * for error exit. - */ - -METHODDEF void -term_source (j_decompress_ptr cinfo) -{ - /* no work necessary here */ -} - - -/* - * Prepare for input from a stdio stream. - * The caller must have already opened the stream, and is responsible - * for closing it after finishing decompression. - */ - -GLOBAL void -jpeg_stdio_src (j_decompress_ptr cinfo, unsigned char *infile) -{ - my_src_ptr src; - - /* The source object and input buffer are made permanent so that a series - * of JPEG images can be read from the same file by calling jpeg_stdio_src - * only before the first one. (If we discarded the buffer at the end of - * one image, we'd likely lose the start of the next one.) - * This makes it unsafe to use this manager and a different source - * manager serially with the same JPEG object. Caveat programmer. - */ - if (cinfo->src == NULL) { /* first time for this JPEG object? */ - cinfo->src = (struct jpeg_source_mgr *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(my_source_mgr)); - src = (my_src_ptr) cinfo->src; - src->buffer = (JOCTET *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - INPUT_BUF_SIZE * SIZEOF(JOCTET)); - } - - src = (my_src_ptr) cinfo->src; - src->pub.init_source = init_source; - src->pub.fill_input_buffer = fill_input_buffer; - src->pub.skip_input_data = skip_input_data; - src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ - src->pub.term_source = term_source; - src->infile = infile; - src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ - src->pub.next_input_byte = NULL; /* until buffer loaded */ -} diff --git a/libs/jpeg6/jdcoefct.cpp b/libs/jpeg6/jdcoefct.cpp deleted file mode 100644 index ba153f5..0000000 --- a/libs/jpeg6/jdcoefct.cpp +++ /dev/null @@ -1,725 +0,0 @@ -/* - * jdcoefct.c - * - * Copyright (C) 1994-1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the coefficient buffer controller for decompression. - * This controller is the top level of the JPEG decompressor proper. - * The coefficient buffer lies between entropy decoding and inverse-DCT steps. - * - * In buffered-image mode, this controller is the interface between - * input-oriented processing and output-oriented processing. - * Also, the input side (only) is used when reading a file for transcoding. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - -/* Block smoothing is only applicable for progressive JPEG, so: */ -#ifndef D_PROGRESSIVE_SUPPORTED -#undef BLOCK_SMOOTHING_SUPPORTED -#endif - -/* Private buffer controller object */ - -typedef struct { - struct jpeg_d_coef_controller pub; /* public fields */ - - /* These variables keep track of the current location of the input side. */ - /* cinfo->input_iMCU_row is also used for this. */ - JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ - int MCU_vert_offset; /* counts MCU rows within iMCU row */ - int MCU_rows_per_iMCU_row; /* number of such rows needed */ - - /* The output side's location is represented by cinfo->output_iMCU_row. */ - - /* In single-pass modes, it's sufficient to buffer just one MCU. - * We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks, - * and let the entropy decoder write into that workspace each time. - * (On 80x86, the workspace is FAR even though it's not really very big; - * this is to keep the module interfaces unchanged when a large coefficient - * buffer is necessary.) - * In multi-pass modes, this array points to the current MCU's blocks - * within the virtual arrays; it is used only by the input side. - */ - JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU]; - -#ifdef D_MULTISCAN_FILES_SUPPORTED - /* In multi-pass modes, we need a virtual block array for each component. */ - jvirt_barray_ptr whole_image[MAX_COMPONENTS]; -#endif - -#ifdef BLOCK_SMOOTHING_SUPPORTED - /* When doing block smoothing, we latch coefficient Al values here */ - int * coef_bits_latch; -#define SAVED_COEFS 6 /* we save coef_bits[0..5] */ -#endif -} my_coef_controller; - -typedef my_coef_controller * my_coef_ptr; - -/* Forward declarations */ -METHODDEF int decompress_onepass - JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); -#ifdef D_MULTISCAN_FILES_SUPPORTED -METHODDEF int decompress_data - JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); -#endif -#ifdef BLOCK_SMOOTHING_SUPPORTED -LOCAL boolean smoothing_ok JPP((j_decompress_ptr cinfo)); -METHODDEF int decompress_smooth_data - JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); -#endif - - -LOCAL void -start_iMCU_row (j_decompress_ptr cinfo) -/* Reset within-iMCU-row counters for a new row (input side) */ -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - - /* In an interleaved scan, an MCU row is the same as an iMCU row. - * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. - * But at the bottom of the image, process only what's left. - */ - if (cinfo->comps_in_scan > 1) { - coef->MCU_rows_per_iMCU_row = 1; - } else { - if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; - else - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; - } - - coef->MCU_ctr = 0; - coef->MCU_vert_offset = 0; -} - - -/* - * Initialize for an input processing pass. - */ - -METHODDEF void -start_input_pass (j_decompress_ptr cinfo) -{ - cinfo->input_iMCU_row = 0; - start_iMCU_row(cinfo); -} - - -/* - * Initialize for an output processing pass. - */ - -METHODDEF void -start_output_pass (j_decompress_ptr cinfo) -{ -#ifdef BLOCK_SMOOTHING_SUPPORTED - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - - /* If multipass, check to see whether to use block smoothing on this pass */ - if (coef->pub.coef_arrays != NULL) { - if (cinfo->do_block_smoothing && smoothing_ok(cinfo)) - coef->pub.decompress_data = decompress_smooth_data; - else - coef->pub.decompress_data = decompress_data; - } -#endif - cinfo->output_iMCU_row = 0; -} - - -/* - * Decompress and return some data in the single-pass case. - * Always attempts to emit one fully interleaved MCU row ("iMCU" row). - * Input and output must run in lockstep since we have only a one-MCU buffer. - * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. - * - * NB: output_buf contains a plane for each component in image. - * For single pass, this is the same as the components in the scan. - */ - -METHODDEF int -decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION MCU_col_num; /* index of current MCU within row */ - JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - int blkn, ci, xindex, yindex, yoffset, useful_width; - JSAMPARRAY output_ptr; - JDIMENSION start_col, output_col; - jpeg_component_info *compptr; - inverse_DCT_method_ptr inverse_DCT; - - /* Loop to process as much as one whole iMCU row */ - for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; - yoffset++) { - for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; - MCU_col_num++) { - /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */ - jzero_far((void FAR *) coef->MCU_buffer[0], - (size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK))); - if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { - /* Suspension forced; update state counters and exit */ - coef->MCU_vert_offset = yoffset; - coef->MCU_ctr = MCU_col_num; - return JPEG_SUSPENDED; - } - /* Determine where data should go in output_buf and do the IDCT thing. - * We skip dummy blocks at the right and bottom edges (but blkn gets - * incremented past them!). Note the inner loop relies on having - * allocated the MCU_buffer[] blocks sequentially. - */ - blkn = 0; /* index of current DCT block within MCU */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Don't bother to IDCT an uninteresting component. */ - if (! compptr->component_needed) { - blkn += compptr->MCU_blocks; - continue; - } - inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; - useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width - : compptr->last_col_width; - output_ptr = output_buf[ci] + yoffset * compptr->DCT_scaled_size; - start_col = MCU_col_num * compptr->MCU_sample_width; - for (yindex = 0; yindex < compptr->MCU_height; yindex++) { - if (cinfo->input_iMCU_row < last_iMCU_row || - yoffset+yindex < compptr->last_row_height) { - output_col = start_col; - for (xindex = 0; xindex < useful_width; xindex++) { - (*inverse_DCT) (cinfo, compptr, - (JCOEFPTR) coef->MCU_buffer[blkn+xindex], - output_ptr, output_col); - output_col += compptr->DCT_scaled_size; - } - } - blkn += compptr->MCU_width; - output_ptr += compptr->DCT_scaled_size; - } - } - } - /* Completed an MCU row, but perhaps not an iMCU row */ - coef->MCU_ctr = 0; - } - /* Completed the iMCU row, advance counters for next one */ - cinfo->output_iMCU_row++; - if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { - start_iMCU_row(cinfo); - return JPEG_ROW_COMPLETED; - } - /* Completed the scan */ - (*cinfo->inputctl->finish_input_pass) (cinfo); - return JPEG_SCAN_COMPLETED; -} - - -/* - * Dummy consume-input routine for single-pass operation. - */ - -METHODDEF int -dummy_consume_data (j_decompress_ptr cinfo) -{ - return JPEG_SUSPENDED; /* Always indicate nothing was done */ -} - - -#ifdef D_MULTISCAN_FILES_SUPPORTED - -/* - * Consume input data and store it in the full-image coefficient buffer. - * We read as much as one fully interleaved MCU row ("iMCU" row) per call, - * ie, v_samp_factor block rows for each component in the scan. - * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. - */ - -METHODDEF int -consume_data (j_decompress_ptr cinfo) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION MCU_col_num; /* index of current MCU within row */ - int blkn, ci, xindex, yindex, yoffset; - JDIMENSION start_col; - JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; - JBLOCKROW buffer_ptr; - jpeg_component_info *compptr; - - /* Align the virtual buffers for the components used in this scan. */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - buffer[ci] = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], - cinfo->input_iMCU_row * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, TRUE); - /* Note: entropy decoder expects buffer to be zeroed, - * but this is handled automatically by the memory manager - * because we requested a pre-zeroed array. - */ - } - - /* Loop to process one whole iMCU row */ - for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; - yoffset++) { - for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row; - MCU_col_num++) { - /* Construct list of pointers to DCT blocks belonging to this MCU */ - blkn = 0; /* index of current DCT block within MCU */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - start_col = MCU_col_num * compptr->MCU_width; - for (yindex = 0; yindex < compptr->MCU_height; yindex++) { - buffer_ptr = buffer[ci][yindex+yoffset] + start_col; - for (xindex = 0; xindex < compptr->MCU_width; xindex++) { - coef->MCU_buffer[blkn++] = buffer_ptr++; - } - } - } - /* Try to fetch the MCU. */ - if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { - /* Suspension forced; update state counters and exit */ - coef->MCU_vert_offset = yoffset; - coef->MCU_ctr = MCU_col_num; - return JPEG_SUSPENDED; - } - } - /* Completed an MCU row, but perhaps not an iMCU row */ - coef->MCU_ctr = 0; - } - /* Completed the iMCU row, advance counters for next one */ - if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { - start_iMCU_row(cinfo); - return JPEG_ROW_COMPLETED; - } - /* Completed the scan */ - (*cinfo->inputctl->finish_input_pass) (cinfo); - return JPEG_SCAN_COMPLETED; -} - - -/* - * Decompress and return some data in the multi-pass case. - * Always attempts to emit one fully interleaved MCU row ("iMCU" row). - * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. - * - * NB: output_buf contains a plane for each component in image. - */ - -METHODDEF int -decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - JDIMENSION block_num; - int ci, block_row, block_rows; - JBLOCKARRAY buffer; - JBLOCKROW buffer_ptr; - JSAMPARRAY output_ptr; - JDIMENSION output_col; - jpeg_component_info *compptr; - inverse_DCT_method_ptr inverse_DCT; - - /* Force some input to be done if we are getting ahead of the input. */ - while (cinfo->input_scan_number < cinfo->output_scan_number || - (cinfo->input_scan_number == cinfo->output_scan_number && - cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { - if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) - return JPEG_SUSPENDED; - } - - /* OK, output from the virtual arrays. */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Don't bother to IDCT an uninteresting component. */ - if (! compptr->component_needed) - continue; - /* Align the virtual buffer for this component. */ - buffer = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[ci], - cinfo->output_iMCU_row * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, FALSE); - /* Count non-dummy DCT block rows in this iMCU row. */ - if (cinfo->output_iMCU_row < last_iMCU_row) - block_rows = compptr->v_samp_factor; - else { - /* NB: can't use last_row_height here; it is input-side-dependent! */ - block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (block_rows == 0) block_rows = compptr->v_samp_factor; - } - inverse_DCT = cinfo->idct->inverse_DCT[ci]; - output_ptr = output_buf[ci]; - /* Loop over all DCT blocks to be processed. */ - for (block_row = 0; block_row < block_rows; block_row++) { - buffer_ptr = buffer[block_row]; - output_col = 0; - for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) { - (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr, - output_ptr, output_col); - buffer_ptr++; - output_col += compptr->DCT_scaled_size; - } - output_ptr += compptr->DCT_scaled_size; - } - } - - if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) - return JPEG_ROW_COMPLETED; - return JPEG_SCAN_COMPLETED; -} - -#endif /* D_MULTISCAN_FILES_SUPPORTED */ - - -#ifdef BLOCK_SMOOTHING_SUPPORTED - -/* - * This code applies interblock smoothing as described by section K.8 - * of the JPEG standard: the first 5 AC coefficients are estimated from - * the DC values of a DCT block and its 8 neighboring blocks. - * We apply smoothing only for progressive JPEG decoding, and only if - * the coefficients it can estimate are not yet known to full precision. - */ - -/* - * Determine whether block smoothing is applicable and safe. - * We also latch the current states of the coef_bits[] entries for the - * AC coefficients; otherwise, if the input side of the decompressor - * advances into a new scan, we might think the coefficients are known - * more accurately than they really are. - */ - -LOCAL boolean -smoothing_ok (j_decompress_ptr cinfo) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - boolean smoothing_useful = FALSE; - int ci, coefi; - jpeg_component_info *compptr; - JQUANT_TBL * qtable; - int * coef_bits; - int * coef_bits_latch; - - if (! cinfo->progressive_mode || cinfo->coef_bits == NULL) - return FALSE; - - /* Allocate latch area if not already done */ - if (coef->coef_bits_latch == NULL) - coef->coef_bits_latch = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components * - (SAVED_COEFS * SIZEOF(int))); - coef_bits_latch = coef->coef_bits_latch; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* All components' quantization values must already be latched. */ - if ((qtable = compptr->quant_table) == NULL) - return FALSE; - /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */ - for (coefi = 0; coefi <= 5; coefi++) { - if (qtable->quantval[coefi] == 0) - return FALSE; - } - /* DC values must be at least partly known for all components. */ - coef_bits = cinfo->coef_bits[ci]; - if (coef_bits[0] < 0) - return FALSE; - /* Block smoothing is helpful if some AC coefficients remain inaccurate. */ - for (coefi = 1; coefi <= 5; coefi++) { - coef_bits_latch[coefi] = coef_bits[coefi]; - if (coef_bits[coefi] != 0) - smoothing_useful = TRUE; - } - coef_bits_latch += SAVED_COEFS; - } - - return smoothing_useful; -} - - -/* - * Variant of decompress_data for use when doing block smoothing. - */ - -METHODDEF int -decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - JDIMENSION block_num, last_block_column; - int ci, block_row, block_rows, access_rows; - JBLOCKARRAY buffer; - JBLOCKROW buffer_ptr, prev_block_row, next_block_row; - JSAMPARRAY output_ptr; - JDIMENSION output_col; - jpeg_component_info *compptr; - inverse_DCT_method_ptr inverse_DCT; - boolean first_row, last_row; - JBLOCK workspace; - int *coef_bits; - JQUANT_TBL *quanttbl; - INT32 Q00,Q01,Q02,Q10,Q11,Q20, num; - int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9; - int Al, pred; - - /* Force some input to be done if we are getting ahead of the input. */ - while (cinfo->input_scan_number <= cinfo->output_scan_number && - ! cinfo->inputctl->eoi_reached) { - if (cinfo->input_scan_number == cinfo->output_scan_number) { - /* If input is working on current scan, we ordinarily want it to - * have completed the current row. But if input scan is DC, - * we want it to keep one row ahead so that next block row's DC - * values are up to date. - */ - JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0; - if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta) - break; - } - if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) - return JPEG_SUSPENDED; - } - - /* OK, output from the virtual arrays. */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Don't bother to IDCT an uninteresting component. */ - if (! compptr->component_needed) - continue; - /* Count non-dummy DCT block rows in this iMCU row. */ - if (cinfo->output_iMCU_row < last_iMCU_row) { - block_rows = compptr->v_samp_factor; - access_rows = block_rows * 2; /* this and next iMCU row */ - last_row = FALSE; - } else { - /* NB: can't use last_row_height here; it is input-side-dependent! */ - block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (block_rows == 0) block_rows = compptr->v_samp_factor; - access_rows = block_rows; /* this iMCU row only */ - last_row = TRUE; - } - /* Align the virtual buffer for this component. */ - if (cinfo->output_iMCU_row > 0) { - access_rows += compptr->v_samp_factor; /* prior iMCU row too */ - buffer = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[ci], - (cinfo->output_iMCU_row - 1) * compptr->v_samp_factor, - (JDIMENSION) access_rows, FALSE); - buffer += compptr->v_samp_factor; /* point to current iMCU row */ - first_row = FALSE; - } else { - buffer = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[ci], - (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE); - first_row = TRUE; - } - /* Fetch component-dependent info */ - coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS); - quanttbl = compptr->quant_table; - Q00 = quanttbl->quantval[0]; - Q01 = quanttbl->quantval[1]; - Q10 = quanttbl->quantval[2]; - Q20 = quanttbl->quantval[3]; - Q11 = quanttbl->quantval[4]; - Q02 = quanttbl->quantval[5]; - inverse_DCT = cinfo->idct->inverse_DCT[ci]; - output_ptr = output_buf[ci]; - /* Loop over all DCT blocks to be processed. */ - for (block_row = 0; block_row < block_rows; block_row++) { - buffer_ptr = buffer[block_row]; - if (first_row && block_row == 0) - prev_block_row = buffer_ptr; - else - prev_block_row = buffer[block_row-1]; - if (last_row && block_row == block_rows-1) - next_block_row = buffer_ptr; - else - next_block_row = buffer[block_row+1]; - /* We fetch the surrounding DC values using a sliding-register approach. - * Initialize all nine here so as to do the right thing on narrow pics. - */ - DC1 = DC2 = DC3 = (int) prev_block_row[0][0]; - DC4 = DC5 = DC6 = (int) buffer_ptr[0][0]; - DC7 = DC8 = DC9 = (int) next_block_row[0][0]; - output_col = 0; - last_block_column = compptr->width_in_blocks - 1; - for (block_num = 0; block_num <= last_block_column; block_num++) { - /* Fetch current DCT block into workspace so we can modify it. */ - jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1); - /* Update DC values */ - if (block_num < last_block_column) { - DC3 = (int) prev_block_row[1][0]; - DC6 = (int) buffer_ptr[1][0]; - DC9 = (int) next_block_row[1][0]; - } - /* Compute coefficient estimates per K.8. - * An estimate is applied only if coefficient is still zero, - * and is not known to be fully accurate. - */ - /* AC01 */ - if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) { - num = 36 * Q00 * (DC4 - DC6); - if (num >= 0) { - pred = (int) (((Q01<<7) + num) / (Q01<<8)); - if (Al > 0 && pred >= (1<<Al)) - pred = (1<<Al)-1; - } else { - pred = (int) (((Q01<<7) - num) / (Q01<<8)); - if (Al > 0 && pred >= (1<<Al)) - pred = (1<<Al)-1; - pred = -pred; - } - workspace[1] = (JCOEF) pred; - } - /* AC10 */ - if ((Al=coef_bits[2]) != 0 && workspace[8] == 0) { - num = 36 * Q00 * (DC2 - DC8); - if (num >= 0) { - pred = (int) (((Q10<<7) + num) / (Q10<<8)); - if (Al > 0 && pred >= (1<<Al)) - pred = (1<<Al)-1; - } else { - pred = (int) (((Q10<<7) - num) / (Q10<<8)); - if (Al > 0 && pred >= (1<<Al)) - pred = (1<<Al)-1; - pred = -pred; - } - workspace[8] = (JCOEF) pred; - } - /* AC20 */ - if ((Al=coef_bits[3]) != 0 && workspace[16] == 0) { - num = 9 * Q00 * (DC2 + DC8 - 2*DC5); - if (num >= 0) { - pred = (int) (((Q20<<7) + num) / (Q20<<8)); - if (Al > 0 && pred >= (1<<Al)) - pred = (1<<Al)-1; - } else { - pred = (int) (((Q20<<7) - num) / (Q20<<8)); - if (Al > 0 && pred >= (1<<Al)) - pred = (1<<Al)-1; - pred = -pred; - } - workspace[16] = (JCOEF) pred; - } - /* AC11 */ - if ((Al=coef_bits[4]) != 0 && workspace[9] == 0) { - num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9); - if (num >= 0) { - pred = (int) (((Q11<<7) + num) / (Q11<<8)); - if (Al > 0 && pred >= (1<<Al)) - pred = (1<<Al)-1; - } else { - pred = (int) (((Q11<<7) - num) / (Q11<<8)); - if (Al > 0 && pred >= (1<<Al)) - pred = (1<<Al)-1; - pred = -pred; - } - workspace[9] = (JCOEF) pred; - } - /* AC02 */ - if ((Al=coef_bits[5]) != 0 && workspace[2] == 0) { - num = 9 * Q00 * (DC4 + DC6 - 2*DC5); - if (num >= 0) { - pred = (int) (((Q02<<7) + num) / (Q02<<8)); - if (Al > 0 && pred >= (1<<Al)) - pred = (1<<Al)-1; - } else { - pred = (int) (((Q02<<7) - num) / (Q02<<8)); - if (Al > 0 && pred >= (1<<Al)) - pred = (1<<Al)-1; - pred = -pred; - } - workspace[2] = (JCOEF) pred; - } - /* OK, do the IDCT */ - (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) workspace, - output_ptr, output_col); - /* Advance for next column */ - DC1 = DC2; DC2 = DC3; - DC4 = DC5; DC5 = DC6; - DC7 = DC8; DC8 = DC9; - buffer_ptr++, prev_block_row++, next_block_row++; - output_col += compptr->DCT_scaled_size; - } - output_ptr += compptr->DCT_scaled_size; - } - } - - if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) - return JPEG_ROW_COMPLETED; - return JPEG_SCAN_COMPLETED; -} - -#endif /* BLOCK_SMOOTHING_SUPPORTED */ - - -/* - * Initialize coefficient buffer controller. - */ - -GLOBAL void -jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) -{ - my_coef_ptr coef; - - coef = (my_coef_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_coef_controller)); - cinfo->coef = (struct jpeg_d_coef_controller *) coef; - coef->pub.start_input_pass = start_input_pass; - coef->pub.start_output_pass = start_output_pass; -#ifdef BLOCK_SMOOTHING_SUPPORTED - coef->coef_bits_latch = NULL; -#endif - - /* Create the coefficient buffer. */ - if (need_full_buffer) { -#ifdef D_MULTISCAN_FILES_SUPPORTED - /* Allocate a full-image virtual array for each component, */ - /* padded to a multiple of samp_factor DCT blocks in each direction. */ - /* Note we ask for a pre-zeroed array. */ - int ci, access_rows; - jpeg_component_info *compptr; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - access_rows = compptr->v_samp_factor; -#ifdef BLOCK_SMOOTHING_SUPPORTED - /* If block smoothing could be used, need a bigger window */ - if (cinfo->progressive_mode) - access_rows *= 3; -#endif - coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, - (JDIMENSION) jround_up((long) compptr->width_in_blocks, - (long) compptr->h_samp_factor), - (JDIMENSION) jround_up((long) compptr->height_in_blocks, - (long) compptr->v_samp_factor), - (JDIMENSION) access_rows); - } - coef->pub.consume_data = consume_data; - coef->pub.decompress_data = decompress_data; - coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */ -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else { - /* We only need a single-MCU buffer. */ - JBLOCKROW buffer; - int i; - - buffer = (JBLOCKROW) - (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); - for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) { - coef->MCU_buffer[i] = buffer + i; - } - coef->pub.consume_data = dummy_consume_data; - coef->pub.decompress_data = decompress_onepass; - coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */ - } -} diff --git a/libs/jpeg6/jdcolor.cpp b/libs/jpeg6/jdcolor.cpp deleted file mode 100644 index b2bdf6e..0000000 --- a/libs/jpeg6/jdcolor.cpp +++ /dev/null @@ -1,367 +0,0 @@ -/* - * jdcolor.c - * - * Copyright (C) 1991-1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains output colorspace conversion routines. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Private subobject */ - -typedef struct { - struct jpeg_color_deconverter pub; /* public fields */ - - /* Private state for YCC->RGB conversion */ - int * Cr_r_tab; /* => table for Cr to R conversion */ - int * Cb_b_tab; /* => table for Cb to B conversion */ - INT32 * Cr_g_tab; /* => table for Cr to G conversion */ - INT32 * Cb_g_tab; /* => table for Cb to G conversion */ -} my_color_deconverter; - -typedef my_color_deconverter * my_cconvert_ptr; - - -/**************** YCbCr -> RGB conversion: most common case **************/ - -/* - * YCbCr is defined per CCIR 601-1, except that Cb and Cr are - * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. - * The conversion equations to be implemented are therefore - * R = Y + 1.40200 * Cr - * G = Y - 0.34414 * Cb - 0.71414 * Cr - * B = Y + 1.77200 * Cb - * where Cb and Cr represent the incoming values less CENTERJSAMPLE. - * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) - * - * To avoid floating-point arithmetic, we represent the fractional constants - * as integers scaled up by 2^16 (about 4 digits precision); we have to divide - * the products by 2^16, with appropriate rounding, to get the correct answer. - * Notice that Y, being an integral input, does not contribute any fraction - * so it need not participate in the rounding. - * - * For even more speed, we avoid doing any multiplications in the inner loop - * by precalculating the constants times Cb and Cr for all possible values. - * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); - * for 12-bit samples it is still acceptable. It's not very reasonable for - * 16-bit samples, but if you want lossless storage you shouldn't be changing - * colorspace anyway. - * The Cr=>R and Cb=>B values can be rounded to integers in advance; the - * values for the G calculation are left scaled up, since we must add them - * together before rounding. - */ - -#define SCALEBITS 16 /* speediest right-shift on some machines */ -#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) -#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5)) - - -/* - * Initialize tables for YCC->RGB colorspace conversion. - */ - -LOCAL void -build_ycc_rgb_table (j_decompress_ptr cinfo) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - int i; - INT32 x; - SHIFT_TEMPS - - cconvert->Cr_r_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); - cconvert->Cb_b_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); - cconvert->Cr_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); - cconvert->Cb_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); - - for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { - /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ - /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ - /* Cr=>R value is nearest int to 1.40200 * x */ - cconvert->Cr_r_tab[i] = (int) - RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); - /* Cb=>B value is nearest int to 1.77200 * x */ - cconvert->Cb_b_tab[i] = (int) - RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); - /* Cr=>G value is scaled-up -0.71414 * x */ - cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; - /* Cb=>G value is scaled-up -0.34414 * x */ - /* We also add in ONE_HALF so that need not do it in inner loop */ - cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; - } -} - - -/* - * Convert some rows of samples to the output colorspace. - * - * Note that we change from noninterleaved, one-plane-per-component format - * to interleaved-pixel format. The output buffer is therefore three times - * as wide as the input buffer. - * A starting row offset is provided only for the input buffer. The caller - * can easily adjust the passed output_buf value to accommodate any row - * offset required on that side. - */ - -METHODDEF void -ycc_rgb_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register int y, cb, cr; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->output_width; - /* copy these pointers into registers if possible */ - register JSAMPLE * range_limit = cinfo->sample_range_limit; - register int * Crrtab = cconvert->Cr_r_tab; - register int * Cbbtab = cconvert->Cb_b_tab; - register INT32 * Crgtab = cconvert->Cr_g_tab; - register INT32 * Cbgtab = cconvert->Cb_g_tab; - SHIFT_TEMPS - - while (--num_rows >= 0) { - inptr0 = input_buf[0][input_row]; - inptr1 = input_buf[1][input_row]; - inptr2 = input_buf[2][input_row]; - input_row++; - outptr = *output_buf++; - for (col = 0; col < num_cols; col++) { - y = GETJSAMPLE(inptr0[col]); - cb = GETJSAMPLE(inptr1[col]); - cr = GETJSAMPLE(inptr2[col]); - /* Range-limiting is essential due to noise introduced by DCT losses. */ - outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; - outptr[RGB_GREEN] = range_limit[y + - ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], - SCALEBITS))]; - outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; - outptr += RGB_PIXELSIZE; - } - } -} - - -/**************** Cases other than YCbCr -> RGB **************/ - - -/* - * Color conversion for no colorspace change: just copy the data, - * converting from separate-planes to interleaved representation. - */ - -METHODDEF void -null_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - register JSAMPROW inptr, outptr; - register JDIMENSION count; - register int num_components = cinfo->num_components; - JDIMENSION num_cols = cinfo->output_width; - int ci; - - while (--num_rows >= 0) { - for (ci = 0; ci < num_components; ci++) { - inptr = input_buf[ci][input_row]; - outptr = output_buf[0] + ci; - for (count = num_cols; count > 0; count--) { - *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ - outptr += num_components; - } - } - input_row++; - output_buf++; - } -} - - -/* - * Color conversion for grayscale: just copy the data. - * This also works for YCbCr -> grayscale conversion, in which - * we just copy the Y (luminance) component and ignore chrominance. - */ - -METHODDEF void -grayscale_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, - num_rows, cinfo->output_width); -} - - -/* - * Adobe-style YCCK->CMYK conversion. - * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same - * conversion as above, while passing K (black) unchanged. - * We assume build_ycc_rgb_table has been called. - */ - -METHODDEF void -ycck_cmyk_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register int y, cb, cr; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2, inptr3; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->output_width; - /* copy these pointers into registers if possible */ - register JSAMPLE * range_limit = cinfo->sample_range_limit; - register int * Crrtab = cconvert->Cr_r_tab; - register int * Cbbtab = cconvert->Cb_b_tab; - register INT32 * Crgtab = cconvert->Cr_g_tab; - register INT32 * Cbgtab = cconvert->Cb_g_tab; - SHIFT_TEMPS - - while (--num_rows >= 0) { - inptr0 = input_buf[0][input_row]; - inptr1 = input_buf[1][input_row]; - inptr2 = input_buf[2][input_row]; - inptr3 = input_buf[3][input_row]; - input_row++; - outptr = *output_buf++; - for (col = 0; col < num_cols; col++) { - y = GETJSAMPLE(inptr0[col]); - cb = GETJSAMPLE(inptr1[col]); - cr = GETJSAMPLE(inptr2[col]); - /* Range-limiting is essential due to noise introduced by DCT losses. */ - outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ - outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ - ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], - SCALEBITS)))]; - outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ - /* K passes through unchanged */ - outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ - outptr += 4; - } - } -} - - -/* - * Empty method for start_pass. - */ - -METHODDEF void -start_pass_dcolor (j_decompress_ptr cinfo) -{ - /* no work needed */ -} - - -/* - * Module initialization routine for output colorspace conversion. - */ - -GLOBAL void -jinit_color_deconverter (j_decompress_ptr cinfo) -{ - my_cconvert_ptr cconvert; - int ci; - - cconvert = (my_cconvert_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_color_deconverter)); - cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; - cconvert->pub.start_pass = start_pass_dcolor; - - /* Make sure num_components agrees with jpeg_color_space */ - switch (cinfo->jpeg_color_space) { - case JCS_GRAYSCALE: - if (cinfo->num_components != 1) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - break; - - case JCS_RGB: - case JCS_YCbCr: - if (cinfo->num_components != 3) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - break; - - case JCS_CMYK: - case JCS_YCCK: - if (cinfo->num_components != 4) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - break; - - default: /* JCS_UNKNOWN can be anything */ - if (cinfo->num_components < 1) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - break; - } - - /* Set out_color_components and conversion method based on requested space. - * Also clear the component_needed flags for any unused components, - * so that earlier pipeline stages can avoid useless computation. - */ - - switch (cinfo->out_color_space) { - case JCS_GRAYSCALE: - cinfo->out_color_components = 1; - if (cinfo->jpeg_color_space == JCS_GRAYSCALE || - cinfo->jpeg_color_space == JCS_YCbCr) { - cconvert->pub.color_convert = grayscale_convert; - /* For color->grayscale conversion, only the Y (0) component is needed */ - for (ci = 1; ci < cinfo->num_components; ci++) - cinfo->comp_info[ci].component_needed = FALSE; - } else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - - case JCS_RGB: - cinfo->out_color_components = RGB_PIXELSIZE; - if (cinfo->jpeg_color_space == JCS_YCbCr) { - cconvert->pub.color_convert = ycc_rgb_convert; - build_ycc_rgb_table(cinfo); - } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) { - cconvert->pub.color_convert = null_convert; - } else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - - case JCS_CMYK: - cinfo->out_color_components = 4; - if (cinfo->jpeg_color_space == JCS_YCCK) { - cconvert->pub.color_convert = ycck_cmyk_convert; - build_ycc_rgb_table(cinfo); - } else if (cinfo->jpeg_color_space == JCS_CMYK) { - cconvert->pub.color_convert = null_convert; - } else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - - default: - /* Permit null conversion to same output space */ - if (cinfo->out_color_space == cinfo->jpeg_color_space) { - cinfo->out_color_components = cinfo->num_components; - cconvert->pub.color_convert = null_convert; - } else /* unsupported non-null conversion */ - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - } - - if (cinfo->quantize_colors) - cinfo->output_components = 1; /* single colormapped output component */ - else - cinfo->output_components = cinfo->out_color_components; -} diff --git a/libs/jpeg6/jdct.h b/libs/jpeg6/jdct.h deleted file mode 100644 index 3ce790b..0000000 --- a/libs/jpeg6/jdct.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * jdct.h - * - * Copyright (C) 1994, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This include file contains common declarations for the forward and - * inverse DCT modules. These declarations are private to the DCT managers - * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. - * The individual DCT algorithms are kept in separate files to ease - * machine-dependent tuning (e.g., assembly coding). - */ - - -/* - * A forward DCT routine is given a pointer to a work area of type DCTELEM[]; - * the DCT is to be performed in-place in that buffer. Type DCTELEM is int - * for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT - * implementations use an array of type FAST_FLOAT, instead.) - * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE). - * The DCT outputs are returned scaled up by a factor of 8; they therefore - * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This - * convention improves accuracy in integer implementations and saves some - * work in floating-point ones. - * Quantization of the output coefficients is done by jcdctmgr.c. - */ - -#if BITS_IN_JSAMPLE == 8 -typedef int DCTELEM; /* 16 or 32 bits is fine */ -#else -typedef INT32 DCTELEM; /* must have 32 bits */ -#endif - -typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data)); -typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data)); - - -/* - * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer - * to an output sample array. The routine must dequantize the input data as - * well as perform the IDCT; for dequantization, it uses the multiplier table - * pointed to by compptr->dct_table. The output data is to be placed into the - * sample array starting at a specified column. (Any row offset needed will - * be applied to the array pointer before it is passed to the IDCT code.) - * Note that the number of samples emitted by the IDCT routine is - * DCT_scaled_size * DCT_scaled_size. - */ - -/* typedef inverse_DCT_method_ptr is declared in jpegint.h */ - -/* - * Each IDCT routine has its own ideas about the best dct_table element type. - */ - -typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */ -#if BITS_IN_JSAMPLE == 8 -typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ -#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */ -#else -typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */ -#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */ -#endif -typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ - - -/* - * Each IDCT routine is responsible for range-limiting its results and - * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could - * be quite far out of range if the input data is corrupt, so a bulletproof - * range-limiting step is required. We use a mask-and-table-lookup method - * to do the combined operations quickly. See the comments with - * prepare_range_limit_table (in jdmaster.c) for more info. - */ - -#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) - -#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ - - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_fdct_islow jFDislow -#define jpeg_fdct_ifast jFDifast -#define jpeg_fdct_float jFDfloat -#define jpeg_idct_islow jRDislow -#define jpeg_idct_ifast jRDifast -#define jpeg_idct_float jRDfloat -#define jpeg_idct_4x4 jRD4x4 -#define jpeg_idct_2x2 jRD2x2 -#define jpeg_idct_1x1 jRD1x1 -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - -/* Extern declarations for the forward and inverse DCT routines. */ - -EXTERN void jpeg_fdct_islow JPP((DCTELEM * data)); -EXTERN void jpeg_fdct_ifast JPP((DCTELEM * data)); -EXTERN void jpeg_fdct_float JPP((FAST_FLOAT * data)); - -EXTERN void jpeg_idct_islow - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN void jpeg_idct_ifast - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN void jpeg_idct_float - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN void jpeg_idct_4x4 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN void jpeg_idct_2x2 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN void jpeg_idct_1x1 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); - - -/* - * Macros for handling fixed-point arithmetic; these are used by many - * but not all of the DCT/IDCT modules. - * - * All values are expected to be of type INT32. - * Fractional constants are scaled left by CONST_BITS bits. - * CONST_BITS is defined within each module using these macros, - * and may differ from one module to the next. - */ - -#define ONE ((INT32) 1) -#define CONST_SCALE (ONE << CONST_BITS) - -/* Convert a positive real constant to an integer scaled by CONST_SCALE. - * Caution: some C compilers fail to reduce "FIX(constant)" at compile time, - * thus causing a lot of useless floating-point operations at run time. - */ - -#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) - -/* Descale and correctly round an INT32 value that's scaled by N bits. - * We assume RIGHT_SHIFT rounds towards minus infinity, so adding - * the fudge factor is correct for either sign of X. - */ - -#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) - -/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. - * This macro is used only when the two inputs will actually be no more than - * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a - * full 32x32 multiply. This provides a useful speedup on many machines. - * Unfortunately there is no way to specify a 16x16->32 multiply portably - * in C, but some C compilers will do the right thing if you provide the - * correct combination of casts. - */ - -#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ -#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const))) -#endif -#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ -#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const))) -#endif - -#ifndef MULTIPLY16C16 /* default definition */ -#define MULTIPLY16C16(var,const) ((var) * (const)) -#endif - -/* Same except both inputs are variables. */ - -#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ -#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2))) -#endif - -#ifndef MULTIPLY16V16 /* default definition */ -#define MULTIPLY16V16(var1,var2) ((var1) * (var2)) -#endif diff --git a/libs/jpeg6/jddctmgr.cpp b/libs/jpeg6/jddctmgr.cpp deleted file mode 100644 index 71215f1..0000000 --- a/libs/jpeg6/jddctmgr.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* - * jddctmgr.c - * - * Copyright (C) 1994-1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the inverse-DCT management logic. - * This code selects a particular IDCT implementation to be used, - * and it performs related housekeeping chores. No code in this file - * is executed per IDCT step, only during output pass setup. - * - * Note that the IDCT routines are responsible for performing coefficient - * dequantization as well as the IDCT proper. This module sets up the - * dequantization multiplier table needed by the IDCT routine. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - - -/* - * The decompressor input side (jdinput.c) saves away the appropriate - * quantization table for each component at the start of the first scan - * involving that component. (This is necessary in order to correctly - * decode files that reuse Q-table slots.) - * When we are ready to make an output pass, the saved Q-table is converted - * to a multiplier table that will actually be used by the IDCT routine. - * The multiplier table contents are IDCT-method-dependent. To support - * application changes in IDCT method between scans, we can remake the - * multiplier tables if necessary. - * In buffered-image mode, the first output pass may occur before any data - * has been seen for some components, and thus before their Q-tables have - * been saved away. To handle this case, multiplier tables are preset - * to zeroes; the result of the IDCT will be a neutral gray level. - */ - - -/* Private subobject for this module */ - -typedef struct { - struct jpeg_inverse_dct pub; /* public fields */ - - /* This array contains the IDCT method code that each multiplier table - * is currently set up for, or -1 if it's not yet set up. - * The actual multiplier tables are pointed to by dct_table in the - * per-component comp_info structures. - */ - int cur_method[MAX_COMPONENTS]; -} my_idct_controller; - -typedef my_idct_controller * my_idct_ptr; - - -/* Allocated multiplier tables: big enough for any supported variant */ - -typedef union { - ISLOW_MULT_TYPE islow_array[DCTSIZE2]; -#ifdef DCT_IFAST_SUPPORTED - IFAST_MULT_TYPE ifast_array[DCTSIZE2]; -#endif -#ifdef DCT_FLOAT_SUPPORTED - FLOAT_MULT_TYPE float_array[DCTSIZE2]; -#endif -} multiplier_table; - - -/* The current scaled-IDCT routines require ISLOW-style multiplier tables, - * so be sure to compile that code if either ISLOW or SCALING is requested. - */ -#ifdef DCT_ISLOW_SUPPORTED -#define PROVIDE_ISLOW_TABLES -#else -#ifdef IDCT_SCALING_SUPPORTED -#define PROVIDE_ISLOW_TABLES -#endif -#endif - - -/* - * Prepare for an output pass. - * Here we select the proper IDCT routine for each component and build - * a matching multiplier table. - */ - -METHODDEF void -start_pass (j_decompress_ptr cinfo) -{ - my_idct_ptr idct = (my_idct_ptr) cinfo->idct; - int ci, i; - jpeg_component_info *compptr; - int method = 0; - inverse_DCT_method_ptr method_ptr = NULL; - JQUANT_TBL * qtbl; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Select the proper IDCT routine for this component's scaling */ - switch (compptr->DCT_scaled_size) { -#ifdef IDCT_SCALING_SUPPORTED - case 1: - method_ptr = jpeg_idct_1x1; - method = JDCT_ISLOW; /* jidctred uses islow-style table */ - break; - case 2: - method_ptr = jpeg_idct_2x2; - method = JDCT_ISLOW; /* jidctred uses islow-style table */ - break; - case 4: - method_ptr = jpeg_idct_4x4; - method = JDCT_ISLOW; /* jidctred uses islow-style table */ - break; -#endif - case DCTSIZE: - switch (cinfo->dct_method) { -#ifdef DCT_ISLOW_SUPPORTED - case JDCT_ISLOW: - method_ptr = jpeg_idct_islow; - method = JDCT_ISLOW; - break; -#endif -#ifdef DCT_IFAST_SUPPORTED - case JDCT_IFAST: - method_ptr = jpeg_idct_ifast; - method = JDCT_IFAST; - break; -#endif -#ifdef DCT_FLOAT_SUPPORTED - case JDCT_FLOAT: - method_ptr = jpeg_idct_float; - method = JDCT_FLOAT; - break; -#endif - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; - } - break; - default: - ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size); - break; - } - idct->pub.inverse_DCT[ci] = method_ptr; - /* Create multiplier table from quant table. - * However, we can skip this if the component is uninteresting - * or if we already built the table. Also, if no quant table - * has yet been saved for the component, we leave the - * multiplier table all-zero; we'll be reading zeroes from the - * coefficient controller's buffer anyway. - */ - if (! compptr->component_needed || idct->cur_method[ci] == method) - continue; - qtbl = compptr->quant_table; - if (qtbl == NULL) /* happens if no data yet for component */ - continue; - idct->cur_method[ci] = method; - switch (method) { -#ifdef PROVIDE_ISLOW_TABLES - case JDCT_ISLOW: - { - /* For LL&M IDCT method, multipliers are equal to raw quantization - * coefficients, but are stored in natural order as ints. - */ - ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table; - for (i = 0; i < DCTSIZE2; i++) { - ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[jpeg_zigzag_order[i]]; - } - } - break; -#endif -#ifdef DCT_IFAST_SUPPORTED - case JDCT_IFAST: - { - /* For AA&N IDCT method, multipliers are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * For integer operation, the multiplier table is to be scaled by - * IFAST_SCALE_BITS. The multipliers are stored in natural order. - */ - IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table; -#define CONST_BITS 14 - static const INT16 aanscales[DCTSIZE2] = { - /* precomputed values scaled up by 14 bits */ - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, - 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, - 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, - 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, - 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 - }; - SHIFT_TEMPS - - for (i = 0; i < DCTSIZE2; i++) { - ifmtbl[i] = (IFAST_MULT_TYPE) - DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[jpeg_zigzag_order[i]], - (INT32) aanscales[i]), - CONST_BITS-IFAST_SCALE_BITS); - } - } - break; -#endif -#ifdef DCT_FLOAT_SUPPORTED - case JDCT_FLOAT: - { - /* For float AA&N IDCT method, multipliers are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * The multipliers are stored in natural order. - */ - FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table; - int row, col; - static const double aanscalefactor[DCTSIZE] = { - 1.0, 1.387039845, 1.306562965, 1.175875602, - 1.0, 0.785694958, 0.541196100, 0.275899379 - }; - - i = 0; - for (row = 0; row < DCTSIZE; row++) { - for (col = 0; col < DCTSIZE; col++) { - fmtbl[i] = (FLOAT_MULT_TYPE) - ((double) qtbl->quantval[jpeg_zigzag_order[i]] * - aanscalefactor[row] * aanscalefactor[col]); - i++; - } - } - } - break; -#endif - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; - } - } -} - - -/* - * Initialize IDCT manager. - */ - -GLOBAL void -jinit_inverse_dct (j_decompress_ptr cinfo) -{ - my_idct_ptr idct; - int ci; - jpeg_component_info *compptr; - - idct = (my_idct_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_idct_controller)); - cinfo->idct = (struct jpeg_inverse_dct *) idct; - idct->pub.start_pass = start_pass; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Allocate and pre-zero a multiplier table for each component */ - compptr->dct_table = - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(multiplier_table)); - MEMZERO(compptr->dct_table, SIZEOF(multiplier_table)); - /* Mark multiplier table not yet set up for any method */ - idct->cur_method[ci] = -1; - } -} diff --git a/libs/jpeg6/jdhuff.cpp b/libs/jpeg6/jdhuff.cpp deleted file mode 100644 index 95174b1..0000000 --- a/libs/jpeg6/jdhuff.cpp +++ /dev/null @@ -1,574 +0,0 @@ -/* - * jdhuff.c - * - * Copyright (C) 1991-1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains Huffman entropy decoding routines. - * - * Much of the complexity here has to do with supporting input suspension. - * If the data source module demands suspension, we want to be able to back - * up to the start of the current MCU. To do this, we copy state variables - * into local working storage, and update them back to the permanent - * storage only upon successful completion of an MCU. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdhuff.h" /* Declarations shared with jdphuff.c */ - - -/* - * Expanded entropy decoder object for Huffman decoding. - * - * The savable_state subrecord contains fields that change within an MCU, - * but must not be updated permanently until we complete the MCU. - */ - -typedef struct { - int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ -} savable_state; - -/* This macro is to work around compilers with missing or broken - * structure assignment. You'll need to fix this code if you have - * such a compiler and you change MAX_COMPS_IN_SCAN. - */ - -#ifndef NO_STRUCT_ASSIGN -#define ASSIGN_STATE(dest,src) ((dest) = (src)) -#else -#if MAX_COMPS_IN_SCAN == 4 -#define ASSIGN_STATE(dest,src) \ - ((dest).last_dc_val[0] = (src).last_dc_val[0], \ - (dest).last_dc_val[1] = (src).last_dc_val[1], \ - (dest).last_dc_val[2] = (src).last_dc_val[2], \ - (dest).last_dc_val[3] = (src).last_dc_val[3]) -#endif -#endif - - -typedef struct { - struct jpeg_entropy_decoder pub; /* public fields */ - - /* These fields are loaded into local variables at start of each MCU. - * In case of suspension, we exit WITHOUT updating them. - */ - bitread_perm_state bitstate; /* Bit buffer at start of MCU */ - savable_state saved; /* Other state at start of MCU */ - - /* These fields are NOT loaded into local working state. */ - unsigned int restarts_to_go; /* MCUs left in this restart interval */ - - /* Pointers to derived tables (these workspaces have image lifespan) */ - d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; - d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; -} huff_entropy_decoder; - -typedef huff_entropy_decoder * huff_entropy_ptr; - - -/* - * Initialize for a Huffman-compressed scan. - */ - -METHODDEF void -start_pass_huff_decoder (j_decompress_ptr cinfo) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int ci, dctbl, actbl; - jpeg_component_info * compptr; - - /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. - * This ought to be an error condition, but we make it a warning because - * there are some baseline files out there with all zeroes in these bytes. - */ - if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 || - cinfo->Ah != 0 || cinfo->Al != 0) - WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - dctbl = compptr->dc_tbl_no; - actbl = compptr->ac_tbl_no; - /* Make sure requested tables are present */ - if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS || - cinfo->dc_huff_tbl_ptrs[dctbl] == NULL) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); - if (actbl < 0 || actbl >= NUM_HUFF_TBLS || - cinfo->ac_huff_tbl_ptrs[actbl] == NULL) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl); - /* Compute derived values for Huffman tables */ - /* We may do this more than once for a table, but it's not expensive */ - jpeg_make_d_derived_tbl(cinfo, cinfo->dc_huff_tbl_ptrs[dctbl], - & entropy->dc_derived_tbls[dctbl]); - jpeg_make_d_derived_tbl(cinfo, cinfo->ac_huff_tbl_ptrs[actbl], - & entropy->ac_derived_tbls[actbl]); - /* Initialize DC predictions to 0 */ - entropy->saved.last_dc_val[ci] = 0; - } - - /* Initialize bitread state variables */ - entropy->bitstate.bits_left = 0; - entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ - entropy->bitstate.printed_eod = FALSE; - - /* Initialize restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; -} - - -/* - * Compute the derived values for a Huffman table. - * Note this is also used by jdphuff.c. - */ - -GLOBAL void -jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, JHUFF_TBL * htbl, - d_derived_tbl ** pdtbl) -{ - d_derived_tbl *dtbl; - int p, i, l, si; - int lookbits, ctr; - char huffsize[257]; - unsigned int huffcode[257]; - unsigned int code; - - /* Allocate a workspace if we haven't already done so. */ - if (*pdtbl == NULL) - *pdtbl = (d_derived_tbl *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(d_derived_tbl)); - dtbl = *pdtbl; - dtbl->pub = htbl; /* fill in back link */ - - /* Figure C.1: make table of Huffman code length for each symbol */ - /* Note that this is in code-length order. */ - - p = 0; - for (l = 1; l <= 16; l++) { - for (i = 1; i <= (int) htbl->bits[l]; i++) - huffsize[p++] = (char) l; - } - huffsize[p] = 0; - - /* Figure C.2: generate the codes themselves */ - /* Note that this is in code-length order. */ - - code = 0; - si = huffsize[0]; - p = 0; - while (huffsize[p]) { - while (((int) huffsize[p]) == si) { - huffcode[p++] = code; - code++; - } - code <<= 1; - si++; - } - - /* Figure F.15: generate decoding tables for bit-sequential decoding */ - - p = 0; - for (l = 1; l <= 16; l++) { - if (htbl->bits[l]) { - dtbl->valptr[l] = p; /* huffval[] index of 1st symbol of code length l */ - dtbl->mincode[l] = huffcode[p]; /* minimum code of length l */ - p += htbl->bits[l]; - dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */ - } else { - dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ - } - } - dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */ - - /* Compute lookahead tables to speed up decoding. - * First we set all the table entries to 0, indicating "too long"; - * then we iterate through the Huffman codes that are short enough and - * fill in all the entries that correspond to bit sequences starting - * with that code. - */ - - MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits)); - - p = 0; - for (l = 1; l <= HUFF_LOOKAHEAD; l++) { - for (i = 1; i <= (int) htbl->bits[l]; i++, p++) { - /* l = current code's length, p = its index in huffcode[] & huffval[]. */ - /* Generate left-justified code followed by all possible bit sequences */ - lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); - for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { - dtbl->look_nbits[lookbits] = l; - dtbl->look_sym[lookbits] = htbl->huffval[p]; - lookbits++; - } - } - } -} - - -/* - * Out-of-line code for bit fetching (shared with jdphuff.c). - * See jdhuff.h for info about usage. - * Note: current values of get_buffer and bits_left are passed as parameters, - * but are returned in the corresponding fields of the state struct. - * - * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width - * of get_buffer to be used. (On machines with wider words, an even larger - * buffer could be used.) However, on some machines 32-bit shifts are - * quite slow and take time proportional to the number of places shifted. - * (This is true with most PC compilers, for instance.) In this case it may - * be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the - * average shift distance at the cost of more calls to jpeg_fill_bit_buffer. - */ - -#ifdef SLOW_SHIFT_32 -#define MIN_GET_BITS 15 /* minimum allowable value */ -#else -#define MIN_GET_BITS (BIT_BUF_SIZE-7) -#endif - - -GLOBAL boolean -jpeg_fill_bit_buffer (bitread_working_state * state, - register bit_buf_type get_buffer, register int bits_left, - int nbits) -/* Load up the bit buffer to a depth of at least nbits */ -{ - /* Copy heavily used state fields into locals (hopefully registers) */ - register const JOCTET * next_input_byte = state->next_input_byte; - register size_t bytes_in_buffer = state->bytes_in_buffer; - register int c; - - /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */ - /* (It is assumed that no request will be for more than that many bits.) */ - - while (bits_left < MIN_GET_BITS) { - /* Attempt to read a byte */ - if (state->unread_marker != 0) - goto no_more_data; /* can't advance past a marker */ - - if (bytes_in_buffer == 0) { - if (! (*state->cinfo->src->fill_input_buffer) (state->cinfo)) - return FALSE; - next_input_byte = state->cinfo->src->next_input_byte; - bytes_in_buffer = state->cinfo->src->bytes_in_buffer; - } - bytes_in_buffer--; - c = GETJOCTET(*next_input_byte++); - - /* If it's 0xFF, check and discard stuffed zero byte */ - if (c == 0xFF) { - do { - if (bytes_in_buffer == 0) { - if (! (*state->cinfo->src->fill_input_buffer) (state->cinfo)) - return FALSE; - next_input_byte = state->cinfo->src->next_input_byte; - bytes_in_buffer = state->cinfo->src->bytes_in_buffer; - } - bytes_in_buffer--; - c = GETJOCTET(*next_input_byte++); - } while (c == 0xFF); - - if (c == 0) { - /* Found FF/00, which represents an FF data byte */ - c = 0xFF; - } else { - /* Oops, it's actually a marker indicating end of compressed data. */ - /* Better put it back for use later */ - state->unread_marker = c; - - no_more_data: - /* There should be enough bits still left in the data segment; */ - /* if so, just break out of the outer while loop. */ - if (bits_left >= nbits) - break; - /* Uh-oh. Report corrupted data to user and stuff zeroes into - * the data stream, so that we can produce some kind of image. - * Note that this code will be repeated for each byte demanded - * for the rest of the segment. We use a nonvolatile flag to ensure - * that only one warning message appears. - */ - if (! *(state->printed_eod_ptr)) { - WARNMS(state->cinfo, JWRN_HIT_MARKER); - *(state->printed_eod_ptr) = TRUE; - } - c = 0; /* insert a zero byte into bit buffer */ - } - } - - /* OK, load c into get_buffer */ - get_buffer = (get_buffer << 8) | c; - bits_left += 8; - } - - /* Unload the local registers */ - state->next_input_byte = next_input_byte; - state->bytes_in_buffer = bytes_in_buffer; - state->get_buffer = get_buffer; - state->bits_left = bits_left; - - return TRUE; -} - - -/* - * Out-of-line code for Huffman code decoding. - * See jdhuff.h for info about usage. - */ - -GLOBAL int -jpeg_huff_decode (bitread_working_state * state, - register bit_buf_type get_buffer, register int bits_left, - d_derived_tbl * htbl, int min_bits) -{ - register int l = min_bits; - register INT32 code; - - /* HUFF_DECODE has determined that the code is at least min_bits */ - /* bits long, so fetch that many bits in one swoop. */ - - CHECK_BIT_BUFFER(*state, l, return -1); - code = GET_BITS(l); - - /* Collect the rest of the Huffman code one bit at a time. */ - /* This is per Figure F.16 in the JPEG spec. */ - - while (code > htbl->maxcode[l]) { - code <<= 1; - CHECK_BIT_BUFFER(*state, 1, return -1); - code |= GET_BITS(1); - l++; - } - - /* Unload the local registers */ - state->get_buffer = get_buffer; - state->bits_left = bits_left; - - /* With garbage input we may reach the sentinel value l = 17. */ - - if (l > 16) { - WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE); - return 0; /* fake a zero as the safest result */ - } - - return htbl->pub->huffval[ htbl->valptr[l] + - ((int) (code - htbl->mincode[l])) ]; -} - - -/* - * Figure F.12: extend sign bit. - * On some machines, a shift and add will be faster than a table lookup. - */ - -#ifdef AVOID_TABLES - -#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) - -#else - -#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) - -static const int extend_test[16] = /* entry n is 2**(n-1) */ - { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, - 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; - -static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ - { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, - ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, - ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, - ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; - -#endif /* AVOID_TABLES */ - - -/* - * Check for a restart marker & resynchronize decoder. - * Returns FALSE if must suspend. - */ - -LOCAL boolean -process_restart (j_decompress_ptr cinfo) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int ci; - - /* Throw away any unused bits remaining in bit buffer; */ - /* include any full bytes in next_marker's count of discarded bytes */ - cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; - entropy->bitstate.bits_left = 0; - - /* Advance past the RSTn marker */ - if (! (*cinfo->marker->read_restart_marker) (cinfo)) - return FALSE; - - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) - entropy->saved.last_dc_val[ci] = 0; - - /* Reset restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; - - /* Next segment can get another out-of-data warning */ - entropy->bitstate.printed_eod = FALSE; - - return TRUE; -} - - -/* - * Decode and return one MCU's worth of Huffman-compressed coefficients. - * The coefficients are reordered from zigzag order into natural array order, - * but are not dequantized. - * - * The i'th block of the MCU is stored into the block pointed to by - * MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER. - * (Wholesale zeroing is usually a little faster than retail...) - * - * Returns FALSE if data source requested suspension. In that case no - * changes have been made to permanent state. (Exception: some output - * coefficients may already have been assigned. This is harmless for - * this module, since we'll just re-assign them on the next call.) - */ - -METHODDEF boolean -decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - register int s, k, r; - int blkn, ci; - JBLOCKROW block; - BITREAD_STATE_VARS; - savable_state state; - d_derived_tbl * dctbl; - d_derived_tbl * actbl; - jpeg_component_info * compptr; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(state, entropy->saved); - - /* Outer loop handles each block in the MCU */ - - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - dctbl = entropy->dc_derived_tbls[compptr->dc_tbl_no]; - actbl = entropy->ac_derived_tbls[compptr->ac_tbl_no]; - - /* Decode a single block's worth of coefficients */ - - /* Section F.2.2.1: decode the DC coefficient difference */ - HUFF_DECODE(s, br_state, dctbl, return FALSE, label1); - if (s) { - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - } - - /* Shortcut if component's values are not interesting */ - if (! compptr->component_needed) - goto skip_ACs; - - /* Convert DC difference to actual value, update last_dc_val */ - s += state.last_dc_val[ci]; - state.last_dc_val[ci] = s; - /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */ - (*block)[0] = (JCOEF) s; - - /* Do we need to decode the AC coefficients for this component? */ - if (compptr->DCT_scaled_size > 1) { - - /* Section F.2.2.2: decode the AC coefficients */ - /* Since zeroes are skipped, output area must be cleared beforehand */ - for (k = 1; k < DCTSIZE2; k++) { - HUFF_DECODE(s, br_state, actbl, return FALSE, label2); - - r = s >> 4; - s &= 15; - - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - /* Output coefficient in natural (dezigzagged) order. - * Note: the extra entries in jpeg_natural_order[] will save us - * if k >= DCTSIZE2, which could happen if the data is corrupted. - */ - (*block)[jpeg_natural_order[k]] = (JCOEF) s; - } else { - if (r != 15) - break; - k += 15; - } - } - - } else { -skip_ACs: - - /* Section F.2.2.2: decode the AC coefficients */ - /* In this path we just discard the values */ - for (k = 1; k < DCTSIZE2; k++) { - HUFF_DECODE(s, br_state, actbl, return FALSE, label3); - - r = s >> 4; - s &= 15; - - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - DROP_BITS(s); - } else { - if (r != 15) - break; - k += 15; - } - } - - } - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(entropy->saved, state); - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * Module initialization routine for Huffman entropy decoding. - */ - -GLOBAL void -jinit_huff_decoder (j_decompress_ptr cinfo) -{ - huff_entropy_ptr entropy; - int i; - - entropy = (huff_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(huff_entropy_decoder)); - cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; - entropy->pub.start_pass = start_pass_huff_decoder; - entropy->pub.decode_mcu = decode_mcu; - - /* Mark tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; - } -} diff --git a/libs/jpeg6/jdhuff.h b/libs/jpeg6/jdhuff.h deleted file mode 100644 index d375c78..0000000 --- a/libs/jpeg6/jdhuff.h +++ /dev/null @@ -1,202 +0,0 @@ -/* - * jdhuff.h - * - * Copyright (C) 1991-1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains declarations for Huffman entropy decoding routines - * that are shared between the sequential decoder (jdhuff.c) and the - * progressive decoder (jdphuff.c). No other modules need to see these. - */ - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_make_d_derived_tbl jMkDDerived -#define jpeg_fill_bit_buffer jFilBitBuf -#define jpeg_huff_decode jHufDecode -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* Derived data constructed for each Huffman table */ - -#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ - -typedef struct { - /* Basic tables: (element [0] of each array is unused) */ - INT32 mincode[17]; /* smallest code of length k */ - INT32 maxcode[18]; /* largest code of length k (-1 if none) */ - /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ - int valptr[17]; /* huffval[] index of 1st symbol of length k */ - - /* Link to public Huffman table (needed only in jpeg_huff_decode) */ - JHUFF_TBL *pub; - - /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of - * the input data stream. If the next Huffman code is no more - * than HUFF_LOOKAHEAD bits long, we can obtain its length and - * the corresponding symbol directly from these tables. - */ - int look_nbits[1<<HUFF_LOOKAHEAD]; /* # bits, or 0 if too long */ - UINT8 look_sym[1<<HUFF_LOOKAHEAD]; /* symbol, or unused */ -} d_derived_tbl; - -/* Expand a Huffman table definition into the derived format */ -EXTERN void jpeg_make_d_derived_tbl JPP((j_decompress_ptr cinfo, - JHUFF_TBL * htbl, d_derived_tbl ** pdtbl)); - - -/* - * Fetching the next N bits from the input stream is a time-critical operation - * for the Huffman decoders. We implement it with a combination of inline - * macros and out-of-line subroutines. Note that N (the number of bits - * demanded at one time) never exceeds 15 for JPEG use. - * - * We read source bytes into get_buffer and dole out bits as needed. - * If get_buffer already contains enough bits, they are fetched in-line - * by the macros CHECK_BIT_BUFFER and GET_BITS. When there aren't enough - * bits, jpeg_fill_bit_buffer is called; it will attempt to fill get_buffer - * as full as possible (not just to the number of bits needed; this - * prefetching reduces the overhead cost of calling jpeg_fill_bit_buffer). - * Note that jpeg_fill_bit_buffer may return FALSE to indicate suspension. - * On TRUE return, jpeg_fill_bit_buffer guarantees that get_buffer contains - * at least the requested number of bits --- dummy zeroes are inserted if - * necessary. - */ - -typedef INT32 bit_buf_type; /* type of bit-extraction buffer */ -#define BIT_BUF_SIZE 32 /* size of buffer in bits */ - -/* If long is > 32 bits on your machine, and shifting/masking longs is - * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE - * appropriately should be a win. Unfortunately we can't do this with - * something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) - * because not all machines measure sizeof in 8-bit bytes. - */ - -typedef struct { /* Bitreading state saved across MCUs */ - bit_buf_type get_buffer; /* current bit-extraction buffer */ - int bits_left; /* # of unused bits in it */ - boolean printed_eod; /* flag to suppress multiple warning msgs */ -} bitread_perm_state; - -typedef struct { /* Bitreading working state within an MCU */ - /* current data source state */ - const JOCTET * next_input_byte; /* => next byte to read from source */ - size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ - int unread_marker; /* nonzero if we have hit a marker */ - /* bit input buffer --- note these values are kept in register variables, - * not in this struct, inside the inner loops. - */ - bit_buf_type get_buffer; /* current bit-extraction buffer */ - int bits_left; /* # of unused bits in it */ - /* pointers needed by jpeg_fill_bit_buffer */ - j_decompress_ptr cinfo; /* back link to decompress master record */ - boolean * printed_eod_ptr; /* => flag in permanent state */ -} bitread_working_state; - -/* Macros to declare and load/save bitread local variables. */ -#define BITREAD_STATE_VARS \ - register bit_buf_type get_buffer; \ - register int bits_left; \ - bitread_working_state br_state - -#define BITREAD_LOAD_STATE(cinfop,permstate) \ - br_state.cinfo = cinfop; \ - br_state.next_input_byte = cinfop->src->next_input_byte; \ - br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ - br_state.unread_marker = cinfop->unread_marker; \ - get_buffer = permstate.get_buffer; \ - bits_left = permstate.bits_left; \ - br_state.printed_eod_ptr = & permstate.printed_eod - -#define BITREAD_SAVE_STATE(cinfop,permstate) \ - cinfop->src->next_input_byte = br_state.next_input_byte; \ - cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ - cinfop->unread_marker = br_state.unread_marker; \ - permstate.get_buffer = get_buffer; \ - permstate.bits_left = bits_left - -/* - * These macros provide the in-line portion of bit fetching. - * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer - * before using GET_BITS, PEEK_BITS, or DROP_BITS. - * The variables get_buffer and bits_left are assumed to be locals, - * but the state struct might not be (jpeg_huff_decode needs this). - * CHECK_BIT_BUFFER(state,n,action); - * Ensure there are N bits in get_buffer; if suspend, take action. - * val = GET_BITS(n); - * Fetch next N bits. - * val = PEEK_BITS(n); - * Fetch next N bits without removing them from the buffer. - * DROP_BITS(n); - * Discard next N bits. - * The value N should be a simple variable, not an expression, because it - * is evaluated multiple times. - */ - -#define CHECK_BIT_BUFFER(state,nbits,action) \ - { if (bits_left < (nbits)) { \ - if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ - { action; } \ - get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } - -#define GET_BITS(nbits) \ - (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1)) - -#define PEEK_BITS(nbits) \ - (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1)) - -#define DROP_BITS(nbits) \ - (bits_left -= (nbits)) - -/* Load up the bit buffer to a depth of at least nbits */ -EXTERN boolean jpeg_fill_bit_buffer JPP((bitread_working_state * state, - register bit_buf_type get_buffer, register int bits_left, - int nbits)); - - -/* - * Code for extracting next Huffman-coded symbol from input bit stream. - * Again, this is time-critical and we make the main paths be macros. - * - * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits - * without looping. Usually, more than 95% of the Huffman codes will be 8 - * or fewer bits long. The few overlength codes are handled with a loop, - * which need not be inline code. - * - * Notes about the HUFF_DECODE macro: - * 1. Near the end of the data segment, we may fail to get enough bits - * for a lookahead. In that case, we do it the hard way. - * 2. If the lookahead table contains no entry, the next code must be - * more than HUFF_LOOKAHEAD bits long. - * 3. jpeg_huff_decode returns -1 if forced to suspend. - */ - -#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ -{ register int nb, look; \ - if (bits_left < HUFF_LOOKAHEAD) { \ - if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ - get_buffer = state.get_buffer; bits_left = state.bits_left; \ - if (bits_left < HUFF_LOOKAHEAD) { \ - nb = 1; goto slowlabel; \ - } \ - } \ - look = PEEK_BITS(HUFF_LOOKAHEAD); \ - if ((nb = htbl->look_nbits[look]) != 0) { \ - DROP_BITS(nb); \ - result = htbl->look_sym[look]; \ - } else { \ - nb = HUFF_LOOKAHEAD+1; \ -slowlabel: \ - if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ - { failaction; } \ - get_buffer = state.get_buffer; bits_left = state.bits_left; \ - } \ -} - -/* Out-of-line case for Huffman code fetching */ -EXTERN int jpeg_huff_decode JPP((bitread_working_state * state, - register bit_buf_type get_buffer, register int bits_left, - d_derived_tbl * htbl, int min_bits)); diff --git a/libs/jpeg6/jdinput.cpp b/libs/jpeg6/jdinput.cpp deleted file mode 100644 index 3061a17..0000000 --- a/libs/jpeg6/jdinput.cpp +++ /dev/null @@ -1,381 +0,0 @@ -/* - * jdinput.c - * - * Copyright (C) 1991-1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains input control logic for the JPEG decompressor. - * These routines are concerned with controlling the decompressor's input - * processing (marker reading and coefficient decoding). The actual input - * reading is done in jdmarker.c, jdhuff.c, and jdphuff.c. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Private state */ - -typedef struct { - struct jpeg_input_controller pub; /* public fields */ - - boolean inheaders; /* TRUE until first SOS is reached */ -} my_input_controller; - -typedef my_input_controller * my_inputctl_ptr; - - -/* Forward declarations */ -METHODDEF int consume_markers JPP((j_decompress_ptr cinfo)); - - -/* - * Routines to calculate various quantities related to the size of the image. - */ - -LOCAL void -initial_setup (j_decompress_ptr cinfo) -/* Called once, when first SOS marker is reached */ -{ - int ci; - jpeg_component_info *compptr; - - /* Make sure image isn't bigger than I can handle */ - if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || - (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) - ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); - - /* For now, precision must match compiled-in value... */ - if (cinfo->data_precision != BITS_IN_JSAMPLE) - ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); - - /* Check that number of components won't exceed internal array sizes */ - if (cinfo->num_components > MAX_COMPONENTS) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, - MAX_COMPONENTS); - - /* Compute maximum sampling factors; check factor validity */ - cinfo->max_h_samp_factor = 1; - cinfo->max_v_samp_factor = 1; - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || - compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) - ERREXIT(cinfo, JERR_BAD_SAMPLING); - cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, - compptr->h_samp_factor); - cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, - compptr->v_samp_factor); - } - - /* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE. - * In the full decompressor, this will be overridden by jdmaster.c; - * but in the transcoder, jdmaster.c is not used, so we must do it here. - */ - cinfo->min_DCT_scaled_size = DCTSIZE; - - /* Compute dimensions of components */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - compptr->DCT_scaled_size = DCTSIZE; - /* Size in DCT blocks */ - compptr->width_in_blocks = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) (cinfo->max_h_samp_factor * DCTSIZE)); - compptr->height_in_blocks = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) (cinfo->max_v_samp_factor * DCTSIZE)); - /* downsampled_width and downsampled_height will also be overridden by - * jdmaster.c if we are doing full decompression. The transcoder library - * doesn't use these values, but the calling application might. - */ - /* Size in samples */ - compptr->downsampled_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) cinfo->max_h_samp_factor); - compptr->downsampled_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) cinfo->max_v_samp_factor); - /* Mark component needed, until color conversion says otherwise */ - compptr->component_needed = TRUE; - /* Mark no quantization table yet saved for component */ - compptr->quant_table = NULL; - } - - /* Compute number of fully interleaved MCU rows. */ - cinfo->total_iMCU_rows = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor*DCTSIZE)); - - /* Decide whether file contains multiple scans */ - if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode) - cinfo->inputctl->has_multiple_scans = TRUE; - else - cinfo->inputctl->has_multiple_scans = FALSE; -} - - -LOCAL void -per_scan_setup (j_decompress_ptr cinfo) -/* Do computations that are needed before processing a JPEG scan */ -/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */ -{ - int ci, mcublks, tmp; - jpeg_component_info *compptr; - - if (cinfo->comps_in_scan == 1) { - - /* Noninterleaved (single-component) scan */ - compptr = cinfo->cur_comp_info[0]; - - /* Overall image size in MCUs */ - cinfo->MCUs_per_row = compptr->width_in_blocks; - cinfo->MCU_rows_in_scan = compptr->height_in_blocks; - - /* For noninterleaved scan, always one block per MCU */ - compptr->MCU_width = 1; - compptr->MCU_height = 1; - compptr->MCU_blocks = 1; - compptr->MCU_sample_width = compptr->DCT_scaled_size; - compptr->last_col_width = 1; - /* For noninterleaved scans, it is convenient to define last_row_height - * as the number of block rows present in the last iMCU row. - */ - tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (tmp == 0) tmp = compptr->v_samp_factor; - compptr->last_row_height = tmp; - - /* Prepare array describing MCU composition */ - cinfo->blocks_in_MCU = 1; - cinfo->MCU_membership[0] = 0; - - } else { - - /* Interleaved (multi-component) scan */ - if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, - MAX_COMPS_IN_SCAN); - - /* Overall image size in MCUs */ - cinfo->MCUs_per_row = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, - (long) (cinfo->max_h_samp_factor*DCTSIZE)); - cinfo->MCU_rows_in_scan = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor*DCTSIZE)); - - cinfo->blocks_in_MCU = 0; - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Sampling factors give # of blocks of component in each MCU */ - compptr->MCU_width = compptr->h_samp_factor; - compptr->MCU_height = compptr->v_samp_factor; - compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; - compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size; - /* Figure number of non-dummy blocks in last MCU column & row */ - tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); - if (tmp == 0) tmp = compptr->MCU_width; - compptr->last_col_width = tmp; - tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); - if (tmp == 0) tmp = compptr->MCU_height; - compptr->last_row_height = tmp; - /* Prepare array describing MCU composition */ - mcublks = compptr->MCU_blocks; - if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU) - ERREXIT(cinfo, JERR_BAD_MCU_SIZE); - while (mcublks-- > 0) { - cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; - } - } - - } -} - - -/* - * Save away a copy of the Q-table referenced by each component present - * in the current scan, unless already saved during a prior scan. - * - * In a multiple-scan JPEG file, the encoder could assign different components - * the same Q-table slot number, but change table definitions between scans - * so that each component uses a different Q-table. (The IJG encoder is not - * currently capable of doing this, but other encoders might.) Since we want - * to be able to dequantize all the components at the end of the file, this - * means that we have to save away the table actually used for each component. - * We do this by copying the table at the start of the first scan containing - * the component. - * The JPEG spec prohibits the encoder from changing the contents of a Q-table - * slot between scans of a component using that slot. If the encoder does so - * anyway, this decoder will simply use the Q-table values that were current - * at the start of the first scan for the component. - * - * The decompressor output side looks only at the saved quant tables, - * not at the current Q-table slots. - */ - -LOCAL void -latch_quant_tables (j_decompress_ptr cinfo) -{ - int ci, qtblno; - jpeg_component_info *compptr; - JQUANT_TBL * qtbl; - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* No work if we already saved Q-table for this component */ - if (compptr->quant_table != NULL) - continue; - /* Make sure specified quantization table is present */ - qtblno = compptr->quant_tbl_no; - if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || - cinfo->quant_tbl_ptrs[qtblno] == NULL) - ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); - /* OK, save away the quantization table */ - qtbl = (JQUANT_TBL *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(JQUANT_TBL)); - MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); - compptr->quant_table = qtbl; - } -} - - -/* - * Initialize the input modules to read a scan of compressed data. - * The first call to this is done by jdmaster.c after initializing - * the entire decompressor (during jpeg_start_decompress). - * Subsequent calls come from consume_markers, below. - */ - -METHODDEF void -start_input_pass (j_decompress_ptr cinfo) -{ - per_scan_setup(cinfo); - latch_quant_tables(cinfo); - (*cinfo->entropy->start_pass) (cinfo); - (*cinfo->coef->start_input_pass) (cinfo); - cinfo->inputctl->consume_input = cinfo->coef->consume_data; -} - - -/* - * Finish up after inputting a compressed-data scan. - * This is called by the coefficient controller after it's read all - * the expected data of the scan. - */ - -METHODDEF void -finish_input_pass (j_decompress_ptr cinfo) -{ - cinfo->inputctl->consume_input = consume_markers; -} - - -/* - * Read JPEG markers before, between, or after compressed-data scans. - * Change state as necessary when a new scan is reached. - * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. - * - * The consume_input method pointer points either here or to the - * coefficient controller's consume_data routine, depending on whether - * we are reading a compressed data segment or inter-segment markers. - */ - -METHODDEF int -consume_markers (j_decompress_ptr cinfo) -{ - my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; - int val; - - if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */ - return JPEG_REACHED_EOI; - - val = (*cinfo->marker->read_markers) (cinfo); - - switch (val) { - case JPEG_REACHED_SOS: /* Found SOS */ - if (inputctl->inheaders) { /* 1st SOS */ - initial_setup(cinfo); - inputctl->inheaders = FALSE; - /* Note: start_input_pass must be called by jdmaster.c - * before any more input can be consumed. jdapi.c is - * responsible for enforcing this sequencing. - */ - } else { /* 2nd or later SOS marker */ - if (! inputctl->pub.has_multiple_scans) - ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ - start_input_pass(cinfo); - } - break; - case JPEG_REACHED_EOI: /* Found EOI */ - inputctl->pub.eoi_reached = TRUE; - if (inputctl->inheaders) { /* Tables-only datastream, apparently */ - if (cinfo->marker->saw_SOF) - ERREXIT(cinfo, JERR_SOF_NO_SOS); - } else { - /* Prevent infinite loop in coef ctlr's decompress_data routine - * if user set output_scan_number larger than number of scans. - */ - if (cinfo->output_scan_number > cinfo->input_scan_number) - cinfo->output_scan_number = cinfo->input_scan_number; - } - break; - case JPEG_SUSPENDED: - break; - } - - return val; -} - - -/* - * Reset state to begin a fresh datastream. - */ - -METHODDEF void -reset_input_controller (j_decompress_ptr cinfo) -{ - my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; - - inputctl->pub.consume_input = consume_markers; - inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ - inputctl->pub.eoi_reached = FALSE; - inputctl->inheaders = TRUE; - /* Reset other modules */ - (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); - (*cinfo->marker->reset_marker_reader) (cinfo); - /* Reset progression state -- would be cleaner if entropy decoder did this */ - cinfo->coef_bits = NULL; -} - - -/* - * Initialize the input controller module. - * This is called only once, when the decompression object is created. - */ - -GLOBAL void -jinit_input_controller (j_decompress_ptr cinfo) -{ - my_inputctl_ptr inputctl; - - /* Create subobject in permanent pool */ - inputctl = (my_inputctl_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(my_input_controller)); - cinfo->inputctl = (struct jpeg_input_controller *) inputctl; - /* Initialize method pointers */ - inputctl->pub.consume_input = consume_markers; - inputctl->pub.reset_input_controller = reset_input_controller; - inputctl->pub.start_input_pass = start_input_pass; - inputctl->pub.finish_input_pass = finish_input_pass; - /* Initialize state: can't use reset_input_controller since we don't - * want to try to reset other modules yet. - */ - inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ - inputctl->pub.eoi_reached = FALSE; - inputctl->inheaders = TRUE; -} diff --git a/libs/jpeg6/jdmainct.cpp b/libs/jpeg6/jdmainct.cpp deleted file mode 100644 index f3a06e5..0000000 --- a/libs/jpeg6/jdmainct.cpp +++ /dev/null @@ -1,512 +0,0 @@ -/* - * jdmainct.c - * - * Copyright (C) 1994-1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the main buffer controller for decompression. - * The main buffer lies between the JPEG decompressor proper and the - * post-processor; it holds downsampled data in the JPEG colorspace. - * - * Note that this code is bypassed in raw-data mode, since the application - * supplies the equivalent of the main buffer in that case. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * In the current system design, the main buffer need never be a full-image - * buffer; any full-height buffers will be found inside the coefficient or - * postprocessing controllers. Nonetheless, the main controller is not - * trivial. Its responsibility is to provide context rows for upsampling/ - * rescaling, and doing this in an efficient fashion is a bit tricky. - * - * Postprocessor input data is counted in "row groups". A row group - * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) - * sample rows of each component. (We require DCT_scaled_size values to be - * chosen such that these numbers are integers. In practice DCT_scaled_size - * values will likely be powers of two, so we actually have the stronger - * condition that DCT_scaled_size / min_DCT_scaled_size is an integer.) - * Upsampling will typically produce max_v_samp_factor pixel rows from each - * row group (times any additional scale factor that the upsampler is - * applying). - * - * The coefficient controller will deliver data to us one iMCU row at a time; - * each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or - * exactly min_DCT_scaled_size row groups. (This amount of data corresponds - * to one row of MCUs when the image is fully interleaved.) Note that the - * number of sample rows varies across components, but the number of row - * groups does not. Some garbage sample rows may be included in the last iMCU - * row at the bottom of the image. - * - * Depending on the vertical scaling algorithm used, the upsampler may need - * access to the sample row(s) above and below its current input row group. - * The upsampler is required to set need_context_rows TRUE at global selection - * time if so. When need_context_rows is FALSE, this controller can simply - * obtain one iMCU row at a time from the coefficient controller and dole it - * out as row groups to the postprocessor. - * - * When need_context_rows is TRUE, this controller guarantees that the buffer - * passed to postprocessing contains at least one row group's worth of samples - * above and below the row group(s) being processed. Note that the context - * rows "above" the first passed row group appear at negative row offsets in - * the passed buffer. At the top and bottom of the image, the required - * context rows are manufactured by duplicating the first or last real sample - * row; this avoids having special cases in the upsampling inner loops. - * - * The amount of context is fixed at one row group just because that's a - * convenient number for this controller to work with. The existing - * upsamplers really only need one sample row of context. An upsampler - * supporting arbitrary output rescaling might wish for more than one row - * group of context when shrinking the image; tough, we don't handle that. - * (This is justified by the assumption that downsizing will be handled mostly - * by adjusting the DCT_scaled_size values, so that the actual scale factor at - * the upsample step needn't be much less than one.) - * - * To provide the desired context, we have to retain the last two row groups - * of one iMCU row while reading in the next iMCU row. (The last row group - * can't be processed until we have another row group for its below-context, - * and so we have to save the next-to-last group too for its above-context.) - * We could do this most simply by copying data around in our buffer, but - * that'd be very slow. We can avoid copying any data by creating a rather - * strange pointer structure. Here's how it works. We allocate a workspace - * consisting of M+2 row groups (where M = min_DCT_scaled_size is the number - * of row groups per iMCU row). We create two sets of redundant pointers to - * the workspace. Labeling the physical row groups 0 to M+1, the synthesized - * pointer lists look like this: - * M+1 M-1 - * master pointer --> 0 master pointer --> 0 - * 1 1 - * ... ... - * M-3 M-3 - * M-2 M - * M-1 M+1 - * M M-2 - * M+1 M-1 - * 0 0 - * We read alternate iMCU rows using each master pointer; thus the last two - * row groups of the previous iMCU row remain un-overwritten in the workspace. - * The pointer lists are set up so that the required context rows appear to - * be adjacent to the proper places when we pass the pointer lists to the - * upsampler. - * - * The above pictures describe the normal state of the pointer lists. - * At top and bottom of the image, we diddle the pointer lists to duplicate - * the first or last sample row as necessary (this is cheaper than copying - * sample rows around). - * - * This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that - * situation each iMCU row provides only one row group so the buffering logic - * must be different (eg, we must read two iMCU rows before we can emit the - * first row group). For now, we simply do not support providing context - * rows when min_DCT_scaled_size is 1. That combination seems unlikely to - * be worth providing --- if someone wants a 1/8th-size preview, they probably - * want it quick and dirty, so a context-free upsampler is sufficient. - */ - - -/* Private buffer controller object */ - -typedef struct { - struct jpeg_d_main_controller pub; /* public fields */ - - /* Pointer to allocated workspace (M or M+2 row groups). */ - JSAMPARRAY buffer[MAX_COMPONENTS]; - - boolean buffer_full; /* Have we gotten an iMCU row from decoder? */ - JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */ - - /* Remaining fields are only used in the context case. */ - - /* These are the master pointers to the funny-order pointer lists. */ - JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ - - int whichptr; /* indicates which pointer set is now in use */ - int context_state; /* process_data state machine status */ - JDIMENSION rowgroups_avail; /* row groups available to postprocessor */ - JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */ -} my_main_controller; - -typedef my_main_controller * my_main_ptr; - -/* context_state values: */ -#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */ -#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */ -#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */ - - -/* Forward declarations */ -METHODDEF void process_data_simple_main - JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); -METHODDEF void process_data_context_main - JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); -#ifdef QUANT_2PASS_SUPPORTED -METHODDEF void process_data_crank_post - JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); -#endif - - -LOCAL void -alloc_funny_pointers (j_decompress_ptr cinfo) -/* Allocate space for the funny pointer lists. - * This is done only once, not once per pass. - */ -{ - my_main_ptr main = (my_main_ptr) cinfo->main; - int ci, rgroup; - int M = cinfo->min_DCT_scaled_size; - jpeg_component_info *compptr; - JSAMPARRAY xbuf; - - /* Get top-level space for component array pointers. - * We alloc both arrays with one call to save a few cycles. - */ - main->xbuffer[0] = (JSAMPIMAGE) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); - main->xbuffer[1] = main->xbuffer[0] + cinfo->num_components; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; /* height of a row group of component */ - /* Get space for pointer lists --- M+4 row groups in each list. - * We alloc both pointer lists with one call to save a few cycles. - */ - xbuf = (JSAMPARRAY) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW)); - xbuf += rgroup; /* want one row group at negative offsets */ - main->xbuffer[0][ci] = xbuf; - xbuf += rgroup * (M + 4); - main->xbuffer[1][ci] = xbuf; - } -} - - -LOCAL void -make_funny_pointers (j_decompress_ptr cinfo) -/* Create the funny pointer lists discussed in the comments above. - * The actual workspace is already allocated (in main->buffer), - * and the space for the pointer lists is allocated too. - * This routine just fills in the curiously ordered lists. - * This will be repeated at the beginning of each pass. - */ -{ - my_main_ptr main = (my_main_ptr) cinfo->main; - int ci, i, rgroup; - int M = cinfo->min_DCT_scaled_size; - jpeg_component_info *compptr; - JSAMPARRAY buf, xbuf0, xbuf1; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; /* height of a row group of component */ - xbuf0 = main->xbuffer[0][ci]; - xbuf1 = main->xbuffer[1][ci]; - /* First copy the workspace pointers as-is */ - buf = main->buffer[ci]; - for (i = 0; i < rgroup * (M + 2); i++) { - xbuf0[i] = xbuf1[i] = buf[i]; - } - /* In the second list, put the last four row groups in swapped order */ - for (i = 0; i < rgroup * 2; i++) { - xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i]; - xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i]; - } - /* The wraparound pointers at top and bottom will be filled later - * (see set_wraparound_pointers, below). Initially we want the "above" - * pointers to duplicate the first actual data line. This only needs - * to happen in xbuffer[0]. - */ - for (i = 0; i < rgroup; i++) { - xbuf0[i - rgroup] = xbuf0[0]; - } - } -} - - -LOCAL void -set_wraparound_pointers (j_decompress_ptr cinfo) -/* Set up the "wraparound" pointers at top and bottom of the pointer lists. - * This changes the pointer list state from top-of-image to the normal state. - */ -{ - my_main_ptr main = (my_main_ptr) cinfo->main; - int ci, i, rgroup; - int M = cinfo->min_DCT_scaled_size; - jpeg_component_info *compptr; - JSAMPARRAY xbuf0, xbuf1; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; /* height of a row group of component */ - xbuf0 = main->xbuffer[0][ci]; - xbuf1 = main->xbuffer[1][ci]; - for (i = 0; i < rgroup; i++) { - xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i]; - xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i]; - xbuf0[rgroup*(M+2) + i] = xbuf0[i]; - xbuf1[rgroup*(M+2) + i] = xbuf1[i]; - } - } -} - - -LOCAL void -set_bottom_pointers (j_decompress_ptr cinfo) -/* Change the pointer lists to duplicate the last sample row at the bottom - * of the image. whichptr indicates which xbuffer holds the final iMCU row. - * Also sets rowgroups_avail to indicate number of nondummy row groups in row. - */ -{ - my_main_ptr main = (my_main_ptr) cinfo->main; - int ci, i, rgroup, iMCUheight, rows_left; - jpeg_component_info *compptr; - JSAMPARRAY xbuf; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Count sample rows in one iMCU row and in one row group */ - iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size; - rgroup = iMCUheight / cinfo->min_DCT_scaled_size; - /* Count nondummy sample rows remaining for this component */ - rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); - if (rows_left == 0) rows_left = iMCUheight; - /* Count nondummy row groups. Should get same answer for each component, - * so we need only do it once. - */ - if (ci == 0) { - main->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); - } - /* Duplicate the last real sample row rgroup*2 times; this pads out the - * last partial rowgroup and ensures at least one full rowgroup of context. - */ - xbuf = main->xbuffer[main->whichptr][ci]; - for (i = 0; i < rgroup * 2; i++) { - xbuf[rows_left + i] = xbuf[rows_left-1]; - } - } -} - - -/* - * Initialize for a processing pass. - */ - -METHODDEF void -start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) -{ - my_main_ptr main = (my_main_ptr) cinfo->main; - - switch (pass_mode) { - case JBUF_PASS_THRU: - if (cinfo->upsample->need_context_rows) { - main->pub.process_data = process_data_context_main; - make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ - main->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ - main->context_state = CTX_PREPARE_FOR_IMCU; - main->iMCU_row_ctr = 0; - } else { - /* Simple case with no context needed */ - main->pub.process_data = process_data_simple_main; - } - main->buffer_full = FALSE; /* Mark buffer empty */ - main->rowgroup_ctr = 0; - break; -#ifdef QUANT_2PASS_SUPPORTED - case JBUF_CRANK_DEST: - /* For last pass of 2-pass quantization, just crank the postprocessor */ - main->pub.process_data = process_data_crank_post; - break; -#endif - default: - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - break; - } -} - - -/* - * Process some data. - * This handles the simple case where no context is required. - */ - -METHODDEF void -process_data_simple_main (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_main_ptr main = (my_main_ptr) cinfo->main; - JDIMENSION rowgroups_avail; - - /* Read input data if we haven't filled the main buffer yet */ - if (! main->buffer_full) { - if (! (*cinfo->coef->decompress_data) (cinfo, main->buffer)) - return; /* suspension forced, can do nothing more */ - main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ - } - - /* There are always min_DCT_scaled_size row groups in an iMCU row. */ - rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size; - /* Note: at the bottom of the image, we may pass extra garbage row groups - * to the postprocessor. The postprocessor has to check for bottom - * of image anyway (at row resolution), so no point in us doing it too. - */ - - /* Feed the postprocessor */ - (*cinfo->post->post_process_data) (cinfo, main->buffer, - &main->rowgroup_ctr, rowgroups_avail, - output_buf, out_row_ctr, out_rows_avail); - - /* Has postprocessor consumed all the data yet? If so, mark buffer empty */ - if (main->rowgroup_ctr >= rowgroups_avail) { - main->buffer_full = FALSE; - main->rowgroup_ctr = 0; - } -} - - -/* - * Process some data. - * This handles the case where context rows must be provided. - */ - -METHODDEF void -process_data_context_main (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_main_ptr main = (my_main_ptr) cinfo->main; - - /* Read input data if we haven't filled the main buffer yet */ - if (! main->buffer_full) { - if (! (*cinfo->coef->decompress_data) (cinfo, - main->xbuffer[main->whichptr])) - return; /* suspension forced, can do nothing more */ - main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ - main->iMCU_row_ctr++; /* count rows received */ - } - - /* Postprocessor typically will not swallow all the input data it is handed - * in one call (due to filling the output buffer first). Must be prepared - * to exit and restart. This switch lets us keep track of how far we got. - * Note that each case falls through to the next on successful completion. - */ - switch (main->context_state) { - case CTX_POSTPONED_ROW: - /* Call postprocessor using previously set pointers for postponed row */ - (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr], - &main->rowgroup_ctr, main->rowgroups_avail, - output_buf, out_row_ctr, out_rows_avail); - if (main->rowgroup_ctr < main->rowgroups_avail) - return; /* Need to suspend */ - main->context_state = CTX_PREPARE_FOR_IMCU; - if (*out_row_ctr >= out_rows_avail) - return; /* Postprocessor exactly filled output buf */ - /*FALLTHROUGH*/ - case CTX_PREPARE_FOR_IMCU: - /* Prepare to process first M-1 row groups of this iMCU row */ - main->rowgroup_ctr = 0; - main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1); - /* Check for bottom of image: if so, tweak pointers to "duplicate" - * the last sample row, and adjust rowgroups_avail to ignore padding rows. - */ - if (main->iMCU_row_ctr == cinfo->total_iMCU_rows) - set_bottom_pointers(cinfo); - main->context_state = CTX_PROCESS_IMCU; - /*FALLTHROUGH*/ - case CTX_PROCESS_IMCU: - /* Call postprocessor using previously set pointers */ - (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr], - &main->rowgroup_ctr, main->rowgroups_avail, - output_buf, out_row_ctr, out_rows_avail); - if (main->rowgroup_ctr < main->rowgroups_avail) - return; /* Need to suspend */ - /* After the first iMCU, change wraparound pointers to normal state */ - if (main->iMCU_row_ctr == 1) - set_wraparound_pointers(cinfo); - /* Prepare to load new iMCU row using other xbuffer list */ - main->whichptr ^= 1; /* 0=>1 or 1=>0 */ - main->buffer_full = FALSE; - /* Still need to process last row group of this iMCU row, */ - /* which is saved at index M+1 of the other xbuffer */ - main->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1); - main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2); - main->context_state = CTX_POSTPONED_ROW; - } -} - - -/* - * Process some data. - * Final pass of two-pass quantization: just call the postprocessor. - * Source data will be the postprocessor controller's internal buffer. - */ - -#ifdef QUANT_2PASS_SUPPORTED - -METHODDEF void -process_data_crank_post (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL, - (JDIMENSION *) NULL, (JDIMENSION) 0, - output_buf, out_row_ctr, out_rows_avail); -} - -#endif /* QUANT_2PASS_SUPPORTED */ - - -/* - * Initialize main buffer controller. - */ - -GLOBAL void -jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) -{ - my_main_ptr main; - int ci, rgroup, ngroups; - jpeg_component_info *compptr; - - main = (my_main_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_main_controller)); - cinfo->main = (struct jpeg_d_main_controller *) main; - main->pub.start_pass = start_pass_main; - - if (need_full_buffer) /* shouldn't happen */ - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - - /* Allocate the workspace. - * ngroups is the number of row groups we need. - */ - if (cinfo->upsample->need_context_rows) { - if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */ - ERREXIT(cinfo, JERR_NOTIMPL); - alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */ - ngroups = cinfo->min_DCT_scaled_size + 2; - } else { - ngroups = cinfo->min_DCT_scaled_size; - } - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; /* height of a row group of component */ - main->buffer[ci] = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - compptr->width_in_blocks * compptr->DCT_scaled_size, - (JDIMENSION) (rgroup * ngroups)); - } -} diff --git a/libs/jpeg6/jdmarker.cpp b/libs/jpeg6/jdmarker.cpp deleted file mode 100644 index 80e5f78..0000000 --- a/libs/jpeg6/jdmarker.cpp +++ /dev/null @@ -1,1052 +0,0 @@ -/* - * jdmarker.c - * - * Copyright (C) 1991-1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains routines to decode JPEG datastream markers. - * Most of the complexity arises from our desire to support input - * suspension: if not all of the data for a marker is available, - * we must exit back to the application. On resumption, we reprocess - * the marker. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -typedef enum { /* JPEG marker codes */ - M_SOF0 = 0xc0, - M_SOF1 = 0xc1, - M_SOF2 = 0xc2, - M_SOF3 = 0xc3, - - M_SOF5 = 0xc5, - M_SOF6 = 0xc6, - M_SOF7 = 0xc7, - - M_JPG = 0xc8, - M_SOF9 = 0xc9, - M_SOF10 = 0xca, - M_SOF11 = 0xcb, - - M_SOF13 = 0xcd, - M_SOF14 = 0xce, - M_SOF15 = 0xcf, - - M_DHT = 0xc4, - - M_DAC = 0xcc, - - M_RST0 = 0xd0, - M_RST1 = 0xd1, - M_RST2 = 0xd2, - M_RST3 = 0xd3, - M_RST4 = 0xd4, - M_RST5 = 0xd5, - M_RST6 = 0xd6, - M_RST7 = 0xd7, - - M_SOI = 0xd8, - M_EOI = 0xd9, - M_SOS = 0xda, - M_DQT = 0xdb, - M_DNL = 0xdc, - M_DRI = 0xdd, - M_DHP = 0xde, - M_EXP = 0xdf, - - M_APP0 = 0xe0, - M_APP1 = 0xe1, - M_APP2 = 0xe2, - M_APP3 = 0xe3, - M_APP4 = 0xe4, - M_APP5 = 0xe5, - M_APP6 = 0xe6, - M_APP7 = 0xe7, - M_APP8 = 0xe8, - M_APP9 = 0xe9, - M_APP10 = 0xea, - M_APP11 = 0xeb, - M_APP12 = 0xec, - M_APP13 = 0xed, - M_APP14 = 0xee, - M_APP15 = 0xef, - - M_JPG0 = 0xf0, - M_JPG13 = 0xfd, - M_COM = 0xfe, - - M_TEM = 0x01, - - M_ERROR = 0x100 -} JPEG_MARKER; - - -/* - * Macros for fetching data from the data source module. - * - * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect - * the current restart point; we update them only when we have reached a - * suitable place to restart if a suspension occurs. - */ - -/* Declare and initialize local copies of input pointer/count */ -#define INPUT_VARS(cinfo) \ - struct jpeg_source_mgr * datasrc = (cinfo)->src; \ - const JOCTET * next_input_byte = datasrc->next_input_byte; \ - size_t bytes_in_buffer = datasrc->bytes_in_buffer - -/* Unload the local copies --- do this only at a restart boundary */ -#define INPUT_SYNC(cinfo) \ - ( datasrc->next_input_byte = next_input_byte, \ - datasrc->bytes_in_buffer = bytes_in_buffer ) - -/* Reload the local copies --- seldom used except in MAKE_BYTE_AVAIL */ -#define INPUT_RELOAD(cinfo) \ - ( next_input_byte = datasrc->next_input_byte, \ - bytes_in_buffer = datasrc->bytes_in_buffer ) - -/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. - * Note we do *not* do INPUT_SYNC before calling fill_input_buffer, - * but we must reload the local copies after a successful fill. - */ -#define MAKE_BYTE_AVAIL(cinfo,action) \ - if (bytes_in_buffer == 0) { \ - if (! (*datasrc->fill_input_buffer) (cinfo)) \ - { action; } \ - INPUT_RELOAD(cinfo); \ - } \ - bytes_in_buffer-- - -/* Read a byte into variable V. - * If must suspend, take the specified action (typically "return FALSE"). - */ -#define INPUT_BYTE(cinfo,V,action) \ - MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ - V = GETJOCTET(*next_input_byte++); ) - -/* As above, but read two bytes interpreted as an unsigned 16-bit integer. - * V should be declared unsigned int or perhaps INT32. - */ -#define INPUT_2BYTES(cinfo,V,action) \ - MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ - V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ - MAKE_BYTE_AVAIL(cinfo,action); \ - V += GETJOCTET(*next_input_byte++); ) - - -/* - * Routines to process JPEG markers. - * - * Entry condition: JPEG marker itself has been read and its code saved - * in cinfo->unread_marker; input restart point is just after the marker. - * - * Exit: if return TRUE, have read and processed any parameters, and have - * updated the restart point to point after the parameters. - * If return FALSE, was forced to suspend before reaching end of - * marker parameters; restart point has not been moved. Same routine - * will be called again after application supplies more input data. - * - * This approach to suspension assumes that all of a marker's parameters can - * fit into a single input bufferload. This should hold for "normal" - * markers. Some COM/APPn markers might have large parameter segments, - * but we use skip_input_data to get past those, and thereby put the problem - * on the source manager's shoulders. - * - * Note that we don't bother to avoid duplicate trace messages if a - * suspension occurs within marker parameters. Other side effects - * require more care. - */ - - -LOCAL boolean -get_soi (j_decompress_ptr cinfo) -/* Process an SOI marker */ -{ - int i; - - TRACEMS(cinfo, 1, JTRC_SOI); - - if (cinfo->marker->saw_SOI) - ERREXIT(cinfo, JERR_SOI_DUPLICATE); - - /* Reset all parameters that are defined to be reset by SOI */ - - for (i = 0; i < NUM_ARITH_TBLS; i++) { - cinfo->arith_dc_L[i] = 0; - cinfo->arith_dc_U[i] = 1; - cinfo->arith_ac_K[i] = 5; - } - cinfo->restart_interval = 0; - - /* Set initial assumptions for colorspace etc */ - - cinfo->jpeg_color_space = JCS_UNKNOWN; - cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */ - - cinfo->saw_JFIF_marker = FALSE; - cinfo->density_unit = 0; /* set default JFIF APP0 values */ - cinfo->X_density = 1; - cinfo->Y_density = 1; - cinfo->saw_Adobe_marker = FALSE; - cinfo->Adobe_transform = 0; - - cinfo->marker->saw_SOI = TRUE; - - return TRUE; -} - - -LOCAL boolean -get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith) -/* Process a SOFn marker */ -{ - INT32 length; - int c, ci; - jpeg_component_info * compptr; - INPUT_VARS(cinfo); - - cinfo->progressive_mode = is_prog; - cinfo->arith_code = is_arith; - - INPUT_2BYTES(cinfo, length, return FALSE); - - INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE); - INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE); - INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE); - INPUT_BYTE(cinfo, cinfo->num_components, return FALSE); - - length -= 8; - - TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker, - (int) cinfo->image_width, (int) cinfo->image_height, - cinfo->num_components); - - if (cinfo->marker->saw_SOF) - ERREXIT(cinfo, JERR_SOF_DUPLICATE); - - /* We don't support files in which the image height is initially specified */ - /* as 0 and is later redefined by DNL. As long as we have to check that, */ - /* might as well have a general sanity check. */ - if (cinfo->image_height <= 0 || cinfo->image_width <= 0 - || cinfo->num_components <= 0) - ERREXIT(cinfo, JERR_EMPTY_IMAGE); - - if (length != (cinfo->num_components * 3)) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - if (cinfo->comp_info == NULL) /* do only once, even if suspend */ - cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components * SIZEOF(jpeg_component_info)); - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - compptr->component_index = ci; - INPUT_BYTE(cinfo, compptr->component_id, return FALSE); - INPUT_BYTE(cinfo, c, return FALSE); - compptr->h_samp_factor = (c >> 4) & 15; - compptr->v_samp_factor = (c ) & 15; - INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE); - - TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT, - compptr->component_id, compptr->h_samp_factor, - compptr->v_samp_factor, compptr->quant_tbl_no); - } - - cinfo->marker->saw_SOF = TRUE; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -LOCAL boolean -get_sos (j_decompress_ptr cinfo) -/* Process a SOS marker */ -{ - INT32 length; - int i, ci, n, c, cc; - jpeg_component_info * compptr; - INPUT_VARS(cinfo); - - if (! cinfo->marker->saw_SOF) - ERREXIT(cinfo, JERR_SOS_NO_SOF); - - INPUT_2BYTES(cinfo, length, return FALSE); - - INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */ - - if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - TRACEMS1(cinfo, 1, JTRC_SOS, n); - - cinfo->comps_in_scan = n; - - /* Collect the component-spec parameters */ - - for (i = 0; i < n; i++) { - INPUT_BYTE(cinfo, cc, return FALSE); - INPUT_BYTE(cinfo, c, return FALSE); - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - if (cc == compptr->component_id) - goto id_found; - } - - ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc); - - id_found: - - cinfo->cur_comp_info[i] = compptr; - compptr->dc_tbl_no = (c >> 4) & 15; - compptr->ac_tbl_no = (c ) & 15; - - TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc, - compptr->dc_tbl_no, compptr->ac_tbl_no); - } - - /* Collect the additional scan parameters Ss, Se, Ah/Al. */ - INPUT_BYTE(cinfo, c, return FALSE); - cinfo->Ss = c; - INPUT_BYTE(cinfo, c, return FALSE); - cinfo->Se = c; - INPUT_BYTE(cinfo, c, return FALSE); - cinfo->Ah = (c >> 4) & 15; - cinfo->Al = (c ) & 15; - - TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se, - cinfo->Ah, cinfo->Al); - - /* Prepare to scan data & restart markers */ - cinfo->marker->next_restart_num = 0; - - /* Count another SOS marker */ - cinfo->input_scan_number++; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -METHODDEF boolean -get_app0 (j_decompress_ptr cinfo) -/* Process an APP0 marker */ -{ -#define JFIF_LEN 14 - INT32 length; - UINT8 b[JFIF_LEN]; - int buffp; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - /* See if a JFIF APP0 marker is present */ - - if (length >= JFIF_LEN) { - for (buffp = 0; buffp < JFIF_LEN; buffp++) - INPUT_BYTE(cinfo, b[buffp], return FALSE); - length -= JFIF_LEN; - - if (b[0]==0x4A && b[1]==0x46 && b[2]==0x49 && b[3]==0x46 && b[4]==0) { - /* Found JFIF APP0 marker: check version */ - /* Major version must be 1, anything else signals an incompatible change. - * We used to treat this as an error, but now it's a nonfatal warning, - * because some bozo at Hijaak couldn't read the spec. - * Minor version should be 0..2, but process anyway if newer. - */ - if (b[5] != 1) - WARNMS2(cinfo, JWRN_JFIF_MAJOR, b[5], b[6]); - else if (b[6] > 2) - TRACEMS2(cinfo, 1, JTRC_JFIF_MINOR, b[5], b[6]); - /* Save info */ - cinfo->saw_JFIF_marker = TRUE; - cinfo->density_unit = b[7]; - cinfo->X_density = (b[8] << 8) + b[9]; - cinfo->Y_density = (b[10] << 8) + b[11]; - TRACEMS3(cinfo, 1, JTRC_JFIF, - cinfo->X_density, cinfo->Y_density, cinfo->density_unit); - if (b[12] | b[13]) - TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, b[12], b[13]); - if (length != ((INT32) b[12] * (INT32) b[13] * (INT32) 3)) - TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) length); - } else { - /* Start of APP0 does not match "JFIF" */ - TRACEMS1(cinfo, 1, JTRC_APP0, (int) length + JFIF_LEN); - } - } else { - /* Too short to be JFIF marker */ - TRACEMS1(cinfo, 1, JTRC_APP0, (int) length); - } - - INPUT_SYNC(cinfo); - if (length > 0) /* skip any remaining data -- could be lots */ - (*cinfo->src->skip_input_data) (cinfo, (long) length); - - return TRUE; -} - - -METHODDEF boolean -get_app14 (j_decompress_ptr cinfo) -/* Process an APP14 marker */ -{ -#define ADOBE_LEN 12 - INT32 length; - UINT8 b[ADOBE_LEN]; - int buffp; - unsigned int version, flags0, flags1, transform; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - /* See if an Adobe APP14 marker is present */ - - if (length >= ADOBE_LEN) { - for (buffp = 0; buffp < ADOBE_LEN; buffp++) - INPUT_BYTE(cinfo, b[buffp], return FALSE); - length -= ADOBE_LEN; - - if (b[0]==0x41 && b[1]==0x64 && b[2]==0x6F && b[3]==0x62 && b[4]==0x65) { - /* Found Adobe APP14 marker */ - version = (b[5] << 8) + b[6]; - flags0 = (b[7] << 8) + b[8]; - flags1 = (b[9] << 8) + b[10]; - transform = b[11]; - TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform); - cinfo->saw_Adobe_marker = TRUE; - cinfo->Adobe_transform = (UINT8) transform; - } else { - /* Start of APP14 does not match "Adobe" */ - TRACEMS1(cinfo, 1, JTRC_APP14, (int) length + ADOBE_LEN); - } - } else { - /* Too short to be Adobe marker */ - TRACEMS1(cinfo, 1, JTRC_APP14, (int) length); - } - - INPUT_SYNC(cinfo); - if (length > 0) /* skip any remaining data -- could be lots */ - (*cinfo->src->skip_input_data) (cinfo, (long) length); - - return TRUE; -} - - -LOCAL boolean -get_dac (j_decompress_ptr cinfo) -/* Process a DAC marker */ -{ - INT32 length; - int index, val; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - while (length > 0) { - INPUT_BYTE(cinfo, index, return FALSE); - INPUT_BYTE(cinfo, val, return FALSE); - - length -= 2; - - TRACEMS2(cinfo, 1, JTRC_DAC, index, val); - - if (index < 0 || index >= (2*NUM_ARITH_TBLS)) - ERREXIT1(cinfo, JERR_DAC_INDEX, index); - - if (index >= NUM_ARITH_TBLS) { /* define AC table */ - cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val; - } else { /* define DC table */ - cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F); - cinfo->arith_dc_U[index] = (UINT8) (val >> 4); - if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index]) - ERREXIT1(cinfo, JERR_DAC_VALUE, val); - } - } - - INPUT_SYNC(cinfo); - return TRUE; -} - - -LOCAL boolean -get_dht (j_decompress_ptr cinfo) -/* Process a DHT marker */ -{ - INT32 length; - UINT8 bits[17]; - UINT8 huffval[256]; - int i, index, count; - JHUFF_TBL **htblptr; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - while (length > 0) { - INPUT_BYTE(cinfo, index, return FALSE); - - TRACEMS1(cinfo, 1, JTRC_DHT, index); - - bits[0] = 0; - count = 0; - for (i = 1; i <= 16; i++) { - INPUT_BYTE(cinfo, bits[i], return FALSE); - count += bits[i]; - } - - length -= 1 + 16; - - TRACEMS8(cinfo, 2, JTRC_HUFFBITS, - bits[1], bits[2], bits[3], bits[4], - bits[5], bits[6], bits[7], bits[8]); - TRACEMS8(cinfo, 2, JTRC_HUFFBITS, - bits[9], bits[10], bits[11], bits[12], - bits[13], bits[14], bits[15], bits[16]); - - if (count > 256 || ((INT32) count) > length) - ERREXIT(cinfo, JERR_DHT_COUNTS); - - for (i = 0; i < count; i++) - INPUT_BYTE(cinfo, huffval[i], return FALSE); - - length -= count; - - if (index & 0x10) { /* AC table definition */ - index -= 0x10; - htblptr = &cinfo->ac_huff_tbl_ptrs[index]; - } else { /* DC table definition */ - htblptr = &cinfo->dc_huff_tbl_ptrs[index]; - } - - if (index < 0 || index >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_DHT_INDEX, index); - - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - - MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); - MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval)); - } - - INPUT_SYNC(cinfo); - return TRUE; -} - - -LOCAL boolean -get_dqt (j_decompress_ptr cinfo) -/* Process a DQT marker */ -{ - INT32 length; - int n, i, prec; - unsigned int tmp; - JQUANT_TBL *quant_ptr; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - while (length > 0) { - INPUT_BYTE(cinfo, n, return FALSE); - prec = n >> 4; - n &= 0x0F; - - TRACEMS2(cinfo, 1, JTRC_DQT, n, prec); - - if (n >= NUM_QUANT_TBLS) - ERREXIT1(cinfo, JERR_DQT_INDEX, n); - - if (cinfo->quant_tbl_ptrs[n] == NULL) - cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo); - quant_ptr = cinfo->quant_tbl_ptrs[n]; - - for (i = 0; i < DCTSIZE2; i++) { - if (prec) - INPUT_2BYTES(cinfo, tmp, return FALSE); - else - INPUT_BYTE(cinfo, tmp, return FALSE); - quant_ptr->quantval[i] = (UINT16) tmp; - } - - for (i = 0; i < DCTSIZE2; i += 8) { - TRACEMS8(cinfo, 2, JTRC_QUANTVALS, - quant_ptr->quantval[i ], quant_ptr->quantval[i+1], - quant_ptr->quantval[i+2], quant_ptr->quantval[i+3], - quant_ptr->quantval[i+4], quant_ptr->quantval[i+5], - quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]); - } - - length -= DCTSIZE2+1; - if (prec) length -= DCTSIZE2; - } - - INPUT_SYNC(cinfo); - return TRUE; -} - - -LOCAL boolean -get_dri (j_decompress_ptr cinfo) -/* Process a DRI marker */ -{ - INT32 length; - unsigned int tmp; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - - if (length != 4) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - INPUT_2BYTES(cinfo, tmp, return FALSE); - - TRACEMS1(cinfo, 1, JTRC_DRI, tmp); - - cinfo->restart_interval = tmp; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -METHODDEF boolean -skip_variable (j_decompress_ptr cinfo) -/* Skip over an unknown or uninteresting variable-length marker */ -{ - INT32 length; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - - TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length); - - INPUT_SYNC(cinfo); /* do before skip_input_data */ - (*cinfo->src->skip_input_data) (cinfo, (long) length - 2L); - - return TRUE; -} - - -/* - * Find the next JPEG marker, save it in cinfo->unread_marker. - * Returns FALSE if had to suspend before reaching a marker; - * in that case cinfo->unread_marker is unchanged. - * - * Note that the result might not be a valid marker code, - * but it will never be 0 or FF. - */ - -LOCAL boolean -next_marker (j_decompress_ptr cinfo) -{ - int c; - INPUT_VARS(cinfo); - - for (;;) { - INPUT_BYTE(cinfo, c, return FALSE); - /* Skip any non-FF bytes. - * This may look a bit inefficient, but it will not occur in a valid file. - * We sync after each discarded byte so that a suspending data source - * can discard the byte from its buffer. - */ - while (c != 0xFF) { - cinfo->marker->discarded_bytes++; - INPUT_SYNC(cinfo); - INPUT_BYTE(cinfo, c, return FALSE); - } - /* This loop swallows any duplicate FF bytes. Extra FFs are legal as - * pad bytes, so don't count them in discarded_bytes. We assume there - * will not be so many consecutive FF bytes as to overflow a suspending - * data source's input buffer. - */ - do { - INPUT_BYTE(cinfo, c, return FALSE); - } while (c == 0xFF); - if (c != 0) - break; /* found a valid marker, exit loop */ - /* Reach here if we found a stuffed-zero data sequence (FF/00). - * Discard it and loop back to try again. - */ - cinfo->marker->discarded_bytes += 2; - INPUT_SYNC(cinfo); - } - - if (cinfo->marker->discarded_bytes != 0) { - WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c); - cinfo->marker->discarded_bytes = 0; - } - - cinfo->unread_marker = c; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -LOCAL boolean -first_marker (j_decompress_ptr cinfo) -/* Like next_marker, but used to obtain the initial SOI marker. */ -/* For this marker, we do not allow preceding garbage or fill; otherwise, - * we might well scan an entire input file before realizing it ain't JPEG. - * If an application wants to process non-JFIF files, it must seek to the - * SOI before calling the JPEG library. - */ -{ - int c, c2; - INPUT_VARS(cinfo); - - INPUT_BYTE(cinfo, c, return FALSE); - INPUT_BYTE(cinfo, c2, return FALSE); - if (c != 0xFF || c2 != (int) M_SOI) - ERREXIT2(cinfo, JERR_NO_SOI, c, c2); - - cinfo->unread_marker = c2; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -/* - * Read markers until SOS or EOI. - * - * Returns same codes as are defined for jpeg_consume_input: - * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. - */ - -METHODDEF int -read_markers (j_decompress_ptr cinfo) -{ - /* Outer loop repeats once for each marker. */ - for (;;) { - /* Collect the marker proper, unless we already did. */ - /* NB: first_marker() enforces the requirement that SOI appear first. */ - if (cinfo->unread_marker == 0) { - if (! cinfo->marker->saw_SOI) { - if (! first_marker(cinfo)) - return JPEG_SUSPENDED; - } else { - if (! next_marker(cinfo)) - return JPEG_SUSPENDED; - } - } - /* At this point cinfo->unread_marker contains the marker code and the - * input point is just past the marker proper, but before any parameters. - * A suspension will cause us to return with this state still true. - */ - switch (cinfo->unread_marker) { - case M_SOI: - if (! get_soi(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_SOF0: /* Baseline */ - case M_SOF1: /* Extended sequential, Huffman */ - if (! get_sof(cinfo, FALSE, FALSE)) - return JPEG_SUSPENDED; - break; - - case M_SOF2: /* Progressive, Huffman */ - if (! get_sof(cinfo, TRUE, FALSE)) - return JPEG_SUSPENDED; - break; - - case M_SOF9: /* Extended sequential, arithmetic */ - if (! get_sof(cinfo, FALSE, TRUE)) - return JPEG_SUSPENDED; - break; - - case M_SOF10: /* Progressive, arithmetic */ - if (! get_sof(cinfo, TRUE, TRUE)) - return JPEG_SUSPENDED; - break; - - /* Currently unsupported SOFn types */ - case M_SOF3: /* Lossless, Huffman */ - case M_SOF5: /* Differential sequential, Huffman */ - case M_SOF6: /* Differential progressive, Huffman */ - case M_SOF7: /* Differential lossless, Huffman */ - case M_JPG: /* Reserved for JPEG extensions */ - case M_SOF11: /* Lossless, arithmetic */ - case M_SOF13: /* Differential sequential, arithmetic */ - case M_SOF14: /* Differential progressive, arithmetic */ - case M_SOF15: /* Differential lossless, arithmetic */ - ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker); - break; - - case M_SOS: - if (! get_sos(cinfo)) - return JPEG_SUSPENDED; - cinfo->unread_marker = 0; /* processed the marker */ - return JPEG_REACHED_SOS; - - case M_EOI: - TRACEMS(cinfo, 1, JTRC_EOI); - cinfo->unread_marker = 0; /* processed the marker */ - return JPEG_REACHED_EOI; - - case M_DAC: - if (! get_dac(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_DHT: - if (! get_dht(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_DQT: - if (! get_dqt(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_DRI: - if (! get_dri(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_APP0: - case M_APP1: - case M_APP2: - case M_APP3: - case M_APP4: - case M_APP5: - case M_APP6: - case M_APP7: - case M_APP8: - case M_APP9: - case M_APP10: - case M_APP11: - case M_APP12: - case M_APP13: - case M_APP14: - case M_APP15: - if (! (*cinfo->marker->process_APPn[cinfo->unread_marker - (int) M_APP0]) (cinfo)) - return JPEG_SUSPENDED; - break; - - case M_COM: - if (! (*cinfo->marker->process_COM) (cinfo)) - return JPEG_SUSPENDED; - break; - - case M_RST0: /* these are all parameterless */ - case M_RST1: - case M_RST2: - case M_RST3: - case M_RST4: - case M_RST5: - case M_RST6: - case M_RST7: - case M_TEM: - TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker); - break; - - case M_DNL: /* Ignore DNL ... perhaps the wrong thing */ - if (! skip_variable(cinfo)) - return JPEG_SUSPENDED; - break; - - default: /* must be DHP, EXP, JPGn, or RESn */ - /* For now, we treat the reserved markers as fatal errors since they are - * likely to be used to signal incompatible JPEG Part 3 extensions. - * Once the JPEG 3 version-number marker is well defined, this code - * ought to change! - */ - ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); - break; - } - /* Successfully processed marker, so reset state variable */ - cinfo->unread_marker = 0; - } /* end loop */ -} - - -/* - * Read a restart marker, which is expected to appear next in the datastream; - * if the marker is not there, take appropriate recovery action. - * Returns FALSE if suspension is required. - * - * This is called by the entropy decoder after it has read an appropriate - * number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder - * has already read a marker from the data source. Under normal conditions - * cinfo->unread_marker will be reset to 0 before returning; if not reset, - * it holds a marker which the decoder will be unable to read past. - */ - -METHODDEF boolean -read_restart_marker (j_decompress_ptr cinfo) -{ - /* Obtain a marker unless we already did. */ - /* Note that next_marker will complain if it skips any data. */ - if (cinfo->unread_marker == 0) { - if (! next_marker(cinfo)) - return FALSE; - } - - if (cinfo->unread_marker == - ((int) M_RST0 + cinfo->marker->next_restart_num)) { - /* Normal case --- swallow the marker and let entropy decoder continue */ - TRACEMS1(cinfo, 2, JTRC_RST, cinfo->marker->next_restart_num); - cinfo->unread_marker = 0; - } else { - /* Uh-oh, the restart markers have been messed up. */ - /* Let the data source manager determine how to resync. */ - if (! (*cinfo->src->resync_to_restart) (cinfo, - cinfo->marker->next_restart_num)) - return FALSE; - } - - /* Update next-restart state */ - cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7; - - return TRUE; -} - - -/* - * This is the default resync_to_restart method for data source managers - * to use if they don't have any better approach. Some data source managers - * may be able to back up, or may have additional knowledge about the data - * which permits a more intelligent recovery strategy; such managers would - * presumably supply their own resync method. - * - * read_restart_marker calls resync_to_restart if it finds a marker other than - * the restart marker it was expecting. (This code is *not* used unless - * a nonzero restart interval has been declared.) cinfo->unread_marker is - * the marker code actually found (might be anything, except 0 or FF). - * The desired restart marker number (0..7) is passed as a parameter. - * This routine is supposed to apply whatever error recovery strategy seems - * appropriate in order to position the input stream to the next data segment. - * Note that cinfo->unread_marker is treated as a marker appearing before - * the current data-source input point; usually it should be reset to zero - * before returning. - * Returns FALSE if suspension is required. - * - * This implementation is substantially constrained by wanting to treat the - * input as a data stream; this means we can't back up. Therefore, we have - * only the following actions to work with: - * 1. Simply discard the marker and let the entropy decoder resume at next - * byte of file. - * 2. Read forward until we find another marker, discarding intervening - * data. (In theory we could look ahead within the current bufferload, - * without having to discard data if we don't find the desired marker. - * This idea is not implemented here, in part because it makes behavior - * dependent on buffer size and chance buffer-boundary positions.) - * 3. Leave the marker unread (by failing to zero cinfo->unread_marker). - * This will cause the entropy decoder to process an empty data segment, - * inserting dummy zeroes, and then we will reprocess the marker. - * - * #2 is appropriate if we think the desired marker lies ahead, while #3 is - * appropriate if the found marker is a future restart marker (indicating - * that we have missed the desired restart marker, probably because it got - * corrupted). - * We apply #2 or #3 if the found marker is a restart marker no more than - * two counts behind or ahead of the expected one. We also apply #2 if the - * found marker is not a legal JPEG marker code (it's certainly bogus data). - * If the found marker is a restart marker more than 2 counts away, we do #1 - * (too much risk that the marker is erroneous; with luck we will be able to - * resync at some future point). - * For any valid non-restart JPEG marker, we apply #3. This keeps us from - * overrunning the end of a scan. An implementation limited to single-scan - * files might find it better to apply #2 for markers other than EOI, since - * any other marker would have to be bogus data in that case. - */ - -GLOBAL boolean -jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired) -{ - int marker = cinfo->unread_marker; - int action = 1; - - /* Always put up a warning. */ - WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired); - - /* Outer loop handles repeated decision after scanning forward. */ - for (;;) { - if (marker < (int) M_SOF0) - action = 2; /* invalid marker */ - else if (marker < (int) M_RST0 || marker > (int) M_RST7) - action = 3; /* valid non-restart marker */ - else { - if (marker == ((int) M_RST0 + ((desired+1) & 7)) || - marker == ((int) M_RST0 + ((desired+2) & 7))) - action = 3; /* one of the next two expected restarts */ - else if (marker == ((int) M_RST0 + ((desired-1) & 7)) || - marker == ((int) M_RST0 + ((desired-2) & 7))) - action = 2; /* a prior restart, so advance */ - else - action = 1; /* desired restart or too far away */ - } - TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action); - switch (action) { - case 1: - /* Discard marker and let entropy decoder resume processing. */ - cinfo->unread_marker = 0; - return TRUE; - case 2: - /* Scan to the next marker, and repeat the decision loop. */ - if (! next_marker(cinfo)) - return FALSE; - marker = cinfo->unread_marker; - break; - case 3: - /* Return without advancing past this marker. */ - /* Entropy decoder will be forced to process an empty segment. */ - return TRUE; - } - } /* end loop */ -} - - -/* - * Reset marker processing state to begin a fresh datastream. - */ - -METHODDEF void -reset_marker_reader (j_decompress_ptr cinfo) -{ - cinfo->comp_info = NULL; /* until allocated by get_sof */ - cinfo->input_scan_number = 0; /* no SOS seen yet */ - cinfo->unread_marker = 0; /* no pending marker */ - cinfo->marker->saw_SOI = FALSE; /* set internal state too */ - cinfo->marker->saw_SOF = FALSE; - cinfo->marker->discarded_bytes = 0; -} - - -/* - * Initialize the marker reader module. - * This is called only once, when the decompression object is created. - */ - -GLOBAL void -jinit_marker_reader (j_decompress_ptr cinfo) -{ - int i; - - /* Create subobject in permanent pool */ - cinfo->marker = (struct jpeg_marker_reader *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(struct jpeg_marker_reader)); - /* Initialize method pointers */ - cinfo->marker->reset_marker_reader = reset_marker_reader; - cinfo->marker->read_markers = read_markers; - cinfo->marker->read_restart_marker = read_restart_marker; - cinfo->marker->process_COM = skip_variable; - for (i = 0; i < 16; i++) - cinfo->marker->process_APPn[i] = skip_variable; - cinfo->marker->process_APPn[0] = get_app0; - cinfo->marker->process_APPn[14] = get_app14; - /* Reset marker processing state */ - reset_marker_reader(cinfo); -} diff --git a/libs/jpeg6/jdmaster.cpp b/libs/jpeg6/jdmaster.cpp deleted file mode 100644 index 18e0880..0000000 --- a/libs/jpeg6/jdmaster.cpp +++ /dev/null @@ -1,557 +0,0 @@ -/* - * jdmaster.c - * - * Copyright (C) 1991-1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains master control logic for the JPEG decompressor. - * These routines are concerned with selecting the modules to be executed - * and with determining the number of passes and the work to be done in each - * pass. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Private state */ - -typedef struct { - struct jpeg_decomp_master pub; /* public fields */ - - int pass_number; /* # of passes completed */ - - boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */ - - /* Saved references to initialized quantizer modules, - * in case we need to switch modes. - */ - struct jpeg_color_quantizer * quantizer_1pass; - struct jpeg_color_quantizer * quantizer_2pass; -} my_decomp_master; - -typedef my_decomp_master * my_master_ptr; - - -/* - * Determine whether merged upsample/color conversion should be used. - * CRUCIAL: this must match the actual capabilities of jdmerge.c! - */ - -LOCAL boolean -use_merged_upsample (j_decompress_ptr cinfo) -{ -#ifdef UPSAMPLE_MERGING_SUPPORTED - /* Merging is the equivalent of plain box-filter upsampling */ - if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling) - return FALSE; - /* jdmerge.c only supports YCC=>RGB color conversion */ - if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 || - cinfo->out_color_space != JCS_RGB || - cinfo->out_color_components != RGB_PIXELSIZE) - return FALSE; - /* and it only handles 2h1v or 2h2v sampling ratios */ - if (cinfo->comp_info[0].h_samp_factor != 2 || - cinfo->comp_info[1].h_samp_factor != 1 || - cinfo->comp_info[2].h_samp_factor != 1 || - cinfo->comp_info[0].v_samp_factor > 2 || - cinfo->comp_info[1].v_samp_factor != 1 || - cinfo->comp_info[2].v_samp_factor != 1) - return FALSE; - /* furthermore, it doesn't work if we've scaled the IDCTs differently */ - if (cinfo->comp_info[0].DCT_scaled_size != cinfo->min_DCT_scaled_size || - cinfo->comp_info[1].DCT_scaled_size != cinfo->min_DCT_scaled_size || - cinfo->comp_info[2].DCT_scaled_size != cinfo->min_DCT_scaled_size) - return FALSE; - /* ??? also need to test for upsample-time rescaling, when & if supported */ - return TRUE; /* by golly, it'll work... */ -#else - return FALSE; -#endif -} - - -/* - * Compute output image dimensions and related values. - * NOTE: this is exported for possible use by application. - * Hence it mustn't do anything that can't be done twice. - * Also note that it may be called before the master module is initialized! - */ - -GLOBAL void -jpeg_calc_output_dimensions (j_decompress_ptr cinfo) -/* Do computations that are needed before master selection phase */ -{ -#if 0 // JDC: commented out to remove warning - int ci; - jpeg_component_info *compptr; -#endif - - /* Prevent application from calling me at wrong times */ - if (cinfo->global_state != DSTATE_READY) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - -#ifdef IDCT_SCALING_SUPPORTED - - /* Compute actual output image dimensions and DCT scaling choices. */ - if (cinfo->scale_num * 8 <= cinfo->scale_denom) { - /* Provide 1/8 scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, 8L); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, 8L); - cinfo->min_DCT_scaled_size = 1; - } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) { - /* Provide 1/4 scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, 4L); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, 4L); - cinfo->min_DCT_scaled_size = 2; - } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) { - /* Provide 1/2 scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, 2L); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, 2L); - cinfo->min_DCT_scaled_size = 4; - } else { - /* Provide 1/1 scaling */ - cinfo->output_width = cinfo->image_width; - cinfo->output_height = cinfo->image_height; - cinfo->min_DCT_scaled_size = DCTSIZE; - } - /* In selecting the actual DCT scaling for each component, we try to - * scale up the chroma components via IDCT scaling rather than upsampling. - * This saves time if the upsampler gets to use 1:1 scaling. - * Note this code assumes that the supported DCT scalings are powers of 2. - */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - int ssize = cinfo->min_DCT_scaled_size; - while (ssize < DCTSIZE && - (compptr->h_samp_factor * ssize * 2 <= - cinfo->max_h_samp_factor * cinfo->min_DCT_scaled_size) && - (compptr->v_samp_factor * ssize * 2 <= - cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size)) { - ssize = ssize * 2; - } - compptr->DCT_scaled_size = ssize; - } - - /* Recompute downsampled dimensions of components; - * application needs to know these if using raw downsampled data. - */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Size in samples, after IDCT scaling */ - compptr->downsampled_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * - (long) (compptr->h_samp_factor * compptr->DCT_scaled_size), - (long) (cinfo->max_h_samp_factor * DCTSIZE)); - compptr->downsampled_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * - (long) (compptr->v_samp_factor * compptr->DCT_scaled_size), - (long) (cinfo->max_v_samp_factor * DCTSIZE)); - } - -#else /* !IDCT_SCALING_SUPPORTED */ - - /* Hardwire it to "no scaling" */ - cinfo->output_width = cinfo->image_width; - cinfo->output_height = cinfo->image_height; - /* jdinput.c has already initialized DCT_scaled_size to DCTSIZE, - * and has computed unscaled downsampled_width and downsampled_height. - */ - -#endif /* IDCT_SCALING_SUPPORTED */ - - /* Report number of components in selected colorspace. */ - /* Probably this should be in the color conversion module... */ - switch (cinfo->out_color_space) { - case JCS_GRAYSCALE: - cinfo->out_color_components = 1; - break; - case JCS_RGB: -#if RGB_PIXELSIZE != 3 - cinfo->out_color_components = RGB_PIXELSIZE; - break; -#endif /* else share code with YCbCr */ - case JCS_YCbCr: - cinfo->out_color_components = 3; - break; - case JCS_CMYK: - case JCS_YCCK: - cinfo->out_color_components = 4; - break; - default: /* else must be same colorspace as in file */ - cinfo->out_color_components = cinfo->num_components; - break; - } - cinfo->output_components = (cinfo->quantize_colors ? 1 : - cinfo->out_color_components); - - /* See if upsampler will want to emit more than one row at a time */ - if (use_merged_upsample(cinfo)) - cinfo->rec_outbuf_height = cinfo->max_v_samp_factor; - else - cinfo->rec_outbuf_height = 1; -} - - -/* - * Several decompression processes need to range-limit values to the range - * 0..MAXJSAMPLE; the input value may fall somewhat outside this range - * due to noise introduced by quantization, roundoff error, etc. These - * processes are inner loops and need to be as fast as possible. On most - * machines, particularly CPUs with pipelines or instruction prefetch, - * a (subscript-check-less) C table lookup - * x = sample_range_limit[x]; - * is faster than explicit tests - * if (x < 0) x = 0; - * else if (x > MAXJSAMPLE) x = MAXJSAMPLE; - * These processes all use a common table prepared by the routine below. - * - * For most steps we can mathematically guarantee that the initial value - * of x is within MAXJSAMPLE+1 of the legal range, so a table running from - * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial - * limiting step (just after the IDCT), a wildly out-of-range value is - * possible if the input data is corrupt. To avoid any chance of indexing - * off the end of memory and getting a bad-pointer trap, we perform the - * post-IDCT limiting thus: - * x = range_limit[x & MASK]; - * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit - * samples. Under normal circumstances this is more than enough range and - * a correct output will be generated; with bogus input data the mask will - * cause wraparound, and we will safely generate a bogus-but-in-range output. - * For the post-IDCT step, we want to convert the data from signed to unsigned - * representation by adding CENTERJSAMPLE at the same time that we limit it. - * So the post-IDCT limiting table ends up looking like this: - * CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE, - * MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), - * 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), - * 0,1,...,CENTERJSAMPLE-1 - * Negative inputs select values from the upper half of the table after - * masking. - * - * We can save some space by overlapping the start of the post-IDCT table - * with the simpler range limiting table. The post-IDCT table begins at - * sample_range_limit + CENTERJSAMPLE. - * - * Note that the table is allocated in near data space on PCs; it's small - * enough and used often enough to justify this. - */ - -LOCAL void -prepare_range_limit_table (j_decompress_ptr cinfo) -/* Allocate and fill in the sample_range_limit table */ -{ - JSAMPLE * table; - int i; - - table = (JSAMPLE *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE)); - table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */ - cinfo->sample_range_limit = table; - /* First segment of "simple" table: limit[x] = 0 for x < 0 */ - MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); - /* Main part of "simple" table: limit[x] = x */ - for (i = 0; i <= MAXJSAMPLE; i++) - table[i] = (JSAMPLE) i; - table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ - /* End of simple table, rest of first half of post-IDCT table */ - for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++) - table[i] = MAXJSAMPLE; - /* Second half of post-IDCT table */ - MEMZERO(table + (2 * (MAXJSAMPLE+1)), - (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE)); - MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE), - cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE)); -} - - -/* - * Master selection of decompression modules. - * This is done once at jpeg_start_decompress time. We determine - * which modules will be used and give them appropriate initialization calls. - * We also initialize the decompressor input side to begin consuming data. - * - * Since jpeg_read_header has finished, we know what is in the SOF - * and (first) SOS markers. We also have all the application parameter - * settings. - */ - -LOCAL void -master_selection (j_decompress_ptr cinfo) -{ - my_master_ptr master = (my_master_ptr) cinfo->master; - boolean use_c_buffer; - long samplesperrow; - JDIMENSION jd_samplesperrow; - - /* Initialize dimensions and other stuff */ - jpeg_calc_output_dimensions(cinfo); - prepare_range_limit_table(cinfo); - - /* Width of an output scanline must be representable as JDIMENSION. */ - samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components; - jd_samplesperrow = (JDIMENSION) samplesperrow; - if ((long) jd_samplesperrow != samplesperrow) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - - /* Initialize my private state */ - master->pass_number = 0; - master->using_merged_upsample = use_merged_upsample(cinfo); - - /* Color quantizer selection */ - master->quantizer_1pass = NULL; - master->quantizer_2pass = NULL; - /* No mode changes if not using buffered-image mode. */ - if (! cinfo->quantize_colors || ! cinfo->buffered_image) { - cinfo->enable_1pass_quant = FALSE; - cinfo->enable_external_quant = FALSE; - cinfo->enable_2pass_quant = FALSE; - } - if (cinfo->quantize_colors) { - if (cinfo->raw_data_out) - ERREXIT(cinfo, JERR_NOTIMPL); - /* 2-pass quantizer only works in 3-component color space. */ - if (cinfo->out_color_components != 3) { - cinfo->enable_1pass_quant = TRUE; - cinfo->enable_external_quant = FALSE; - cinfo->enable_2pass_quant = FALSE; - cinfo->colormap = NULL; - } else if (cinfo->colormap != NULL) { - cinfo->enable_external_quant = TRUE; - } else if (cinfo->two_pass_quantize) { - cinfo->enable_2pass_quant = TRUE; - } else { - cinfo->enable_1pass_quant = TRUE; - } - - if (cinfo->enable_1pass_quant) { -#ifdef QUANT_1PASS_SUPPORTED - jinit_1pass_quantizer(cinfo); - master->quantizer_1pass = cinfo->cquantize; -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } - - /* We use the 2-pass code to map to external colormaps. */ - if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { -#ifdef QUANT_2PASS_SUPPORTED - jinit_2pass_quantizer(cinfo); - master->quantizer_2pass = cinfo->cquantize; -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } - /* If both quantizers are initialized, the 2-pass one is left active; - * this is necessary for starting with quantization to an external map. - */ - } - - /* Post-processing: in particular, color conversion first */ - if (! cinfo->raw_data_out) { - if (master->using_merged_upsample) { -#ifdef UPSAMPLE_MERGING_SUPPORTED - jinit_merged_upsampler(cinfo); /* does color conversion too */ -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else { - jinit_color_deconverter(cinfo); - jinit_upsampler(cinfo); - } - jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); - } - /* Inverse DCT */ - jinit_inverse_dct(cinfo); - /* Entropy decoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); - } else { - if (cinfo->progressive_mode) { -#ifdef D_PROGRESSIVE_SUPPORTED - jinit_phuff_decoder(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else - jinit_huff_decoder(cinfo); - } - - /* Initialize principal buffer controllers. */ - use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; - jinit_d_coef_controller(cinfo, use_c_buffer); - - if (! cinfo->raw_data_out) - jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); - - /* We can now tell the memory manager to allocate virtual arrays. */ - (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); - - /* Initialize input side of decompressor to consume first scan. */ - (*cinfo->inputctl->start_input_pass) (cinfo); - -#ifdef D_MULTISCAN_FILES_SUPPORTED - /* If jpeg_start_decompress will read the whole file, initialize - * progress monitoring appropriately. The input step is counted - * as one pass. - */ - if (cinfo->progress != NULL && ! cinfo->buffered_image && - cinfo->inputctl->has_multiple_scans) { - int nscans; - /* Estimate number of scans to set pass_limit. */ - if (cinfo->progressive_mode) { - /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ - nscans = 2 + 3 * cinfo->num_components; - } else { - /* For a nonprogressive multiscan file, estimate 1 scan per component. */ - nscans = cinfo->num_components; - } - cinfo->progress->pass_counter = 0L; - cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; - cinfo->progress->completed_passes = 0; - cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2); - /* Count the input pass as done */ - master->pass_number++; - } -#endif /* D_MULTISCAN_FILES_SUPPORTED */ -} - - -/* - * Per-pass setup. - * This is called at the beginning of each output pass. We determine which - * modules will be active during this pass and give them appropriate - * start_pass calls. We also set is_dummy_pass to indicate whether this - * is a "real" output pass or a dummy pass for color quantization. - * (In the latter case, jdapi.c will crank the pass to completion.) - */ - -METHODDEF void -prepare_for_output_pass (j_decompress_ptr cinfo) -{ - my_master_ptr master = (my_master_ptr) cinfo->master; - - if (master->pub.is_dummy_pass) { -#ifdef QUANT_2PASS_SUPPORTED - /* Final pass of 2-pass quantization */ - master->pub.is_dummy_pass = FALSE; - (*cinfo->cquantize->start_pass) (cinfo, FALSE); - (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST); - (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif /* QUANT_2PASS_SUPPORTED */ - } else { - if (cinfo->quantize_colors && cinfo->colormap == NULL) { - /* Select new quantization method */ - if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) { - cinfo->cquantize = master->quantizer_2pass; - master->pub.is_dummy_pass = TRUE; - } else if (cinfo->enable_1pass_quant) { - cinfo->cquantize = master->quantizer_1pass; - } else { - ERREXIT(cinfo, JERR_MODE_CHANGE); - } - } - (*cinfo->idct->start_pass) (cinfo); - (*cinfo->coef->start_output_pass) (cinfo); - if (! cinfo->raw_data_out) { - if (! master->using_merged_upsample) - (*cinfo->cconvert->start_pass) (cinfo); - (*cinfo->upsample->start_pass) (cinfo); - if (cinfo->quantize_colors) - (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass); - (*cinfo->post->start_pass) (cinfo, - (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); - (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); - } - } - - /* Set up progress monitor's pass info if present */ - if (cinfo->progress != NULL) { - cinfo->progress->completed_passes = master->pass_number; - cinfo->progress->total_passes = master->pass_number + - (master->pub.is_dummy_pass ? 2 : 1); - /* In buffered-image mode, we assume one more output pass if EOI not - * yet reached, but no more passes if EOI has been reached. - */ - if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) { - cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1); - } - } -} - - -/* - * Finish up at end of an output pass. - */ - -METHODDEF void -finish_output_pass (j_decompress_ptr cinfo) -{ - my_master_ptr master = (my_master_ptr) cinfo->master; - - if (cinfo->quantize_colors) - (*cinfo->cquantize->finish_pass) (cinfo); - master->pass_number++; -} - - -#ifdef D_MULTISCAN_FILES_SUPPORTED - -/* - * Switch to a new external colormap between output passes. - */ - -GLOBAL void -jpeg_new_colormap (j_decompress_ptr cinfo) -{ - my_master_ptr master = (my_master_ptr) cinfo->master; - - /* Prevent application from calling me at wrong times */ - if (cinfo->global_state != DSTATE_BUFIMAGE) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - if (cinfo->quantize_colors && cinfo->enable_external_quant && - cinfo->colormap != NULL) { - /* Select 2-pass quantizer for external colormap use */ - cinfo->cquantize = master->quantizer_2pass; - /* Notify quantizer of colormap change */ - (*cinfo->cquantize->new_color_map) (cinfo); - master->pub.is_dummy_pass = FALSE; /* just in case */ - } else - ERREXIT(cinfo, JERR_MODE_CHANGE); -} - -#endif /* D_MULTISCAN_FILES_SUPPORTED */ - - -/* - * Initialize master decompression control and select active modules. - * This is performed at the start of jpeg_start_decompress. - */ - -GLOBAL void -jinit_master_decompress (j_decompress_ptr cinfo) -{ - my_master_ptr master; - - master = (my_master_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_decomp_master)); - cinfo->master = (struct jpeg_decomp_master *) master; - master->pub.prepare_for_output_pass = prepare_for_output_pass; - master->pub.finish_output_pass = finish_output_pass; - - master->pub.is_dummy_pass = FALSE; - - master_selection(cinfo); -} diff --git a/libs/jpeg6/jdpostct.cpp b/libs/jpeg6/jdpostct.cpp deleted file mode 100644 index f612002..0000000 --- a/libs/jpeg6/jdpostct.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/* - * jdpostct.c - * - * Copyright (C) 1994-1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the decompression postprocessing controller. - * This controller manages the upsampling, color conversion, and color - * quantization/reduction steps; specifically, it controls the buffering - * between upsample/color conversion and color quantization/reduction. - * - * If no color quantization/reduction is required, then this module has no - * work to do, and it just hands off to the upsample/color conversion code. - * An integrated upsample/convert/quantize process would replace this module - * entirely. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Private buffer controller object */ - -typedef struct { - struct jpeg_d_post_controller pub; /* public fields */ - - /* Color quantization source buffer: this holds output data from - * the upsample/color conversion step to be passed to the quantizer. - * For two-pass color quantization, we need a full-image buffer; - * for one-pass operation, a strip buffer is sufficient. - */ - jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */ - JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */ - JDIMENSION strip_height; /* buffer size in rows */ - /* for two-pass mode only: */ - JDIMENSION starting_row; /* row # of first row in current strip */ - JDIMENSION next_row; /* index of next row to fill/empty in strip */ -} my_post_controller; - -typedef my_post_controller * my_post_ptr; - - -/* Forward declarations */ -METHODDEF void post_process_1pass - JPP((j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -#ifdef QUANT_2PASS_SUPPORTED -METHODDEF void post_process_prepass - JPP((j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -METHODDEF void post_process_2pass - JPP((j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -#endif - - -/* - * Initialize for a processing pass. - */ - -METHODDEF void -start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) -{ - my_post_ptr post = (my_post_ptr) cinfo->post; - - switch (pass_mode) { - case JBUF_PASS_THRU: - if (cinfo->quantize_colors) { - /* Single-pass processing with color quantization. */ - post->pub.post_process_data = post_process_1pass; - /* We could be doing buffered-image output before starting a 2-pass - * color quantization; in that case, jinit_d_post_controller did not - * allocate a strip buffer. Use the virtual-array buffer as workspace. - */ - if (post->buffer == NULL) { - post->buffer = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, post->whole_image, - (JDIMENSION) 0, post->strip_height, TRUE); - } - } else { - /* For single-pass processing without color quantization, - * I have no work to do; just call the upsampler directly. - */ - post->pub.post_process_data = cinfo->upsample->upsample; - } - break; -#ifdef QUANT_2PASS_SUPPORTED - case JBUF_SAVE_AND_PASS: - /* First pass of 2-pass quantization */ - if (post->whole_image == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - post->pub.post_process_data = post_process_prepass; - break; - case JBUF_CRANK_DEST: - /* Second pass of 2-pass quantization */ - if (post->whole_image == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - post->pub.post_process_data = post_process_2pass; - break; -#endif /* QUANT_2PASS_SUPPORTED */ - default: - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - break; - } - post->starting_row = post->next_row = 0; -} - - -/* - * Process some data in the one-pass (strip buffer) case. - * This is used for color precision reduction as well as one-pass quantization. - */ - -METHODDEF void -post_process_1pass (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_post_ptr post = (my_post_ptr) cinfo->post; - JDIMENSION num_rows, max_rows; - - /* Fill the buffer, but not more than what we can dump out in one go. */ - /* Note we rely on the upsampler to detect bottom of image. */ - max_rows = out_rows_avail - *out_row_ctr; - if (max_rows > post->strip_height) - max_rows = post->strip_height; - num_rows = 0; - (*cinfo->upsample->upsample) (cinfo, - input_buf, in_row_group_ctr, in_row_groups_avail, - post->buffer, &num_rows, max_rows); - /* Quantize and emit data. */ - (*cinfo->cquantize->color_quantize) (cinfo, - post->buffer, output_buf + *out_row_ctr, (int) num_rows); - *out_row_ctr += num_rows; -} - - -#ifdef QUANT_2PASS_SUPPORTED - -/* - * Process some data in the first pass of 2-pass quantization. - */ - -METHODDEF void -post_process_prepass (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_post_ptr post = (my_post_ptr) cinfo->post; - JDIMENSION old_next_row, num_rows; - - /* Reposition virtual buffer if at start of strip. */ - if (post->next_row == 0) { - post->buffer = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, post->whole_image, - post->starting_row, post->strip_height, TRUE); - } - - /* Upsample some data (up to a strip height's worth). */ - old_next_row = post->next_row; - (*cinfo->upsample->upsample) (cinfo, - input_buf, in_row_group_ctr, in_row_groups_avail, - post->buffer, &post->next_row, post->strip_height); - - /* Allow quantizer to scan new data. No data is emitted, */ - /* but we advance out_row_ctr so outer loop can tell when we're done. */ - if (post->next_row > old_next_row) { - num_rows = post->next_row - old_next_row; - (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row, - (JSAMPARRAY) NULL, (int) num_rows); - *out_row_ctr += num_rows; - } - - /* Advance if we filled the strip. */ - if (post->next_row >= post->strip_height) { - post->starting_row += post->strip_height; - post->next_row = 0; - } -} - - -/* - * Process some data in the second pass of 2-pass quantization. - */ - -METHODDEF void -post_process_2pass (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_post_ptr post = (my_post_ptr) cinfo->post; - JDIMENSION num_rows, max_rows; - - /* Reposition virtual buffer if at start of strip. */ - if (post->next_row == 0) { - post->buffer = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, post->whole_image, - post->starting_row, post->strip_height, FALSE); - } - - /* Determine number of rows to emit. */ - num_rows = post->strip_height - post->next_row; /* available in strip */ - max_rows = out_rows_avail - *out_row_ctr; /* available in output area */ - if (num_rows > max_rows) - num_rows = max_rows; - /* We have to check bottom of image here, can't depend on upsampler. */ - max_rows = cinfo->output_height - post->starting_row; - if (num_rows > max_rows) - num_rows = max_rows; - - /* Quantize and emit data. */ - (*cinfo->cquantize->color_quantize) (cinfo, - post->buffer + post->next_row, output_buf + *out_row_ctr, - (int) num_rows); - *out_row_ctr += num_rows; - - /* Advance if we filled the strip. */ - post->next_row += num_rows; - if (post->next_row >= post->strip_height) { - post->starting_row += post->strip_height; - post->next_row = 0; - } -} - -#endif /* QUANT_2PASS_SUPPORTED */ - - -/* - * Initialize postprocessing controller. - */ - -GLOBAL void -jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer) -{ - my_post_ptr post; - - post = (my_post_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_post_controller)); - cinfo->post = (struct jpeg_d_post_controller *) post; - post->pub.start_pass = start_pass_dpost; - post->whole_image = NULL; /* flag for no virtual arrays */ - post->buffer = NULL; /* flag for no strip buffer */ - - /* Create the quantization buffer, if needed */ - if (cinfo->quantize_colors) { - /* The buffer strip height is max_v_samp_factor, which is typically - * an efficient number of rows for upsampling to return. - * (In the presence of output rescaling, we might want to be smarter?) - */ - post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor; - if (need_full_buffer) { - /* Two-pass color quantization: need full-image storage. */ - /* We round up the number of rows to a multiple of the strip height. */ -#ifdef QUANT_2PASS_SUPPORTED - post->whole_image = (*cinfo->mem->request_virt_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, - cinfo->output_width * cinfo->out_color_components, - (JDIMENSION) jround_up((long) cinfo->output_height, - (long) post->strip_height), - post->strip_height); -#else - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); -#endif /* QUANT_2PASS_SUPPORTED */ - } else { - /* One-pass color quantization: just make a strip buffer. */ - post->buffer = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->output_width * cinfo->out_color_components, - post->strip_height); - } - } -} diff --git a/libs/jpeg6/jdsample.cpp b/libs/jpeg6/jdsample.cpp deleted file mode 100644 index 661e198..0000000 --- a/libs/jpeg6/jdsample.cpp +++ /dev/null @@ -1,478 +0,0 @@ -/* - * jdsample.c - * - * Copyright (C) 1991-1994, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains upsampling routines. - * - * Upsampling input data is counted in "row groups". A row group - * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) - * sample rows of each component. Upsampling will normally produce - * max_v_samp_factor pixel rows from each row group (but this could vary - * if the upsampler is applying a scale factor of its own). - * - * An excellent reference for image resampling is - * Digital Image Warping, George Wolberg, 1990. - * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Pointer to routine to upsample a single component */ -typedef JMETHOD(void, upsample1_ptr, - (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)); - -/* Private subobject */ - -typedef struct { - struct jpeg_upsampler pub; /* public fields */ - - /* Color conversion buffer. When using separate upsampling and color - * conversion steps, this buffer holds one upsampled row group until it - * has been color converted and output. - * Note: we do not allocate any storage for component(s) which are full-size, - * ie do not need rescaling. The corresponding entry of color_buf[] is - * simply set to point to the input data array, thereby avoiding copying. - */ - JSAMPARRAY color_buf[MAX_COMPONENTS]; - - /* Per-component upsampling method pointers */ - upsample1_ptr methods[MAX_COMPONENTS]; - - int next_row_out; /* counts rows emitted from color_buf */ - JDIMENSION rows_to_go; /* counts rows remaining in image */ - - /* Height of an input row group for each component. */ - int rowgroup_height[MAX_COMPONENTS]; - - /* These arrays save pixel expansion factors so that int_expand need not - * recompute them each time. They are unused for other upsampling methods. - */ - UINT8 h_expand[MAX_COMPONENTS]; - UINT8 v_expand[MAX_COMPONENTS]; -} my_upsampler; - -typedef my_upsampler * my_upsample_ptr; - - -/* - * Initialize for an upsampling pass. - */ - -METHODDEF void -start_pass_upsample (j_decompress_ptr cinfo) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - - /* Mark the conversion buffer empty */ - upsample->next_row_out = cinfo->max_v_samp_factor; - /* Initialize total-height counter for detecting bottom of image */ - upsample->rows_to_go = cinfo->output_height; -} - - -/* - * Control routine to do upsampling (and color conversion). - * - * In this version we upsample each component independently. - * We upsample one row group into the conversion buffer, then apply - * color conversion a row at a time. - */ - -METHODDEF void -sep_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - int ci; - jpeg_component_info * compptr; - JDIMENSION num_rows; - - /* Fill the conversion buffer, if it's empty */ - if (upsample->next_row_out >= cinfo->max_v_samp_factor) { - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Invoke per-component upsample method. Notice we pass a POINTER - * to color_buf[ci], so that fullsize_upsample can change it. - */ - (*upsample->methods[ci]) (cinfo, compptr, - input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]), - upsample->color_buf + ci); - } - upsample->next_row_out = 0; - } - - /* Color-convert and emit rows */ - - /* How many we have in the buffer: */ - num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out); - /* Not more than the distance to the end of the image. Need this test - * in case the image height is not a multiple of max_v_samp_factor: - */ - if (num_rows > upsample->rows_to_go) - num_rows = upsample->rows_to_go; - /* And not more than what the client can accept: */ - out_rows_avail -= *out_row_ctr; - if (num_rows > out_rows_avail) - num_rows = out_rows_avail; - - (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf, - (JDIMENSION) upsample->next_row_out, - output_buf + *out_row_ctr, - (int) num_rows); - - /* Adjust counts */ - *out_row_ctr += num_rows; - upsample->rows_to_go -= num_rows; - upsample->next_row_out += num_rows; - /* When the buffer is emptied, declare this input row group consumed */ - if (upsample->next_row_out >= cinfo->max_v_samp_factor) - (*in_row_group_ctr)++; -} - - -/* - * These are the routines invoked by sep_upsample to upsample pixel values - * of a single component. One row group is processed per call. - */ - - -/* - * For full-size components, we just make color_buf[ci] point at the - * input buffer, and thus avoid copying any data. Note that this is - * safe only because sep_upsample doesn't declare the input row group - * "consumed" until we are done color converting and emitting it. - */ - -METHODDEF void -fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - *output_data_ptr = input_data; -} - - -/* - * This is a no-op version used for "uninteresting" components. - * These components will not be referenced by color conversion. - */ - -METHODDEF void -noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - *output_data_ptr = NULL; /* safety check */ -} - - -/* - * This version handles any integral sampling ratios. - * This is not used for typical JPEG files, so it need not be fast. - * Nor, for that matter, is it particularly accurate: the algorithm is - * simple replication of the input pixel onto the corresponding output - * pixels. The hi-falutin sampling literature refers to this as a - * "box filter". A box filter tends to introduce visible artifacts, - * so if you are actually going to use 3:1 or 4:1 sampling ratios - * you would be well advised to improve this code. - */ - -METHODDEF void -int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register JSAMPLE invalue; - register int h; - JSAMPROW outend; - int h_expand, v_expand; - int inrow, outrow; - - h_expand = upsample->h_expand[compptr->component_index]; - v_expand = upsample->v_expand[compptr->component_index]; - - inrow = outrow = 0; - while (outrow < cinfo->max_v_samp_factor) { - /* Generate one output row with proper horizontal expansion */ - inptr = input_data[inrow]; - outptr = output_data[outrow]; - outend = outptr + cinfo->output_width; - while (outptr < outend) { - invalue = *inptr++; /* don't need GETJSAMPLE() here */ - for (h = h_expand; h > 0; h--) { - *outptr++ = invalue; - } - } - /* Generate any additional output rows by duplicating the first one */ - if (v_expand > 1) { - jcopy_sample_rows(output_data, outrow, output_data, outrow+1, - v_expand-1, cinfo->output_width); - } - inrow++; - outrow += v_expand; - } -} - - -/* - * Fast processing for the common case of 2:1 horizontal and 1:1 vertical. - * It's still a box filter. - */ - -METHODDEF void -h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register JSAMPLE invalue; - JSAMPROW outend; - int inrow; - - for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { - inptr = input_data[inrow]; - outptr = output_data[inrow]; - outend = outptr + cinfo->output_width; - while (outptr < outend) { - invalue = *inptr++; /* don't need GETJSAMPLE() here */ - *outptr++ = invalue; - *outptr++ = invalue; - } - } -} - - -/* - * Fast processing for the common case of 2:1 horizontal and 2:1 vertical. - * It's still a box filter. - */ - -METHODDEF void -h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register JSAMPLE invalue; - JSAMPROW outend; - int inrow, outrow; - - inrow = outrow = 0; - while (outrow < cinfo->max_v_samp_factor) { - inptr = input_data[inrow]; - outptr = output_data[outrow]; - outend = outptr + cinfo->output_width; - while (outptr < outend) { - invalue = *inptr++; /* don't need GETJSAMPLE() here */ - *outptr++ = invalue; - *outptr++ = invalue; - } - jcopy_sample_rows(output_data, outrow, output_data, outrow+1, - 1, cinfo->output_width); - inrow++; - outrow += 2; - } -} - - -/* - * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical. - * - * The upsampling algorithm is linear interpolation between pixel centers, - * also known as a "triangle filter". This is a good compromise between - * speed and visual quality. The centers of the output pixels are 1/4 and 3/4 - * of the way between input pixel centers. - * - * A note about the "bias" calculations: when rounding fractional values to - * integer, we do not want to always round 0.5 up to the next integer. - * If we did that, we'd introduce a noticeable bias towards larger values. - * Instead, this code is arranged so that 0.5 will be rounded up or down at - * alternate pixel locations (a simple ordered dither pattern). - */ - -METHODDEF void -h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register int invalue; - register JDIMENSION colctr; - int inrow; - - for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { - inptr = input_data[inrow]; - outptr = output_data[inrow]; - /* Special case for first column */ - invalue = GETJSAMPLE(*inptr++); - *outptr++ = (JSAMPLE) invalue; - *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2); - - for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { - /* General case: 3/4 * nearer pixel + 1/4 * further pixel */ - invalue = GETJSAMPLE(*inptr++) * 3; - *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2); - *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2); - } - - /* Special case for last column */ - invalue = GETJSAMPLE(*inptr); - *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2); - *outptr++ = (JSAMPLE) invalue; - } -} - - -/* - * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical. - * Again a triangle filter; see comments for h2v1 case, above. - * - * It is OK for us to reference the adjacent input rows because we demanded - * context from the main buffer controller (see initialization code). - */ - -METHODDEF void -h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr0, inptr1, outptr; -#if BITS_IN_JSAMPLE == 8 - register int thiscolsum, lastcolsum, nextcolsum; -#else - register INT32 thiscolsum, lastcolsum, nextcolsum; -#endif - register JDIMENSION colctr; - int inrow, outrow, v; - - inrow = outrow = 0; - while (outrow < cinfo->max_v_samp_factor) { - for (v = 0; v < 2; v++) { - /* inptr0 points to nearest input row, inptr1 points to next nearest */ - inptr0 = input_data[inrow]; - if (v == 0) /* next nearest is row above */ - inptr1 = input_data[inrow-1]; - else /* next nearest is row below */ - inptr1 = input_data[inrow+1]; - outptr = output_data[outrow++]; - - /* Special case for first column */ - thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); - nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); - *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4); - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); - lastcolsum = thiscolsum; thiscolsum = nextcolsum; - - for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { - /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */ - /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */ - nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); - lastcolsum = thiscolsum; thiscolsum = nextcolsum; - } - - /* Special case for last column */ - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); - *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4); - } - inrow++; - } -} - - -/* - * Module initialization routine for upsampling. - */ - -GLOBAL void -jinit_upsampler (j_decompress_ptr cinfo) -{ - my_upsample_ptr upsample; - int ci; - jpeg_component_info * compptr; - boolean need_buffer, do_fancy; - int h_in_group, v_in_group, h_out_group, v_out_group; - - upsample = (my_upsample_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_upsampler)); - cinfo->upsample = (struct jpeg_upsampler *) upsample; - upsample->pub.start_pass = start_pass_upsample; - upsample->pub.upsample = sep_upsample; - upsample->pub.need_context_rows = FALSE; /* until we find out differently */ - - if (cinfo->CCIR601_sampling) /* this isn't supported */ - ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); - - /* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1, - * so don't ask for it. - */ - do_fancy = cinfo->do_fancy_upsampling && cinfo->min_DCT_scaled_size > 1; - - /* Verify we can handle the sampling factors, select per-component methods, - * and create storage as needed. - */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Compute size of an "input group" after IDCT scaling. This many samples - * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. - */ - h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; - v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; - h_out_group = cinfo->max_h_samp_factor; - v_out_group = cinfo->max_v_samp_factor; - upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ - need_buffer = TRUE; - if (! compptr->component_needed) { - /* Don't bother to upsample an uninteresting component. */ - upsample->methods[ci] = noop_upsample; - need_buffer = FALSE; - } else if (h_in_group == h_out_group && v_in_group == v_out_group) { - /* Fullsize components can be processed without any work. */ - upsample->methods[ci] = fullsize_upsample; - need_buffer = FALSE; - } else if (h_in_group * 2 == h_out_group && - v_in_group == v_out_group) { - /* Special cases for 2h1v upsampling */ - if (do_fancy && compptr->downsampled_width > 2) - upsample->methods[ci] = h2v1_fancy_upsample; - else - upsample->methods[ci] = h2v1_upsample; - } else if (h_in_group * 2 == h_out_group && - v_in_group * 2 == v_out_group) { - /* Special cases for 2h2v upsampling */ - if (do_fancy && compptr->downsampled_width > 2) { - upsample->methods[ci] = h2v2_fancy_upsample; - upsample->pub.need_context_rows = TRUE; - } else - upsample->methods[ci] = h2v2_upsample; - } else if ((h_out_group % h_in_group) == 0 && - (v_out_group % v_in_group) == 0) { - /* Generic integral-factors upsampling method */ - upsample->methods[ci] = int_upsample; - upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group); - upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group); - } else - ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); - if (need_buffer) { - upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) jround_up((long) cinfo->output_width, - (long) cinfo->max_h_samp_factor), - (JDIMENSION) cinfo->max_v_samp_factor); - } - } -} diff --git a/libs/jpeg6/jdtrans.cpp b/libs/jpeg6/jdtrans.cpp deleted file mode 100644 index 5c14adc..0000000 --- a/libs/jpeg6/jdtrans.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * jdtrans.c - * - * Copyright (C) 1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains library routines for transcoding decompression, - * that is, reading raw DCT coefficient arrays from an input JPEG file. - * The routines in jdapimin.c will also be needed by a transcoder. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Forward declarations */ -LOCAL void transdecode_master_selection JPP((j_decompress_ptr cinfo)); - - -/* - * Read the coefficient arrays from a JPEG file. - * jpeg_read_header must be completed before calling this. - * - * The entire image is read into a set of virtual coefficient-block arrays, - * one per component. The return value is a pointer to the array of - * virtual-array descriptors. These can be manipulated directly via the - * JPEG memory manager, or handed off to jpeg_write_coefficients(). - * To release the memory occupied by the virtual arrays, call - * jpeg_finish_decompress() when done with the data. - * - * Returns NULL if suspended. This case need be checked only if - * a suspending data source is used. - */ - -GLOBAL jvirt_barray_ptr * -jpeg_read_coefficients (j_decompress_ptr cinfo) -{ - if (cinfo->global_state == DSTATE_READY) { - /* First call: initialize active modules */ - transdecode_master_selection(cinfo); - cinfo->global_state = DSTATE_RDCOEFS; - } else if (cinfo->global_state != DSTATE_RDCOEFS) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - /* Absorb whole file into the coef buffer */ - for (;;) { - int retcode; - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - /* Absorb some more input */ - retcode = (*cinfo->inputctl->consume_input) (cinfo); - if (retcode == JPEG_SUSPENDED) - return NULL; - if (retcode == JPEG_REACHED_EOI) - break; - /* Advance progress counter if appropriate */ - if (cinfo->progress != NULL && - (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { - if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { - /* startup underestimated number of scans; ratchet up one scan */ - cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; - } - } - } - /* Set state so that jpeg_finish_decompress does the right thing */ - cinfo->global_state = DSTATE_STOPPING; - return cinfo->coef->coef_arrays; -} - - -/* - * Master selection of decompression modules for transcoding. - * This substitutes for jdmaster.c's initialization of the full decompressor. - */ - -LOCAL void -transdecode_master_selection (j_decompress_ptr cinfo) -{ - /* Entropy decoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); - } else { - if (cinfo->progressive_mode) { -#ifdef D_PROGRESSIVE_SUPPORTED - jinit_phuff_decoder(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else - jinit_huff_decoder(cinfo); - } - - /* Always get a full-image coefficient buffer. */ - jinit_d_coef_controller(cinfo, TRUE); - - /* We can now tell the memory manager to allocate virtual arrays. */ - (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); - - /* Initialize input side of decompressor to consume first scan. */ - (*cinfo->inputctl->start_input_pass) (cinfo); - - /* Initialize progress monitoring. */ - if (cinfo->progress != NULL) { - int nscans; - /* Estimate number of scans to set pass_limit. */ - if (cinfo->progressive_mode) { - /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ - nscans = 2 + 3 * cinfo->num_components; - } else if (cinfo->inputctl->has_multiple_scans) { - /* For a nonprogressive multiscan file, estimate 1 scan per component. */ - nscans = cinfo->num_components; - } else { - nscans = 1; - } - cinfo->progress->pass_counter = 0L; - cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; - cinfo->progress->completed_passes = 0; - cinfo->progress->total_passes = 1; - } -} diff --git a/libs/jpeg6/jerror.cpp b/libs/jpeg6/jerror.cpp deleted file mode 100644 index 595f371..0000000 --- a/libs/jpeg6/jerror.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/* - * jerror.c - * - * Copyright (C) 1991-1994, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains simple error-reporting and trace-message routines. - * These are suitable for Unix-like systems and others where writing to - * stderr is the right thing to do. Many applications will want to replace - * some or all of these routines. - * - * These routines are used by both the compression and decompression code. - */ - -/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ -#include "jinclude.h" -#include "jpeglib.h" -#include "jversion.h" -#include "jerror.h" - -#ifndef EXIT_FAILURE /* define exit() codes if not provided */ -#define EXIT_FAILURE 1 -#endif - - -/* - * Create the message string table. - * We do this from the master message list in jerror.h by re-reading - * jerror.h with a suitable definition for macro JMESSAGE. - * The message table is made an external symbol just in case any applications - * want to refer to it directly. - */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_std_message_table jMsgTable -#endif - -#define JMESSAGE(code,string) string , - -const char * const jpeg_std_message_table[] = { -#include "jerror.h" - NULL -}; - - -/* - * Error exit handler: must not return to caller. - * - * Applications may override this if they want to get control back after - * an error. Typically one would longjmp somewhere instead of exiting. - * The setjmp buffer can be made a private field within an expanded error - * handler object. Note that the info needed to generate an error message - * is stored in the error object, so you can generate the message now or - * later, at your convenience. - * You should make sure that the JPEG object is cleaned up (with jpeg_abort - * or jpeg_destroy) at some point. - */ - -METHODDEF void -error_exit (j_common_ptr cinfo) -{ - char buffer[JMSG_LENGTH_MAX]; - - /* Create the message */ - (*cinfo->err->format_message) (cinfo, buffer); - - /* Let the memory manager delete any temp files before we die */ - jpeg_destroy(cinfo); - - // FIXME: need to get this setup with an error handler - //Error("%s\n", buffer ); -} - - -/* - * Actual output of an error or trace message. - * Applications may override this method to send JPEG messages somewhere - * other than stderr. - */ - -METHODDEF void -output_message (j_common_ptr cinfo) -{ - char buffer[JMSG_LENGTH_MAX]; - - /* Create the message */ - (*cinfo->err->format_message) (cinfo, buffer); - - /* Send it to stderr, adding a newline */ - printf("%s\n", buffer); -} - - -/* - * Decide whether to emit a trace or warning message. - * msg_level is one of: - * -1: recoverable corrupt-data warning, may want to abort. - * 0: important advisory messages (always display to user). - * 1: first level of tracing detail. - * 2,3,...: successively more detailed tracing messages. - * An application might override this method if it wanted to abort on warnings - * or change the policy about which messages to display. - */ - -METHODDEF void -emit_message (j_common_ptr cinfo, int msg_level) -{ - struct jpeg_error_mgr * err = cinfo->err; - - if (msg_level < 0) { - /* It's a warning message. Since corrupt files may generate many warnings, - * the policy implemented here is to show only the first warning, - * unless trace_level >= 3. - */ - if (err->num_warnings == 0 || err->trace_level >= 3) - (*err->output_message) (cinfo); - /* Always count warnings in num_warnings. */ - err->num_warnings++; - } else { - /* It's a trace message. Show it if trace_level >= msg_level. */ - if (err->trace_level >= msg_level) - (*err->output_message) (cinfo); - } -} - - -/* - * Format a message string for the most recent JPEG error or message. - * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX - * characters. Note that no '\n' character is added to the string. - * Few applications should need to override this method. - */ - -METHODDEF void -format_message (j_common_ptr cinfo, char * buffer) -{ - struct jpeg_error_mgr * err = cinfo->err; - int msg_code = err->msg_code; - const char * msgtext = NULL; - const char * msgptr; - char ch; - boolean isstring; - - /* Look up message string in proper table */ - if (msg_code > 0 && msg_code <= err->last_jpeg_message) { - msgtext = err->jpeg_message_table[msg_code]; - } else if (err->addon_message_table != NULL && - msg_code >= err->first_addon_message && - msg_code <= err->last_addon_message) { - msgtext = err->addon_message_table[msg_code - err->first_addon_message]; - } - - /* Defend against bogus message number */ - if (msgtext == NULL) { - err->msg_parm.i[0] = msg_code; - msgtext = err->jpeg_message_table[0]; - } - - /* Check for string parameter, as indicated by %s in the message text */ - isstring = FALSE; - msgptr = msgtext; - while ((ch = *msgptr++) != '\0') { - if (ch == '%') { - if (*msgptr == 's') isstring = TRUE; - break; - } - } - - /* Format the message into the passed buffer */ - if (isstring) - sprintf(buffer, msgtext, err->msg_parm.s); - else - sprintf(buffer, msgtext, - err->msg_parm.i[0], err->msg_parm.i[1], - err->msg_parm.i[2], err->msg_parm.i[3], - err->msg_parm.i[4], err->msg_parm.i[5], - err->msg_parm.i[6], err->msg_parm.i[7]); -} - - -/* - * Reset error state variables at start of a new image. - * This is called during compression startup to reset trace/error - * processing to default state, without losing any application-specific - * method pointers. An application might possibly want to override - * this method if it has additional error processing state. - */ - -METHODDEF void -reset_error_mgr (j_common_ptr cinfo) -{ - cinfo->err->num_warnings = 0; - /* trace_level is not reset since it is an application-supplied parameter */ - cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */ -} - - -/* - * Fill in the standard error-handling methods in a jpeg_error_mgr object. - * Typical call is: - * struct jpeg_compress_struct cinfo; - * struct jpeg_error_mgr err; - * - * cinfo.err = jpeg_std_error(&err); - * after which the application may override some of the methods. - */ - -GLOBAL struct jpeg_error_mgr * -jpeg_std_error (struct jpeg_error_mgr * err) -{ - err->error_exit = error_exit; - err->emit_message = emit_message; - err->output_message = output_message; - err->format_message = format_message; - err->reset_error_mgr = reset_error_mgr; - - err->trace_level = 0; /* default = no tracing */ - err->num_warnings = 0; /* no warnings emitted yet */ - err->msg_code = 0; /* may be useful as a flag for "no error" */ - - /* Initialize message table pointers */ - err->jpeg_message_table = jpeg_std_message_table; - err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1; - - err->addon_message_table = NULL; - err->first_addon_message = 0; /* for safety */ - err->last_addon_message = 0; - - return err; -} diff --git a/libs/jpeg6/jerror.h b/libs/jpeg6/jerror.h deleted file mode 100644 index bf60e7e..0000000 --- a/libs/jpeg6/jerror.h +++ /dev/null @@ -1,273 +0,0 @@ -/* - * jerror.h - * - * Copyright (C) 1994-1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file defines the error and message codes for the JPEG library. - * Edit this file to add new codes, or to translate the message strings to - * some other language. - * A set of error-reporting macros are defined too. Some applications using - * the JPEG library may wish to include this file to get the error codes - * and/or the macros. - */ - -/* - * To define the enum list of message codes, include this file without - * defining macro JMESSAGE. To create a message string table, include it - * again with a suitable JMESSAGE definition (see jerror.c for an example). - */ -#ifndef JMESSAGE -#ifndef JERROR_H -/* First time through, define the enum list */ -#define JMAKE_ENUM_LIST -#else -/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ -#define JMESSAGE(code,string) -#endif /* JERROR_H */ -#endif /* JMESSAGE */ - -#ifdef JMAKE_ENUM_LIST - -typedef enum { - -#define JMESSAGE(code,string) code , - -#endif /* JMAKE_ENUM_LIST */ - -JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ - -/* For maintenance convenience, list is alphabetical by message code name */ -JMESSAGE(JERR_ARITH_NOTIMPL, - "Sorry, there are legal restrictions on arithmetic coding") -JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") -JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") -JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") -JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") -JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") -JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") -JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") -JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") -JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") -JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") -JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") -JMESSAGE(JERR_BAD_PROGRESSION, - "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") -JMESSAGE(JERR_BAD_PROG_SCRIPT, - "Invalid progressive parameters at scan script entry %d") -JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") -JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") -JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") -JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") -JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") -JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") -JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") -JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") -JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") -JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") -JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") -JMESSAGE(JERR_DHT_COUNTS, "Bogus DHT counts") -JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") -JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") -JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") -JMESSAGE(JERR_EMS_READ, "Read from EMS failed") -JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") -JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") -JMESSAGE(JERR_FILE_READ, "Input file read error") -JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") -JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") -JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") -JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") -JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") -JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") -JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") -JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, - "Cannot transcode due to multiple use of quantization table %d") -JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") -JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") -JMESSAGE(JERR_NOTIMPL, "Not implemented yet") -JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") -JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") -JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") -JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") -JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") -JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") -JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") -JMESSAGE(JERR_QUANT_COMPONENTS, - "Cannot quantize more than %d color components") -JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") -JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") -JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") -JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") -JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") -JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") -JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") -JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") -JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") -JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") -JMESSAGE(JERR_TFILE_WRITE, - "Write failed on temporary file --- out of disk space?") -JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") -JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") -JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") -JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") -JMESSAGE(JERR_XMS_READ, "Read from XMS failed") -JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") -JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) -JMESSAGE(JMSG_VERSION, JVERSION) -JMESSAGE(JTRC_16BIT_TABLES, - "Caution: quantization tables are too coarse for baseline JPEG") -JMESSAGE(JTRC_ADOBE, - "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") -JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") -JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") -JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") -JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") -JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") -JMESSAGE(JTRC_DRI, "Define Restart Interval %u") -JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") -JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") -JMESSAGE(JTRC_EOI, "End Of Image") -JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") -JMESSAGE(JTRC_JFIF, "JFIF APP0 marker, density %dx%d %d") -JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, - "Warning: thumbnail image size does not match data length %u") -JMESSAGE(JTRC_JFIF_MINOR, "Unknown JFIF minor revision number %d.%02d") -JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") -JMESSAGE(JTRC_MISC_MARKER, "Skipping marker 0x%02x, length %u") -JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") -JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") -JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") -JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") -JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") -JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") -JMESSAGE(JTRC_RST, "RST%d") -JMESSAGE(JTRC_SMOOTH_NOTIMPL, - "Smoothing not supported with nonstandard sampling ratios") -JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") -JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") -JMESSAGE(JTRC_SOI, "Start of Image") -JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") -JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") -JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") -JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") -JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") -JMESSAGE(JTRC_UNKNOWN_IDS, - "Unrecognized component IDs %d %d %d, assuming YCbCr") -JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") -JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") -JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") -JMESSAGE(JWRN_BOGUS_PROGRESSION, - "Inconsistent progression sequence for component %d coefficient %d") -JMESSAGE(JWRN_EXTRANEOUS_DATA, - "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") -JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") -JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") -JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") -JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") -JMESSAGE(JWRN_MUST_RESYNC, - "Corrupt JPEG data: found marker 0x%02x instead of RST%d") -JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") -JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") - -#ifdef JMAKE_ENUM_LIST - - JMSG_LASTMSGCODE -} J_MESSAGE_CODE; - -#undef JMAKE_ENUM_LIST -#endif /* JMAKE_ENUM_LIST */ - -/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ -#undef JMESSAGE - - -#ifndef JERROR_H -#define JERROR_H - -/* Macros to simplify using the error and trace message stuff */ -/* The first parameter is either type of cinfo pointer */ - -/* Fatal errors (print message and exit) */ -#define ERREXIT(cinfo,code) \ - ((cinfo)->err->msg_code = (code), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT1(cinfo,code,p1) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT2(cinfo,code,p1,p2) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT3(cinfo,code,p1,p2,p3) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (cinfo)->err->msg_parm.i[2] = (p3), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (cinfo)->err->msg_parm.i[2] = (p3), \ - (cinfo)->err->msg_parm.i[3] = (p4), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXITS(cinfo,code,str) \ - ((cinfo)->err->msg_code = (code), \ - strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) - -#define MAKESTMT(stuff) do { stuff } while (0) - -/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ -#define WARNMS(cinfo,code) \ - ((cinfo)->err->msg_code = (code), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) -#define WARNMS1(cinfo,code,p1) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) -#define WARNMS2(cinfo,code,p1,p2) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) - -/* Informational/debugging messages */ -#define TRACEMS(cinfo,lvl,code) \ - ((cinfo)->err->msg_code = (code), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) -#define TRACEMS1(cinfo,lvl,code,p1) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) -#define TRACEMS2(cinfo,lvl,code,p1,p2) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) -#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ - MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) -#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ - MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) -#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ - MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ - _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) -#define TRACEMSS(cinfo,lvl,code,str) \ - ((cinfo)->err->msg_code = (code), \ - strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) - -#endif /* JERROR_H */ diff --git a/libs/jpeg6/jfdctflt.cpp b/libs/jpeg6/jfdctflt.cpp deleted file mode 100644 index 21371eb..0000000 --- a/libs/jpeg6/jfdctflt.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * jfdctflt.c - * - * Copyright (C) 1994, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains a floating-point implementation of the - * forward DCT (Discrete Cosine Transform). - * - * This implementation should be more accurate than either of the integer - * DCT implementations. However, it may not give the same results on all - * machines because of differences in roundoff behavior. Speed will depend - * on the hardware's floating point capacity. - * - * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT - * on each column. Direct algorithms are also available, but they are - * much more complex and seem not to be any faster when reduced to code. - * - * This implementation is based on Arai, Agui, and Nakajima's algorithm for - * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in - * Japanese, but the algorithm is described in the Pennebaker & Mitchell - * JPEG textbook (see REFERENCES section in file README). The following code - * is based directly on figure 4-8 in P&M. - * While an 8-point DCT cannot be done in less than 11 multiplies, it is - * possible to arrange the computation so that many of the multiplies are - * simple scalings of the final outputs. These multiplies can then be - * folded into the multiplications or divisions by the JPEG quantization - * table entries. The AA&N method leaves only 5 multiplies and 29 adds - * to be done in the DCT itself. - * The primary disadvantage of this method is that with a fixed-point - * implementation, accuracy is lost due to imprecise representation of the - * scaled quantization values. However, that problem does not arise if - * we use floating point arithmetic. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - -#ifdef DCT_FLOAT_SUPPORTED - - -/* - * This module is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ -#endif - - -/* - * Perform the forward DCT on one block of samples. - */ - -GLOBAL void -jpeg_fdct_float (FAST_FLOAT * data) -{ - FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; - FAST_FLOAT tmp10, tmp11, tmp12, tmp13; - FAST_FLOAT z1, z2, z3, z4, z5, z11, z13; - FAST_FLOAT *dataptr; - int ctr; - - /* Pass 1: process rows. */ - - dataptr = data; - for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[0] + dataptr[7]; - tmp7 = dataptr[0] - dataptr[7]; - tmp1 = dataptr[1] + dataptr[6]; - tmp6 = dataptr[1] - dataptr[6]; - tmp2 = dataptr[2] + dataptr[5]; - tmp5 = dataptr[2] - dataptr[5]; - tmp3 = dataptr[3] + dataptr[4]; - tmp4 = dataptr[3] - dataptr[4]; - - /* Even part */ - - tmp10 = tmp0 + tmp3; /* phase 2 */ - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - dataptr[0] = tmp10 + tmp11; /* phase 3 */ - dataptr[4] = tmp10 - tmp11; - - z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ - dataptr[2] = tmp13 + z1; /* phase 5 */ - dataptr[6] = tmp13 - z1; - - /* Odd part */ - - tmp10 = tmp4 + tmp5; /* phase 2 */ - tmp11 = tmp5 + tmp6; - tmp12 = tmp6 + tmp7; - - /* The rotator is modified from fig 4-8 to avoid extra negations. */ - z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ - z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ - z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ - z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ - - z11 = tmp7 + z3; /* phase 5 */ - z13 = tmp7 - z3; - - dataptr[5] = z13 + z2; /* phase 6 */ - dataptr[3] = z13 - z2; - dataptr[1] = z11 + z4; - dataptr[7] = z11 - z4; - - dataptr += DCTSIZE; /* advance pointer to next row */ - } - - /* Pass 2: process columns. */ - - dataptr = data; - for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; - tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; - tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; - tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; - tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; - tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; - tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; - tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; - - /* Even part */ - - tmp10 = tmp0 + tmp3; /* phase 2 */ - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ - dataptr[DCTSIZE*4] = tmp10 - tmp11; - - z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ - dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ - dataptr[DCTSIZE*6] = tmp13 - z1; - - /* Odd part */ - - tmp10 = tmp4 + tmp5; /* phase 2 */ - tmp11 = tmp5 + tmp6; - tmp12 = tmp6 + tmp7; - - /* The rotator is modified from fig 4-8 to avoid extra negations. */ - z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ - z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ - z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ - z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ - - z11 = tmp7 + z3; /* phase 5 */ - z13 = tmp7 - z3; - - dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ - dataptr[DCTSIZE*3] = z13 - z2; - dataptr[DCTSIZE*1] = z11 + z4; - dataptr[DCTSIZE*7] = z11 - z4; - - dataptr++; /* advance pointer to next column */ - } -} - -#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/libs/jpeg6/jidctflt.cpp b/libs/jpeg6/jidctflt.cpp deleted file mode 100644 index 847919e..0000000 --- a/libs/jpeg6/jidctflt.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/* - * jidctflt.c - * - * Copyright (C) 1994, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains a floating-point implementation of the - * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine - * must also perform dequantization of the input coefficients. - * - * This implementation should be more accurate than either of the integer - * IDCT implementations. However, it may not give the same results on all - * machines because of differences in roundoff behavior. Speed will depend - * on the hardware's floating point capacity. - * - * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT - * on each row (or vice versa, but it's more convenient to emit a row at - * a time). Direct algorithms are also available, but they are much more - * complex and seem not to be any faster when reduced to code. - * - * This implementation is based on Arai, Agui, and Nakajima's algorithm for - * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in - * Japanese, but the algorithm is described in the Pennebaker & Mitchell - * JPEG textbook (see REFERENCES section in file README). The following code - * is based directly on figure 4-8 in P&M. - * While an 8-point DCT cannot be done in less than 11 multiplies, it is - * possible to arrange the computation so that many of the multiplies are - * simple scalings of the final outputs. These multiplies can then be - * folded into the multiplications or divisions by the JPEG quantization - * table entries. The AA&N method leaves only 5 multiplies and 29 adds - * to be done in the DCT itself. - * The primary disadvantage of this method is that with a fixed-point - * implementation, accuracy is lost due to imprecise representation of the - * scaled quantization values. However, that problem does not arise if - * we use floating point arithmetic. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - -#ifdef DCT_FLOAT_SUPPORTED - - -/* - * This module is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ -#endif - - -/* Dequantize a coefficient by multiplying it by the multiplier-table - * entry; produce a float result. - */ - -#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval)) - - -/* - * Perform dequantization and inverse DCT on one block of coefficients. - */ - -GLOBAL void -jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; - FAST_FLOAT tmp10, tmp11, tmp12, tmp13; - FAST_FLOAT z5, z10, z11, z12, z13; - JCOEFPTR inptr; - FLOAT_MULT_TYPE * quantptr; - FAST_FLOAT * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = DCTSIZE; ctr > 0; ctr--) { - /* Due to quantization, we will usually find that many of the input - * coefficients are zero, especially the AC terms. We can exploit this - * by short-circuiting the IDCT calculation for any column in which all - * the AC terms are zero. In that case each output is equal to the - * DC coefficient (with scale factor as needed). - * With typical images and quantization tables, half or more of the - * column DCT calculations can be simplified this way. - */ - - if ((inptr[DCTSIZE*1] | inptr[DCTSIZE*2] | inptr[DCTSIZE*3] | - inptr[DCTSIZE*4] | inptr[DCTSIZE*5] | inptr[DCTSIZE*6] | - inptr[DCTSIZE*7]) == 0) { - /* AC terms all zero */ - FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - wsptr[DCTSIZE*2] = dcval; - wsptr[DCTSIZE*3] = dcval; - wsptr[DCTSIZE*4] = dcval; - wsptr[DCTSIZE*5] = dcval; - wsptr[DCTSIZE*6] = dcval; - wsptr[DCTSIZE*7] = dcval; - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - continue; - } - - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - tmp10 = tmp0 + tmp2; /* phase 3 */ - tmp11 = tmp0 - tmp2; - - tmp13 = tmp1 + tmp3; /* phases 5-3 */ - tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ - - tmp0 = tmp10 + tmp13; /* phase 2 */ - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; - - /* Odd part */ - - tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - - z13 = tmp6 + tmp5; /* phase 6 */ - z10 = tmp6 - tmp5; - z11 = tmp4 + tmp7; - z12 = tmp4 - tmp7; - - tmp7 = z11 + z13; /* phase 5 */ - tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ - - z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ - tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ - tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ - - tmp6 = tmp12 - tmp7; /* phase 2 */ - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; - - wsptr[DCTSIZE*0] = tmp0 + tmp7; - wsptr[DCTSIZE*7] = tmp0 - tmp7; - wsptr[DCTSIZE*1] = tmp1 + tmp6; - wsptr[DCTSIZE*6] = tmp1 - tmp6; - wsptr[DCTSIZE*2] = tmp2 + tmp5; - wsptr[DCTSIZE*5] = tmp2 - tmp5; - wsptr[DCTSIZE*4] = tmp3 + tmp4; - wsptr[DCTSIZE*3] = tmp3 - tmp4; - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - } - - /* Pass 2: process rows from work array, store into output array. */ - /* Note that we must descale the results by a factor of 8 == 2**3. */ - - wsptr = workspace; - for (ctr = 0; ctr < DCTSIZE; ctr++) { - outptr = output_buf[ctr] + output_col; - /* Rows of zeroes can be exploited in the same way as we did with columns. - * However, the column calculation has created many nonzero AC terms, so - * the simplification applies less often (typically 5% to 10% of the time). - * And testing floats for zero is relatively expensive, so we don't bother. - */ - - /* Even part */ - - tmp10 = wsptr[0] + wsptr[4]; - tmp11 = wsptr[0] - wsptr[4]; - - tmp13 = wsptr[2] + wsptr[6]; - tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13; - - tmp0 = tmp10 + tmp13; - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; - - /* Odd part */ - - z13 = wsptr[5] + wsptr[3]; - z10 = wsptr[5] - wsptr[3]; - z11 = wsptr[1] + wsptr[7]; - z12 = wsptr[1] - wsptr[7]; - - tmp7 = z11 + z13; - tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); - - z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ - tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ - tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ - - tmp6 = tmp12 - tmp7; - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; - - /* Final output stage: scale down by a factor of 8 and range-limit */ - - outptr[0] = range_limit[(int) DESCALE((INT32) (tmp0 + tmp7), 3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) DESCALE((INT32) (tmp0 - tmp7), 3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) DESCALE((INT32) (tmp1 + tmp6), 3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) DESCALE((INT32) (tmp1 - tmp6), 3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) DESCALE((INT32) (tmp2 + tmp5), 3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) DESCALE((INT32) (tmp2 - tmp5), 3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) DESCALE((INT32) (tmp3 + tmp4), 3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) DESCALE((INT32) (tmp3 - tmp4), 3) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ - } -} - -#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/libs/jpeg6/jinclude.h b/libs/jpeg6/jinclude.h deleted file mode 100644 index 0a4f151..0000000 --- a/libs/jpeg6/jinclude.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * jinclude.h - * - * Copyright (C) 1991-1994, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file exists to provide a single place to fix any problems with - * including the wrong system include files. (Common problems are taken - * care of by the standard jconfig symbols, but on really weird systems - * you may have to edit this file.) - * - * NOTE: this file is NOT intended to be included by applications using the - * JPEG library. Most applications need only include jpeglib.h. - */ - - -/* Include auto-config file to find out which system include files we need. */ - -#include "jconfig.h" /* auto configuration options */ -#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ - -/* - * We need the NULL macro and size_t typedef. - * On an ANSI-conforming system it is sufficient to include <stddef.h>. - * Otherwise, we get them from <stdlib.h> or <stdio.h>; we may have to - * pull in <sys/types.h> as well. - * Note that the core JPEG library does not require <stdio.h>; - * only the default error handler and data source/destination modules do. - * But we must pull it in because of the references to FILE in jpeglib.h. - * You can remove those references if you want to compile without <stdio.h>. - */ - -#ifdef HAVE_STDDEF_H -#include <stddef.h> -#endif - -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif - -#ifdef NEED_SYS_TYPES_H -#include <sys/types.h> -#endif - -#include <stdio.h> - -/* - * We need memory copying and zeroing functions, plus strncpy(). - * ANSI and System V implementations declare these in <string.h>. - * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). - * Some systems may declare memset and memcpy in <memory.h>. - * - * NOTE: we assume the size parameters to these functions are of type size_t. - * Change the casts in these macros if not! - */ - -#ifdef NEED_BSD_STRINGS - -#include <strings.h> -#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) -#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) - -#else /* not BSD, assume ANSI/SysV string lib */ - -#include <string.h> -#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) -#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) - -#endif - -/* - * In ANSI C, and indeed any rational implementation, size_t is also the - * type returned by sizeof(). However, it seems there are some irrational - * implementations out there, in which sizeof() returns an int even though - * size_t is defined as long or unsigned long. To ensure consistent results - * we always use this SIZEOF() macro in place of using sizeof() directly. - */ - -#define SIZEOF(object) ((size_t) sizeof(object)) - -/* - * The modules that use fread() and fwrite() always invoke them through - * these macros. On some systems you may need to twiddle the argument casts. - * CAUTION: argument order is different from underlying functions! - */ - -#define JFREAD(file,buf,sizeofbuf) \ - ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) -#define JFWRITE(file,buf,sizeofbuf) \ - ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) diff --git a/libs/jpeg6/jmemmgr.cpp b/libs/jpeg6/jmemmgr.cpp deleted file mode 100644 index dc3e1c7..0000000 --- a/libs/jpeg6/jmemmgr.cpp +++ /dev/null @@ -1,1115 +0,0 @@ -/* - * jmemmgr.c - * - * Copyright (C) 1991-1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the JPEG system-independent memory management - * routines. This code is usable across a wide variety of machines; most - * of the system dependencies have been isolated in a separate file. - * The major functions provided here are: - * * pool-based allocation and freeing of memory; - * * policy decisions about how to divide available memory among the - * virtual arrays; - * * control logic for swapping virtual arrays between main memory and - * backing storage. - * The separate system-dependent file provides the actual backing-storage - * access code, and it contains the policy decision about how much total - * main memory to use. - * This file is system-dependent in the sense that some of its functions - * are unnecessary in some systems. For example, if there is enough virtual - * memory so that backing storage will never be used, much of the virtual - * array control logic could be removed. (Of course, if you have that much - * memory then you shouldn't care about a little bit of unused code...) - */ - -#define JPEG_INTERNALS -#define AM_MEMORY_MANAGER /* we define jvirt_Xarray_control structs */ -#include "jinclude.h" -#include "jpeglib.h" -#include "jmemsys.h" /* import the system-dependent declarations */ - -#ifndef NO_GETENV -#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare getenv() */ -extern char * getenv JPP((const char * name)); -#endif -#endif - - -/* - * Some important notes: - * The allocation routines provided here must never return NULL. - * They should exit to error_exit if unsuccessful. - * - * It's not a good idea to try to merge the sarray and barray routines, - * even though they are textually almost the same, because samples are - * usually stored as bytes while coefficients are shorts or ints. Thus, - * in machines where byte pointers have a different representation from - * word pointers, the resulting machine code could not be the same. - */ - - -/* - * Many machines require storage alignment: longs must start on 4-byte - * boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc() - * always returns pointers that are multiples of the worst-case alignment - * requirement, and we had better do so too. - * There isn't any really portable way to determine the worst-case alignment - * requirement. This module assumes that the alignment requirement is - * multiples of sizeof(ALIGN_TYPE). - * By default, we define ALIGN_TYPE as double. This is necessary on some - * workstations (where doubles really do need 8-byte alignment) and will work - * fine on nearly everything. If your machine has lesser alignment needs, - * you can save a few bytes by making ALIGN_TYPE smaller. - * The only place I know of where this will NOT work is certain Macintosh - * 680x0 compilers that define double as a 10-byte IEEE extended float. - * Doing 10-byte alignment is counterproductive because longwords won't be - * aligned well. Put "#define ALIGN_TYPE long" in jconfig.h if you have - * such a compiler. - */ - -#ifndef ALIGN_TYPE /* so can override from jconfig.h */ -#define ALIGN_TYPE double -#endif - - -/* - * We allocate objects from "pools", where each pool is gotten with a single - * request to jpeg_get_small() or jpeg_get_large(). There is no per-object - * overhead within a pool, except for alignment padding. Each pool has a - * header with a link to the next pool of the same class. - * Small and large pool headers are identical except that the latter's - * link pointer must be FAR on 80x86 machines. - * Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE - * field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple - * of the alignment requirement of ALIGN_TYPE. - */ - -typedef union small_pool_struct * small_pool_ptr; - -typedef union small_pool_struct { - struct { - small_pool_ptr next; /* next in list of pools */ - size_t bytes_used; /* how many bytes already used within pool */ - size_t bytes_left; /* bytes still available in this pool */ - } hdr; - ALIGN_TYPE dummy; /* included in union to ensure alignment */ -} small_pool_hdr; - -typedef union large_pool_struct FAR * large_pool_ptr; - -typedef union large_pool_struct { - struct { - large_pool_ptr next; /* next in list of pools */ - size_t bytes_used; /* how many bytes already used within pool */ - size_t bytes_left; /* bytes still available in this pool */ - } hdr; - ALIGN_TYPE dummy; /* included in union to ensure alignment */ -} large_pool_hdr; - - -/* - * Here is the full definition of a memory manager object. - */ - -typedef struct { - struct jpeg_memory_mgr pub; /* public fields */ - - /* Each pool identifier (lifetime class) names a linked list of pools. */ - small_pool_ptr small_list[JPOOL_NUMPOOLS]; - large_pool_ptr large_list[JPOOL_NUMPOOLS]; - - /* Since we only have one lifetime class of virtual arrays, only one - * linked list is necessary (for each datatype). Note that the virtual - * array control blocks being linked together are actually stored somewhere - * in the small-pool list. - */ - jvirt_sarray_ptr virt_sarray_list; - jvirt_barray_ptr virt_barray_list; - - /* This counts total space obtained from jpeg_get_small/large */ - long total_space_allocated; - - /* alloc_sarray and alloc_barray set this value for use by virtual - * array routines. - */ - JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */ -} my_memory_mgr; - -typedef my_memory_mgr * my_mem_ptr; - - -/* - * The control blocks for virtual arrays. - * Note that these blocks are allocated in the "small" pool area. - * System-dependent info for the associated backing store (if any) is hidden - * inside the backing_store_info struct. - */ - -struct jvirt_sarray_control { - JSAMPARRAY mem_buffer; /* => the in-memory buffer */ - JDIMENSION rows_in_array; /* total virtual array height */ - JDIMENSION samplesperrow; /* width of array (and of memory buffer) */ - JDIMENSION maxaccess; /* max rows accessed by access_virt_sarray */ - JDIMENSION rows_in_mem; /* height of memory buffer */ - JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ - JDIMENSION cur_start_row; /* first logical row # in the buffer */ - JDIMENSION first_undef_row; /* row # of first uninitialized row */ - boolean pre_zero; /* pre-zero mode requested? */ - boolean dirty; /* do current buffer contents need written? */ - boolean b_s_open; /* is backing-store data valid? */ - jvirt_sarray_ptr next; /* link to next virtual sarray control block */ - backing_store_info b_s_info; /* System-dependent control info */ -}; - -struct jvirt_barray_control { - JBLOCKARRAY mem_buffer; /* => the in-memory buffer */ - JDIMENSION rows_in_array; /* total virtual array height */ - JDIMENSION blocksperrow; /* width of array (and of memory buffer) */ - JDIMENSION maxaccess; /* max rows accessed by access_virt_barray */ - JDIMENSION rows_in_mem; /* height of memory buffer */ - JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ - JDIMENSION cur_start_row; /* first logical row # in the buffer */ - JDIMENSION first_undef_row; /* row # of first uninitialized row */ - boolean pre_zero; /* pre-zero mode requested? */ - boolean dirty; /* do current buffer contents need written? */ - boolean b_s_open; /* is backing-store data valid? */ - jvirt_barray_ptr next; /* link to next virtual barray control block */ - backing_store_info b_s_info; /* System-dependent control info */ -}; - - -#ifdef MEM_STATS /* optional extra stuff for statistics */ - -LOCAL void -print_mem_stats (j_common_ptr cinfo, int pool_id) -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - small_pool_ptr shdr_ptr; - large_pool_ptr lhdr_ptr; - - /* Since this is only a debugging stub, we can cheat a little by using - * fprintf directly rather than going through the trace message code. - * This is helpful because message parm array can't handle longs. - */ - fprintf(stderr, "Freeing pool %d, total space = %ld\n", - pool_id, mem->total_space_allocated); - - for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL; - lhdr_ptr = lhdr_ptr->hdr.next) { - fprintf(stderr, " Large chunk used %ld\n", - (long) lhdr_ptr->hdr.bytes_used); - } - - for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL; - shdr_ptr = shdr_ptr->hdr.next) { - fprintf(stderr, " Small chunk used %ld free %ld\n", - (long) shdr_ptr->hdr.bytes_used, - (long) shdr_ptr->hdr.bytes_left); - } -} - -#endif /* MEM_STATS */ - - -LOCAL void -out_of_memory (j_common_ptr cinfo, int which) -/* Report an out-of-memory error and stop execution */ -/* If we compiled MEM_STATS support, report alloc requests before dying */ -{ -#ifdef MEM_STATS - cinfo->err->trace_level = 2; /* force self_destruct to report stats */ -#endif - ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which); -} - - -/* - * Allocation of "small" objects. - * - * For these, we use pooled storage. When a new pool must be created, - * we try to get enough space for the current request plus a "slop" factor, - * where the slop will be the amount of leftover space in the new pool. - * The speed vs. space tradeoff is largely determined by the slop values. - * A different slop value is provided for each pool class (lifetime), - * and we also distinguish the first pool of a class from later ones. - * NOTE: the values given work fairly well on both 16- and 32-bit-int - * machines, but may be too small if longs are 64 bits or more. - */ - -static const size_t first_pool_slop[JPOOL_NUMPOOLS] = -{ - 1600, /* first PERMANENT pool */ - 16000 /* first IMAGE pool */ -}; - -static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = -{ - 0, /* additional PERMANENT pools */ - 5000 /* additional IMAGE pools */ -}; - -#define MIN_SLOP 50 /* greater than 0 to avoid futile looping */ - - -METHODDEF void * -alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) -/* Allocate a "small" object */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - small_pool_ptr hdr_ptr, prev_hdr_ptr; - char * data_ptr; - size_t odd_bytes, min_request, slop; - - /* Check for unsatisfiable request (do now to ensure no overflow below) */ - if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr))) - out_of_memory(cinfo, 1); /* request exceeds malloc's ability */ - - /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ - odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); - if (odd_bytes > 0) - sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; - - /* See if space is available in any existing pool */ - if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - prev_hdr_ptr = NULL; - hdr_ptr = mem->small_list[pool_id]; - while (hdr_ptr != NULL) { - if (hdr_ptr->hdr.bytes_left >= sizeofobject) - break; /* found pool with enough space */ - prev_hdr_ptr = hdr_ptr; - hdr_ptr = hdr_ptr->hdr.next; - } - - /* Time to make a new pool? */ - if (hdr_ptr == NULL) { - /* min_request is what we need now, slop is what will be leftover */ - min_request = sizeofobject + SIZEOF(small_pool_hdr); - if (prev_hdr_ptr == NULL) /* first pool in class? */ - slop = first_pool_slop[pool_id]; - else - slop = extra_pool_slop[pool_id]; - /* Don't ask for more than MAX_ALLOC_CHUNK */ - if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request)) - slop = (size_t) (MAX_ALLOC_CHUNK-min_request); - /* Try to get space, if fail reduce slop and try again */ - for (;;) { - hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop); - if (hdr_ptr != NULL) - break; - slop /= 2; - if (slop < MIN_SLOP) /* give up when it gets real small */ - out_of_memory(cinfo, 2); /* jpeg_get_small failed */ - } - mem->total_space_allocated += min_request + slop; - /* Success, initialize the new pool header and add to end of list */ - hdr_ptr->hdr.next = NULL; - hdr_ptr->hdr.bytes_used = 0; - hdr_ptr->hdr.bytes_left = sizeofobject + slop; - if (prev_hdr_ptr == NULL) /* first pool in class? */ - mem->small_list[pool_id] = hdr_ptr; - else - prev_hdr_ptr->hdr.next = hdr_ptr; - } - - /* OK, allocate the object from the current pool */ - data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */ - data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */ - hdr_ptr->hdr.bytes_used += sizeofobject; - hdr_ptr->hdr.bytes_left -= sizeofobject; - - return (void *) data_ptr; -} - - -/* - * Allocation of "large" objects. - * - * The external semantics of these are the same as "small" objects, - * except that FAR pointers are used on 80x86. However the pool - * management heuristics are quite different. We assume that each - * request is large enough that it may as well be passed directly to - * jpeg_get_large; the pool management just links everything together - * so that we can free it all on demand. - * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY - * structures. The routines that create these structures (see below) - * deliberately bunch rows together to ensure a large request size. - */ - -METHODDEF void FAR * -alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) -/* Allocate a "large" object */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - large_pool_ptr hdr_ptr; - size_t odd_bytes; - - /* Check for unsatisfiable request (do now to ensure no overflow below) */ - if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr))) - out_of_memory(cinfo, 3); /* request exceeds malloc's ability */ - - /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ - odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); - if (odd_bytes > 0) - sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; - - /* Always make a new pool */ - if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - - hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject + - SIZEOF(large_pool_hdr)); - if (hdr_ptr == NULL) - out_of_memory(cinfo, 4); /* jpeg_get_large failed */ - mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr); - - /* Success, initialize the new pool header and add to list */ - hdr_ptr->hdr.next = mem->large_list[pool_id]; - /* We maintain space counts in each pool header for statistical purposes, - * even though they are not needed for allocation. - */ - hdr_ptr->hdr.bytes_used = sizeofobject; - hdr_ptr->hdr.bytes_left = 0; - mem->large_list[pool_id] = hdr_ptr; - - return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */ -} - - -/* - * Creation of 2-D sample arrays. - * The pointers are in near heap, the samples themselves in FAR heap. - * - * To minimize allocation overhead and to allow I/O of large contiguous - * blocks, we allocate the sample rows in groups of as many rows as possible - * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request. - * NB: the virtual array control routines, later in this file, know about - * this chunking of rows. The rowsperchunk value is left in the mem manager - * object so that it can be saved away if this sarray is the workspace for - * a virtual array. - */ - -METHODDEF JSAMPARRAY -alloc_sarray (j_common_ptr cinfo, int pool_id, - JDIMENSION samplesperrow, JDIMENSION numrows) -/* Allocate a 2-D sample array */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - JSAMPARRAY result; - JSAMPROW workspace; - JDIMENSION rowsperchunk, currow, i; - long ltemp; - - /* Calculate max # of rows allowed in one allocation chunk */ - ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / - ((long) samplesperrow * SIZEOF(JSAMPLE)); - if (ltemp <= 0) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - if (ltemp < (long) numrows) - rowsperchunk = (JDIMENSION) ltemp; - else - rowsperchunk = numrows; - mem->last_rowsperchunk = rowsperchunk; - - /* Get space for row pointers (small object) */ - result = (JSAMPARRAY) alloc_small(cinfo, pool_id, - (size_t) (numrows * SIZEOF(JSAMPROW))); - - /* Get the rows themselves (large objects) */ - currow = 0; - while (currow < numrows) { - rowsperchunk = MIN(rowsperchunk, numrows - currow); - workspace = (JSAMPROW) alloc_large(cinfo, pool_id, - (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow - * SIZEOF(JSAMPLE))); - for (i = rowsperchunk; i > 0; i--) { - result[currow++] = workspace; - workspace += samplesperrow; - } - } - - return result; -} - - -/* - * Creation of 2-D coefficient-block arrays. - * This is essentially the same as the code for sample arrays, above. - */ - -METHODDEF JBLOCKARRAY -alloc_barray (j_common_ptr cinfo, int pool_id, - JDIMENSION blocksperrow, JDIMENSION numrows) -/* Allocate a 2-D coefficient-block array */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - JBLOCKARRAY result; - JBLOCKROW workspace; - JDIMENSION rowsperchunk, currow, i; - long ltemp; - - /* Calculate max # of rows allowed in one allocation chunk */ - ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / - ((long) blocksperrow * SIZEOF(JBLOCK)); - if (ltemp <= 0) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - if (ltemp < (long) numrows) - rowsperchunk = (JDIMENSION) ltemp; - else - rowsperchunk = numrows; - mem->last_rowsperchunk = rowsperchunk; - - /* Get space for row pointers (small object) */ - result = (JBLOCKARRAY) alloc_small(cinfo, pool_id, - (size_t) (numrows * SIZEOF(JBLOCKROW))); - - /* Get the rows themselves (large objects) */ - currow = 0; - while (currow < numrows) { - rowsperchunk = MIN(rowsperchunk, numrows - currow); - workspace = (JBLOCKROW) alloc_large(cinfo, pool_id, - (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow - * SIZEOF(JBLOCK))); - for (i = rowsperchunk; i > 0; i--) { - result[currow++] = workspace; - workspace += blocksperrow; - } - } - - return result; -} - - -/* - * About virtual array management: - * - * The above "normal" array routines are only used to allocate strip buffers - * (as wide as the image, but just a few rows high). Full-image-sized buffers - * are handled as "virtual" arrays. The array is still accessed a strip at a - * time, but the memory manager must save the whole array for repeated - * accesses. The intended implementation is that there is a strip buffer in - * memory (as high as is possible given the desired memory limit), plus a - * backing file that holds the rest of the array. - * - * The request_virt_array routines are told the total size of the image and - * the maximum number of rows that will be accessed at once. The in-memory - * buffer must be at least as large as the maxaccess value. - * - * The request routines create control blocks but not the in-memory buffers. - * That is postponed until realize_virt_arrays is called. At that time the - * total amount of space needed is known (approximately, anyway), so free - * memory can be divided up fairly. - * - * The access_virt_array routines are responsible for making a specific strip - * area accessible (after reading or writing the backing file, if necessary). - * Note that the access routines are told whether the caller intends to modify - * the accessed strip; during a read-only pass this saves having to rewrite - * data to disk. The access routines are also responsible for pre-zeroing - * any newly accessed rows, if pre-zeroing was requested. - * - * In current usage, the access requests are usually for nonoverlapping - * strips; that is, successive access start_row numbers differ by exactly - * num_rows = maxaccess. This means we can get good performance with simple - * buffer dump/reload logic, by making the in-memory buffer be a multiple - * of the access height; then there will never be accesses across bufferload - * boundaries. The code will still work with overlapping access requests, - * but it doesn't handle bufferload overlaps very efficiently. - */ - - -METHODDEF jvirt_sarray_ptr -request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero, - JDIMENSION samplesperrow, JDIMENSION numrows, - JDIMENSION maxaccess) -/* Request a virtual 2-D sample array */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - jvirt_sarray_ptr result; - - /* Only IMAGE-lifetime virtual arrays are currently supported */ - if (pool_id != JPOOL_IMAGE) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - - /* get control block */ - result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id, - SIZEOF(struct jvirt_sarray_control)); - - result->mem_buffer = NULL; /* marks array not yet realized */ - result->rows_in_array = numrows; - result->samplesperrow = samplesperrow; - result->maxaccess = maxaccess; - result->pre_zero = pre_zero; - result->b_s_open = FALSE; /* no associated backing-store object */ - result->next = mem->virt_sarray_list; /* add to list of virtual arrays */ - mem->virt_sarray_list = result; - - return result; -} - - -METHODDEF jvirt_barray_ptr -request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, - JDIMENSION blocksperrow, JDIMENSION numrows, - JDIMENSION maxaccess) -/* Request a virtual 2-D coefficient-block array */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - jvirt_barray_ptr result; - - /* Only IMAGE-lifetime virtual arrays are currently supported */ - if (pool_id != JPOOL_IMAGE) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - - /* get control block */ - result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id, - SIZEOF(struct jvirt_barray_control)); - - result->mem_buffer = NULL; /* marks array not yet realized */ - result->rows_in_array = numrows; - result->blocksperrow = blocksperrow; - result->maxaccess = maxaccess; - result->pre_zero = pre_zero; - result->b_s_open = FALSE; /* no associated backing-store object */ - result->next = mem->virt_barray_list; /* add to list of virtual arrays */ - mem->virt_barray_list = result; - - return result; -} - - -METHODDEF void -realize_virt_arrays (j_common_ptr cinfo) -/* Allocate the in-memory buffers for any unrealized virtual arrays */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - long space_per_minheight, maximum_space, avail_mem; - long minheights, max_minheights; - jvirt_sarray_ptr sptr; - jvirt_barray_ptr bptr; - - /* Compute the minimum space needed (maxaccess rows in each buffer) - * and the maximum space needed (full image height in each buffer). - * These may be of use to the system-dependent jpeg_mem_available routine. - */ - space_per_minheight = 0; - maximum_space = 0; - for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { - if (sptr->mem_buffer == NULL) { /* if not realized yet */ - space_per_minheight += (long) sptr->maxaccess * - (long) sptr->samplesperrow * SIZEOF(JSAMPLE); - maximum_space += (long) sptr->rows_in_array * - (long) sptr->samplesperrow * SIZEOF(JSAMPLE); - } - } - for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { - if (bptr->mem_buffer == NULL) { /* if not realized yet */ - space_per_minheight += (long) bptr->maxaccess * - (long) bptr->blocksperrow * SIZEOF(JBLOCK); - maximum_space += (long) bptr->rows_in_array * - (long) bptr->blocksperrow * SIZEOF(JBLOCK); - } - } - - if (space_per_minheight <= 0) - return; /* no unrealized arrays, no work */ - - /* Determine amount of memory to actually use; this is system-dependent. */ - avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space, - mem->total_space_allocated); - - /* If the maximum space needed is available, make all the buffers full - * height; otherwise parcel it out with the same number of minheights - * in each buffer. - */ - if (avail_mem >= maximum_space) - max_minheights = 1000000000L; - else { - max_minheights = avail_mem / space_per_minheight; - /* If there doesn't seem to be enough space, try to get the minimum - * anyway. This allows a "stub" implementation of jpeg_mem_available(). - */ - if (max_minheights <= 0) - max_minheights = 1; - } - - /* Allocate the in-memory buffers and initialize backing store as needed. */ - - for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { - if (sptr->mem_buffer == NULL) { /* if not realized yet */ - minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L; - if (minheights <= max_minheights) { - /* This buffer fits in memory */ - sptr->rows_in_mem = sptr->rows_in_array; - } else { - /* It doesn't fit in memory, create backing store. */ - sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess); - jpeg_open_backing_store(cinfo, & sptr->b_s_info, - (long) sptr->rows_in_array * - (long) sptr->samplesperrow * - (long) SIZEOF(JSAMPLE)); - sptr->b_s_open = TRUE; - } - sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE, - sptr->samplesperrow, sptr->rows_in_mem); - sptr->rowsperchunk = mem->last_rowsperchunk; - sptr->cur_start_row = 0; - sptr->first_undef_row = 0; - sptr->dirty = FALSE; - } - } - - for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { - if (bptr->mem_buffer == NULL) { /* if not realized yet */ - minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L; - if (minheights <= max_minheights) { - /* This buffer fits in memory */ - bptr->rows_in_mem = bptr->rows_in_array; - } else { - /* It doesn't fit in memory, create backing store. */ - bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess); - jpeg_open_backing_store(cinfo, & bptr->b_s_info, - (long) bptr->rows_in_array * - (long) bptr->blocksperrow * - (long) SIZEOF(JBLOCK)); - bptr->b_s_open = TRUE; - } - bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE, - bptr->blocksperrow, bptr->rows_in_mem); - bptr->rowsperchunk = mem->last_rowsperchunk; - bptr->cur_start_row = 0; - bptr->first_undef_row = 0; - bptr->dirty = FALSE; - } - } -} - - -LOCAL void -do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) -/* Do backing store read or write of a virtual sample array */ -{ - long bytesperrow, file_offset, byte_count, rows, thisrow, i; - - bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE); - file_offset = ptr->cur_start_row * bytesperrow; - /* Loop to read or write each allocation chunk in mem_buffer */ - for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { - /* One chunk, but check for short chunk at end of buffer */ - rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); - /* Transfer no more than is currently defined */ - thisrow = (long) ptr->cur_start_row + i; - rows = MIN(rows, (long) ptr->first_undef_row - thisrow); - /* Transfer no more than fits in file */ - rows = MIN(rows, (long) ptr->rows_in_array - thisrow); - if (rows <= 0) /* this chunk might be past end of file! */ - break; - byte_count = rows * bytesperrow; - if (writing) - (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); - else - (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); - file_offset += byte_count; - } -} - - -LOCAL void -do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing) -/* Do backing store read or write of a virtual coefficient-block array */ -{ - long bytesperrow, file_offset, byte_count, rows, thisrow, i; - - bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK); - file_offset = ptr->cur_start_row * bytesperrow; - /* Loop to read or write each allocation chunk in mem_buffer */ - for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { - /* One chunk, but check for short chunk at end of buffer */ - rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); - /* Transfer no more than is currently defined */ - thisrow = (long) ptr->cur_start_row + i; - rows = MIN(rows, (long) ptr->first_undef_row - thisrow); - /* Transfer no more than fits in file */ - rows = MIN(rows, (long) ptr->rows_in_array - thisrow); - if (rows <= 0) /* this chunk might be past end of file! */ - break; - byte_count = rows * bytesperrow; - if (writing) - (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); - else - (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); - file_offset += byte_count; - } -} - - -METHODDEF JSAMPARRAY -access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, - JDIMENSION start_row, JDIMENSION num_rows, - boolean writable) -/* Access the part of a virtual sample array starting at start_row */ -/* and extending for num_rows rows. writable is true if */ -/* caller intends to modify the accessed area. */ -{ - JDIMENSION end_row = start_row + num_rows; - JDIMENSION undef_row; - - /* debugging check */ - if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || - ptr->mem_buffer == NULL) - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - - /* Make the desired part of the virtual array accessible */ - if (start_row < ptr->cur_start_row || - end_row > ptr->cur_start_row+ptr->rows_in_mem) { - if (! ptr->b_s_open) - ERREXIT(cinfo, JERR_VIRTUAL_BUG); - /* Flush old buffer contents if necessary */ - if (ptr->dirty) { - do_sarray_io(cinfo, ptr, TRUE); - ptr->dirty = FALSE; - } - /* Decide what part of virtual array to access. - * Algorithm: if target address > current window, assume forward scan, - * load starting at target address. If target address < current window, - * assume backward scan, load so that target area is top of window. - * Note that when switching from forward write to forward read, will have - * start_row = 0, so the limiting case applies and we load from 0 anyway. - */ - if (start_row > ptr->cur_start_row) { - ptr->cur_start_row = start_row; - } else { - /* use long arithmetic here to avoid overflow & unsigned problems */ - long ltemp; - - ltemp = (long) end_row - (long) ptr->rows_in_mem; - if (ltemp < 0) - ltemp = 0; /* don't fall off front end of file */ - ptr->cur_start_row = (JDIMENSION) ltemp; - } - /* Read in the selected part of the array. - * During the initial write pass, we will do no actual read - * because the selected part is all undefined. - */ - do_sarray_io(cinfo, ptr, FALSE); - } - /* Ensure the accessed part of the array is defined; prezero if needed. - * To improve locality of access, we only prezero the part of the array - * that the caller is about to access, not the entire in-memory array. - */ - if (ptr->first_undef_row < end_row) { - if (ptr->first_undef_row < start_row) { - if (writable) /* writer skipped over a section of array */ - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - undef_row = start_row; /* but reader is allowed to read ahead */ - } else { - undef_row = ptr->first_undef_row; - } - if (writable) - ptr->first_undef_row = end_row; - if (ptr->pre_zero) { - size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE); - undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ - end_row -= ptr->cur_start_row; - while (undef_row < end_row) { - jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); - undef_row++; - } - } else { - if (! writable) /* reader looking at undefined data */ - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - } - } - /* Flag the buffer dirty if caller will write in it */ - if (writable) - ptr->dirty = TRUE; - /* Return address of proper part of the buffer */ - return ptr->mem_buffer + (start_row - ptr->cur_start_row); -} - - -METHODDEF JBLOCKARRAY -access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, - JDIMENSION start_row, JDIMENSION num_rows, - boolean writable) -/* Access the part of a virtual block array starting at start_row */ -/* and extending for num_rows rows. writable is true if */ -/* caller intends to modify the accessed area. */ -{ - JDIMENSION end_row = start_row + num_rows; - JDIMENSION undef_row; - - /* debugging check */ - if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || - ptr->mem_buffer == NULL) - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - - /* Make the desired part of the virtual array accessible */ - if (start_row < ptr->cur_start_row || - end_row > ptr->cur_start_row+ptr->rows_in_mem) { - if (! ptr->b_s_open) - ERREXIT(cinfo, JERR_VIRTUAL_BUG); - /* Flush old buffer contents if necessary */ - if (ptr->dirty) { - do_barray_io(cinfo, ptr, TRUE); - ptr->dirty = FALSE; - } - /* Decide what part of virtual array to access. - * Algorithm: if target address > current window, assume forward scan, - * load starting at target address. If target address < current window, - * assume backward scan, load so that target area is top of window. - * Note that when switching from forward write to forward read, will have - * start_row = 0, so the limiting case applies and we load from 0 anyway. - */ - if (start_row > ptr->cur_start_row) { - ptr->cur_start_row = start_row; - } else { - /* use long arithmetic here to avoid overflow & unsigned problems */ - long ltemp; - - ltemp = (long) end_row - (long) ptr->rows_in_mem; - if (ltemp < 0) - ltemp = 0; /* don't fall off front end of file */ - ptr->cur_start_row = (JDIMENSION) ltemp; - } - /* Read in the selected part of the array. - * During the initial write pass, we will do no actual read - * because the selected part is all undefined. - */ - do_barray_io(cinfo, ptr, FALSE); - } - /* Ensure the accessed part of the array is defined; prezero if needed. - * To improve locality of access, we only prezero the part of the array - * that the caller is about to access, not the entire in-memory array. - */ - if (ptr->first_undef_row < end_row) { - if (ptr->first_undef_row < start_row) { - if (writable) /* writer skipped over a section of array */ - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - undef_row = start_row; /* but reader is allowed to read ahead */ - } else { - undef_row = ptr->first_undef_row; - } - if (writable) - ptr->first_undef_row = end_row; - if (ptr->pre_zero) { - size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK); - undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ - end_row -= ptr->cur_start_row; - while (undef_row < end_row) { - jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); - undef_row++; - } - } else { - if (! writable) /* reader looking at undefined data */ - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - } - } - /* Flag the buffer dirty if caller will write in it */ - if (writable) - ptr->dirty = TRUE; - /* Return address of proper part of the buffer */ - return ptr->mem_buffer + (start_row - ptr->cur_start_row); -} - - -/* - * Release all objects belonging to a specified pool. - */ - -METHODDEF void -free_pool (j_common_ptr cinfo, int pool_id) -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - small_pool_ptr shdr_ptr; - large_pool_ptr lhdr_ptr; - size_t space_freed; - - if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - -#ifdef MEM_STATS - if (cinfo->err->trace_level > 1) - print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */ -#endif - - /* If freeing IMAGE pool, close any virtual arrays first */ - if (pool_id == JPOOL_IMAGE) { - jvirt_sarray_ptr sptr; - jvirt_barray_ptr bptr; - - for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { - if (sptr->b_s_open) { /* there may be no backing store */ - sptr->b_s_open = FALSE; /* prevent recursive close if error */ - (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info); - } - } - mem->virt_sarray_list = NULL; - for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { - if (bptr->b_s_open) { /* there may be no backing store */ - bptr->b_s_open = FALSE; /* prevent recursive close if error */ - (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info); - } - } - mem->virt_barray_list = NULL; - } - - /* Release large objects */ - lhdr_ptr = mem->large_list[pool_id]; - mem->large_list[pool_id] = NULL; - - while (lhdr_ptr != NULL) { - large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next; - space_freed = lhdr_ptr->hdr.bytes_used + - lhdr_ptr->hdr.bytes_left + - SIZEOF(large_pool_hdr); - jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed); - mem->total_space_allocated -= space_freed; - lhdr_ptr = next_lhdr_ptr; - } - - /* Release small objects */ - shdr_ptr = mem->small_list[pool_id]; - mem->small_list[pool_id] = NULL; - - while (shdr_ptr != NULL) { - small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next; - space_freed = shdr_ptr->hdr.bytes_used + - shdr_ptr->hdr.bytes_left + - SIZEOF(small_pool_hdr); - jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed); - mem->total_space_allocated -= space_freed; - shdr_ptr = next_shdr_ptr; - } -} - - -/* - * Close up shop entirely. - * Note that this cannot be called unless cinfo->mem is non-NULL. - */ - -METHODDEF void -self_destruct (j_common_ptr cinfo) -{ - int pool; - - /* Close all backing store, release all memory. - * Releasing pools in reverse order might help avoid fragmentation - * with some (brain-damaged) malloc libraries. - */ - for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { - free_pool(cinfo, pool); - } - - /* Release the memory manager control block too. */ - jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr)); - cinfo->mem = NULL; /* ensures I will be called only once */ - - jpeg_mem_term(cinfo); /* system-dependent cleanup */ -} - - -/* - * Memory manager initialization. - * When this is called, only the error manager pointer is valid in cinfo! - */ - -GLOBAL void -jinit_memory_mgr (j_common_ptr cinfo) -{ - my_mem_ptr mem; - long max_to_use; - int pool; - size_t test_mac; - - cinfo->mem = NULL; /* for safety if init fails */ - - /* Check for configuration errors. - * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably - * doesn't reflect any real hardware alignment requirement. - * The test is a little tricky: for X>0, X and X-1 have no one-bits - * in common if and only if X is a power of 2, ie has only one one-bit. - * Some compilers may give an "unreachable code" warning here; ignore it. - */ - if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0) - ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE); - /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be - * a multiple of SIZEOF(ALIGN_TYPE). - * Again, an "unreachable code" warning may be ignored here. - * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK. - */ - test_mac = (size_t) MAX_ALLOC_CHUNK; - if ((long) test_mac != MAX_ALLOC_CHUNK || - (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0) - ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); - - max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */ - - /* Attempt to allocate memory manager's control block */ - mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr)); - - if (mem == NULL) { - jpeg_mem_term(cinfo); /* system-dependent cleanup */ - ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0); - } - - /* OK, fill in the method pointers */ - mem->pub.alloc_small = alloc_small; - mem->pub.alloc_large = alloc_large; - mem->pub.alloc_sarray = alloc_sarray; - mem->pub.alloc_barray = alloc_barray; - mem->pub.request_virt_sarray = request_virt_sarray; - mem->pub.request_virt_barray = request_virt_barray; - mem->pub.realize_virt_arrays = realize_virt_arrays; - mem->pub.access_virt_sarray = access_virt_sarray; - mem->pub.access_virt_barray = access_virt_barray; - mem->pub.free_pool = free_pool; - mem->pub.self_destruct = self_destruct; - - /* Initialize working state */ - mem->pub.max_memory_to_use = max_to_use; - - for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { - mem->small_list[pool] = NULL; - mem->large_list[pool] = NULL; - } - mem->virt_sarray_list = NULL; - mem->virt_barray_list = NULL; - - mem->total_space_allocated = SIZEOF(my_memory_mgr); - - /* Declare ourselves open for business */ - cinfo->mem = & mem->pub; - - /* Check for an environment variable JPEGMEM; if found, override the - * default max_memory setting from jpeg_mem_init. Note that the - * surrounding application may again override this value. - * If your system doesn't support getenv(), define NO_GETENV to disable - * this feature. - */ -#ifndef NO_GETENV - { char * memenv; - - if ((memenv = getenv("JPEGMEM")) != NULL) { - char ch = 'x'; - - if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) { - if (ch == 'm' || ch == 'M') - max_to_use *= 1000L; - mem->pub.max_memory_to_use = max_to_use * 1000L; - } - } - } -#endif - -} diff --git a/libs/jpeg6/jmemnobs.cpp b/libs/jpeg6/jmemnobs.cpp deleted file mode 100644 index 9bafed5..0000000 --- a/libs/jpeg6/jmemnobs.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - * jmemnobs.c - * - * Copyright (C) 1992-1994, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file provides a really simple implementation of the system- - * dependent portion of the JPEG memory manager. This implementation - * assumes that no backing-store files are needed: all required space - * can be obtained from ri.Malloc(). - * This is very portable in the sense that it'll compile on almost anything, - * but you'd better have lots of main memory (or virtual memory) if you want - * to process big images. - * Note that the max_memory_to_use option is ignored by this implementation. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jmemsys.h" /* import the system-dependent declarations */ - -/* - * Memory allocation and ri.Freeing are controlled by the regular library - * routines ri.Malloc() and ri.Free(). - */ - -GLOBAL void * -jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) -{ - return (void *) malloc(sizeofobject); -} - -GLOBAL void -jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) -{ - free(object); -} - - -/* - * "Large" objects are treated the same as "small" ones. - * NB: although we include FAR keywords in the routine declarations, - * this file won't actually work in 80x86 small/medium model; at least, - * you probably won't be able to process useful-size images in only 64KB. - */ - -GLOBAL void FAR * -jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) -{ - return (void FAR *) malloc(sizeofobject); -} - -GLOBAL void -jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) -{ - free(object); -} - - -/* - * This routine computes the total memory space available for allocation. - * Here we always say, "we got all you want bud!" - */ - -GLOBAL long -jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, - long max_bytes_needed, long already_allocated) -{ - return max_bytes_needed; -} - - -/* - * Backing store (temporary file) management. - * Since jpeg_mem_available always promised the moon, - * this should never be called and we can just error out. - */ - -GLOBAL void -jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, - long total_bytes_needed) -{ - ERREXIT(cinfo, JERR_NO_BACKING_STORE); -} - - -/* - * These routines take care of any system-dependent initialization and - * cleanup required. Here, there isn't any. - */ - -GLOBAL long -jpeg_mem_init (j_common_ptr cinfo) -{ - return 0; /* just set max_memory_to_use to 0 */ -} - -GLOBAL void -jpeg_mem_term (j_common_ptr cinfo) -{ - /* no work */ -} diff --git a/libs/jpeg6/jmemsys.h b/libs/jpeg6/jmemsys.h deleted file mode 100644 index 033d29a..0000000 --- a/libs/jpeg6/jmemsys.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - * jmemsys.h - * - * Copyright (C) 1992-1994, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This include file defines the interface between the system-independent - * and system-dependent portions of the JPEG memory manager. No other - * modules need include it. (The system-independent portion is jmemmgr.c; - * there are several different versions of the system-dependent portion.) - * - * This file works as-is for the system-dependent memory managers supplied - * in the IJG distribution. You may need to modify it if you write a - * custom memory manager. If system-dependent changes are needed in - * this file, the best method is to #ifdef them based on a configuration - * symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR. - */ - - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_get_small jGetSmall -#define jpeg_free_small jFreeSmall -#define jpeg_get_large jGetLarge -#define jpeg_free_large jFreeLarge -#define jpeg_mem_available jMemAvail -#define jpeg_open_backing_store jOpenBackStore -#define jpeg_mem_init jMemInit -#define jpeg_mem_term jMemTerm -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* - * These two functions are used to allocate and release small chunks of - * memory. (Typically the total amount requested through jpeg_get_small is - * no more than 20K or so; this will be requested in chunks of a few K each.) - * Behavior should be the same as for the standard library functions malloc - * and free; in particular, jpeg_get_small must return NULL on failure. - * On most systems, these ARE malloc and free. jpeg_free_small is passed the - * size of the object being freed, just in case it's needed. - * On an 80x86 machine using small-data memory model, these manage near heap. - */ - -EXTERN void * jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject)); -EXTERN void jpeg_free_small JPP((j_common_ptr cinfo, void * object, - size_t sizeofobject)); - -/* - * These two functions are used to allocate and release large chunks of - * memory (up to the total free space designated by jpeg_mem_available). - * The interface is the same as above, except that on an 80x86 machine, - * far pointers are used. On most other machines these are identical to - * the jpeg_get/free_small routines; but we keep them separate anyway, - * in case a different allocation strategy is desirable for large chunks. - */ - -EXTERN void FAR * jpeg_get_large JPP((j_common_ptr cinfo,size_t sizeofobject)); -EXTERN void jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, - size_t sizeofobject)); - -/* - * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may - * be requested in a single call to jpeg_get_large (and jpeg_get_small for that - * matter, but that case should never come into play). This macro is needed - * to model the 64Kb-segment-size limit of far addressing on 80x86 machines. - * On those machines, we expect that jconfig.h will provide a proper value. - * On machines with 32-bit flat address spaces, any large constant may be used. - * - * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type - * size_t and will be a multiple of sizeof(align_type). - */ - -#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */ -#define MAX_ALLOC_CHUNK 1000000000L -#endif - -/* - * This routine computes the total space still available for allocation by - * jpeg_get_large. If more space than this is needed, backing store will be - * used. NOTE: any memory already allocated must not be counted. - * - * There is a minimum space requirement, corresponding to the minimum - * feasible buffer sizes; jmemmgr.c will request that much space even if - * jpeg_mem_available returns zero. The maximum space needed, enough to hold - * all working storage in memory, is also passed in case it is useful. - * Finally, the total space already allocated is passed. If no better - * method is available, cinfo->mem->max_memory_to_use - already_allocated - * is often a suitable calculation. - * - * It is OK for jpeg_mem_available to underestimate the space available - * (that'll just lead to more backing-store access than is really necessary). - * However, an overestimate will lead to failure. Hence it's wise to subtract - * a slop factor from the true available space. 5% should be enough. - * - * On machines with lots of virtual memory, any large constant may be returned. - * Conversely, zero may be returned to always use the minimum amount of memory. - */ - -EXTERN long jpeg_mem_available JPP((j_common_ptr cinfo, - long min_bytes_needed, - long max_bytes_needed, - long already_allocated)); - - -/* - * This structure holds whatever state is needed to access a single - * backing-store object. The read/write/close method pointers are called - * by jmemmgr.c to manipulate the backing-store object; all other fields - * are private to the system-dependent backing store routines. - */ - -#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ - -#ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */ - -typedef unsigned short XMSH; /* type of extended-memory handles */ -typedef unsigned short EMSH; /* type of expanded-memory handles */ - -typedef union { - short file_handle; /* DOS file handle if it's a temp file */ - XMSH xms_handle; /* handle if it's a chunk of XMS */ - EMSH ems_handle; /* handle if it's a chunk of EMS */ -} handle_union; - -#endif /* USE_MSDOS_MEMMGR */ - -typedef struct backing_store_struct * backing_store_ptr; - -typedef struct backing_store_struct { - /* Methods for reading/writing/closing this backing-store object */ - JMETHOD(void, read_backing_store, (j_common_ptr cinfo, - backing_store_ptr info, - void FAR * buffer_address, - long file_offset, long byte_count)); - JMETHOD(void, write_backing_store, (j_common_ptr cinfo, - backing_store_ptr info, - void FAR * buffer_address, - long file_offset, long byte_count)); - JMETHOD(void, close_backing_store, (j_common_ptr cinfo, - backing_store_ptr info)); - - /* Private fields for system-dependent backing-store management */ -#ifdef USE_MSDOS_MEMMGR - /* For the MS-DOS manager (jmemdos.c), we need: */ - handle_union handle; /* reference to backing-store storage object */ - char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ -#else - /* For a typical implementation with temp files, we need: */ - FILE * temp_file; /* stdio reference to temp file */ - char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */ -#endif -} backing_store_info; - -/* - * Initial opening of a backing-store object. This must fill in the - * read/write/close pointers in the object. The read/write routines - * may take an error exit if the specified maximum file size is exceeded. - * (If jpeg_mem_available always returns a large value, this routine can - * just take an error exit.) - */ - -EXTERN void jpeg_open_backing_store JPP((j_common_ptr cinfo, - backing_store_ptr info, - long total_bytes_needed)); - - -/* - * These routines take care of any system-dependent initialization and - * cleanup required. jpeg_mem_init will be called before anything is - * allocated (and, therefore, nothing in cinfo is of use except the error - * manager pointer). It should return a suitable default value for - * max_memory_to_use; this may subsequently be overridden by the surrounding - * application. (Note that max_memory_to_use is only important if - * jpeg_mem_available chooses to consult it ... no one else will.) - * jpeg_mem_term may assume that all requested memory has been freed and that - * all opened backing-store objects have been closed. - */ - -EXTERN long jpeg_mem_init JPP((j_common_ptr cinfo)); -EXTERN void jpeg_mem_term JPP((j_common_ptr cinfo)); diff --git a/libs/jpeg6/jmorecfg.h b/libs/jpeg6/jmorecfg.h deleted file mode 100644 index 7e83fec..0000000 --- a/libs/jpeg6/jmorecfg.h +++ /dev/null @@ -1,346 +0,0 @@ -/* - * jmorecfg.h - * - * Copyright (C) 1991-1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains additional configuration options that customize the - * JPEG software for special applications or support machine-dependent - * optimizations. Most users will not need to touch this file. - */ - - -/* - * Define BITS_IN_JSAMPLE as either - * 8 for 8-bit sample values (the usual setting) - * 12 for 12-bit sample values - * Only 8 and 12 are legal data precisions for lossy JPEG according to the - * JPEG standard, and the IJG code does not support anything else! - * We do not support run-time selection of data precision, sorry. - */ - -#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ - - -/* - * Maximum number of components (color channels) allowed in JPEG image. - * To meet the letter of the JPEG spec, set this to 255. However, darn - * few applications need more than 4 channels (maybe 5 for CMYK + alpha - * mask). We recommend 10 as a reasonable compromise; use 4 if you are - * really short on memory. (Each allowed component costs a hundred or so - * bytes of storage, whether actually used in an image or not.) - */ - -#define MAX_COMPONENTS 10 /* maximum number of image components */ - - -/* - * Basic data types. - * You may need to change these if you have a machine with unusual data - * type sizes; for example, "char" not 8 bits, "short" not 16 bits, - * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, - * but it had better be at least 16. - */ - -/* Representation of a single sample (pixel element value). - * We frequently allocate large arrays of these, so it's important to keep - * them small. But if you have memory to burn and access to char or short - * arrays is very slow on your hardware, you might want to change these. - */ - -#if BITS_IN_JSAMPLE == 8 -/* JSAMPLE should be the smallest type that will hold the values 0..255. - * You can use a signed char by having GETJSAMPLE mask it with 0xFF. - */ - -#ifdef HAVE_UNSIGNED_CHAR - -typedef unsigned char JSAMPLE; -#define GETJSAMPLE(value) ((int) (value)) - -#else /* not HAVE_UNSIGNED_CHAR */ - -typedef char JSAMPLE; -#ifdef CHAR_IS_UNSIGNED -#define GETJSAMPLE(value) ((int) (value)) -#else -#define GETJSAMPLE(value) ((int) (value) & 0xFF) -#endif /* CHAR_IS_UNSIGNED */ - -#endif /* HAVE_UNSIGNED_CHAR */ - -#define MAXJSAMPLE 255 -#define CENTERJSAMPLE 128 - -#endif /* BITS_IN_JSAMPLE == 8 */ - - -#if BITS_IN_JSAMPLE == 12 -/* JSAMPLE should be the smallest type that will hold the values 0..4095. - * On nearly all machines "short" will do nicely. - */ - -typedef short JSAMPLE; -#define GETJSAMPLE(value) ((int) (value)) - -#define MAXJSAMPLE 4095 -#define CENTERJSAMPLE 2048 - -#endif /* BITS_IN_JSAMPLE == 12 */ - - -/* Representation of a DCT frequency coefficient. - * This should be a signed value of at least 16 bits; "short" is usually OK. - * Again, we allocate large arrays of these, but you can change to int - * if you have memory to burn and "short" is really slow. - */ - -typedef short JCOEF; - - -/* Compressed datastreams are represented as arrays of JOCTET. - * These must be EXACTLY 8 bits wide, at least once they are written to - * external storage. Note that when using the stdio data source/destination - * managers, this is also the data type passed to fread/fwrite. - */ - -#ifdef HAVE_UNSIGNED_CHAR - -typedef unsigned char JOCTET; -#define GETJOCTET(value) (value) - -#else /* not HAVE_UNSIGNED_CHAR */ - -typedef char JOCTET; -#ifdef CHAR_IS_UNSIGNED -#define GETJOCTET(value) (value) -#else -#define GETJOCTET(value) ((value) & 0xFF) -#endif /* CHAR_IS_UNSIGNED */ - -#endif /* HAVE_UNSIGNED_CHAR */ - - -/* These typedefs are used for various table entries and so forth. - * They must be at least as wide as specified; but making them too big - * won't cost a huge amount of memory, so we don't provide special - * extraction code like we did for JSAMPLE. (In other words, these - * typedefs live at a different point on the speed/space tradeoff curve.) - */ - -/* UINT8 must hold at least the values 0..255. */ - -#ifdef HAVE_UNSIGNED_CHAR -typedef unsigned char UINT8; -#else /* not HAVE_UNSIGNED_CHAR */ -#ifdef CHAR_IS_UNSIGNED -typedef char UINT8; -#else /* not CHAR_IS_UNSIGNED */ -typedef short UINT8; -#endif /* CHAR_IS_UNSIGNED */ -#endif /* HAVE_UNSIGNED_CHAR */ - -/* UINT16 must hold at least the values 0..65535. */ - -#ifdef HAVE_UNSIGNED_SHORT -typedef unsigned short UINT16; -#else /* not HAVE_UNSIGNED_SHORT */ -typedef unsigned int UINT16; -#endif /* HAVE_UNSIGNED_SHORT */ - -/* INT16 must hold at least the values -32768..32767. */ - -#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ -typedef short INT16; -#endif - -/* INT32 must hold at least signed 32-bit values. */ - -//#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ -//typedef long INT32; -//#endif - -/* Datatype used for image dimensions. The JPEG standard only supports - * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore - * "unsigned int" is sufficient on all machines. However, if you need to - * handle larger images and you don't mind deviating from the spec, you - * can change this datatype. - */ - -typedef unsigned int JDIMENSION; - -#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ - - -/* These defines are used in all function definitions and extern declarations. - * You could modify them if you need to change function linkage conventions. - * Another application is to make all functions global for use with debuggers - * or code profilers that require it. - */ - -#define METHODDEF static /* a function called through method pointers */ -#define LOCAL static /* a function used only in its module */ -#define GLOBAL /* a function referenced thru EXTERNs */ -#define EXTERN extern /* a reference to a GLOBAL function */ - - -/* Here is the pseudo-keyword for declaring pointers that must be "far" - * on 80x86 machines. Most of the specialized coding for 80x86 is handled - * by just saying "FAR *" where such a pointer is needed. In a few places - * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. - */ - -#ifdef NEED_FAR_POINTERS -#undef FAR -#define FAR far -#else -#undef FAR -#define FAR -#endif - - -/* - * On a few systems, type boolean and/or its values FALSE, TRUE may appear - * in standard header files. Or you may have conflicts with application- - * specific header files that you want to include together with these files. - * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. - */ - -//#ifndef HAVE_BOOLEAN -//typedef int boolean; -//#endif -#ifndef FALSE /* in case these macros already exist */ -#define FALSE 0 /* values of boolean */ -#endif -#ifndef TRUE -#define TRUE 1 -#endif - - -/* - * The remaining options affect code selection within the JPEG library, - * but they don't need to be visible to most applications using the library. - * To minimize application namespace pollution, the symbols won't be - * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. - */ - -#ifdef JPEG_INTERNALS -#define JPEG_INTERNAL_OPTIONS -#endif - -#ifdef JPEG_INTERNAL_OPTIONS - - -/* - * These defines indicate whether to include various optional functions. - * Undefining some of these symbols will produce a smaller but less capable - * library. Note that you can leave certain source files out of the - * compilation/linking process if you've #undef'd the corresponding symbols. - * (You may HAVE to do that if your compiler doesn't like null source files.) - */ - -/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ - -/* Capability options common to encoder and decoder: */ - -#undef DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ -#undef DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ -#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ - -/* Encoder capability options: */ - -#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ -#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ -#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ -#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ -/* Note: if you selected 12-bit data precision, it is dangerous to turn off - * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit - * precision, so jchuff.c normally uses entropy optimization to compute - * usable tables for higher precision. If you don't want to do optimization, - * you'll have to supply different default Huffman tables. - * The exact same statements apply for progressive JPEG: the default tables - * don't work for progressive mode. (This may get fixed, however.) - */ -#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ - -/* Decoder capability options: */ - -#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ -#undef D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ -#undef D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ -#undef BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ -#undef IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ -#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ -#undef UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ -#undef QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ -#undef QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ - -/* more capability options later, no doubt */ - - -/* - * Ordering of RGB data in scanlines passed to or from the application. - * If your application wants to deal with data in the order B,G,R, just - * change these macros. You can also deal with formats such as R,G,B,X - * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing - * the offsets will also change the order in which colormap data is organized. - * RESTRICTIONS: - * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. - * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not - * useful if you are using JPEG color spaces other than YCbCr or grayscale. - * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE - * is not 3 (they don't understand about dummy color components!). So you - * can't use color quantization if you change that value. - */ - -#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ -#define RGB_GREEN 1 /* Offset of Green */ -#define RGB_BLUE 2 /* Offset of Blue */ -#define RGB_PIXELSIZE 4 /* JSAMPLEs per RGB scanline element */ - - -/* Definitions for speed-related optimizations. */ - - -/* If your compiler supports inline functions, define INLINE - * as the inline keyword; otherwise define it as empty. - */ - -#ifndef INLINE -#ifdef __GNUC__ /* for instance, GNU C knows about inline */ -#define INLINE __inline__ -#endif -#ifndef INLINE -#define INLINE /* default is to define it as empty */ -#endif -#endif - - -/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying - * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER - * as short on such a machine. MULTIPLIER must be at least 16 bits wide. - */ - -#ifndef MULTIPLIER -#define MULTIPLIER int /* type for fastest integer multiply */ -#endif - - -/* FAST_FLOAT should be either float or double, whichever is done faster - * by your compiler. (Note that this type is only used in the floating point - * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) - * Typically, float is faster in ANSI C compilers, while double is faster in - * pre-ANSI compilers (because they insist on converting to double anyway). - * The code below therefore chooses float if we have ANSI-style prototypes. - */ - -#ifndef FAST_FLOAT -#ifdef HAVE_PROTOTYPES -#define FAST_FLOAT float -#else -#define FAST_FLOAT double -#endif -#endif - -#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/libs/jpeg6/jpeg6.vcproj b/libs/jpeg6/jpeg6.vcproj deleted file mode 100644 index ef6f2ab..0000000 --- a/libs/jpeg6/jpeg6.vcproj +++ /dev/null @@ -1,603 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="7.10" - Name="jpeg6" - SccProjectName=""$/source/q3radiant", FEFAAAAA" - SccLocalPath="..\..\q3radiant"> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <Configurations> - <Configuration - Name="Release|Win32" - OutputDirectory=".\Release" - IntermediateDirectory=".\Release" - ConfigurationType="4" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - InlineFunctionExpansion="1" - AdditionalIncludeDirectories=".." - PreprocessorDefinitions="WIN32;NDEBUG;_LIB" - StringPooling="TRUE" - RuntimeLibrary="0" - EnableFunctionLevelLinking="TRUE" - RuntimeTypeInfo="TRUE" - UsePrecompiledHeader="2" - PrecompiledHeaderFile=".\Release/jpeg6.pch" - AssemblerListingLocation=".\Release/" - ObjectFile=".\Release/" - ProgramDataBaseFileName=".\Release/" - WarningLevel="3" - SuppressStartupBanner="TRUE" - CompileAs="0"/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCLibrarianTool" - OutputFile="..\jpeg6.lib" - SuppressStartupBanner="TRUE"/> - <Tool - Name="VCMIDLTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="NDEBUG" - Culture="1033"/> - <Tool - Name="VCWebServiceProxyGeneratorTool"/> - <Tool - Name="VCXMLDataGeneratorTool"/> - <Tool - Name="VCManagedWrapperGeneratorTool"/> - <Tool - Name="VCAuxiliaryManagedWrapperGeneratorTool"/> - </Configuration> - <Configuration - Name="Debug|Win32" - OutputDirectory=".\Debug" - IntermediateDirectory=".\Debug" - ConfigurationType="4" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories=".." - PreprocessorDefinitions="WIN32;_DEBUG;_LIB" - BasicRuntimeChecks="3" - RuntimeLibrary="1" - RuntimeTypeInfo="TRUE" - UsePrecompiledHeader="2" - PrecompiledHeaderFile=".\Debug/jpeg6.pch" - AssemblerListingLocation=".\Debug/" - ObjectFile=".\Debug/" - ProgramDataBaseFileName=".\Debug/" - WarningLevel="3" - SuppressStartupBanner="TRUE" - DebugInformationFormat="4" - CompileAs="0"/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCLibrarianTool" - OutputFile="..\jpeg6d.lib" - SuppressStartupBanner="TRUE"/> - <Tool - Name="VCMIDLTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="_DEBUG" - Culture="1033"/> - <Tool - Name="VCWebServiceProxyGeneratorTool"/> - <Tool - Name="VCXMLDataGeneratorTool"/> - <Tool - Name="VCManagedWrapperGeneratorTool"/> - <Tool - Name="VCAuxiliaryManagedWrapperGeneratorTool"/> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="Source Files" - Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"> - <File - RelativePath="jcomapi.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jdapimin.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jdapistd.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jdatasrc.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jdcoefct.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jdcolor.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jddctmgr.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jdhuff.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jdinput.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jdmainct.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jdmarker.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jdmaster.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jdpostct.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jdsample.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jdtrans.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jerror.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jfdctflt.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jidctflt.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jmemmgr.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jmemnobs.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jpgload.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - <File - RelativePath="jutils.cpp"> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - </File> - </Filter> - <Filter - Name="Header Files" - Filter="h;hpp;hxx;hm;inl"> - <File - RelativePath="jchuff.h"> - </File> - <File - RelativePath="jconfig.h"> - </File> - <File - RelativePath="jdct.h"> - </File> - <File - RelativePath="jdhuff.h"> - </File> - <File - RelativePath="jerror.h"> - </File> - <File - RelativePath="jinclude.h"> - </File> - <File - RelativePath="jmemsys.h"> - </File> - <File - RelativePath="jmorecfg.h"> - </File> - <File - RelativePath="jpegint.h"> - </File> - <File - RelativePath="jversion.h"> - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/libs/jpeg6/jpegint.h b/libs/jpeg6/jpegint.h deleted file mode 100644 index ab5bee2..0000000 --- a/libs/jpeg6/jpegint.h +++ /dev/null @@ -1,388 +0,0 @@ -/* - * jpegint.h - * - * Copyright (C) 1991-1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file provides common declarations for the various JPEG modules. - * These declarations are considered internal to the JPEG library; most - * applications using the library shouldn't need to include this file. - */ - - -/* Declarations for both compression & decompression */ - -typedef enum { /* Operating modes for buffer controllers */ - JBUF_PASS_THRU, /* Plain stripwise operation */ - /* Remaining modes require a full-image buffer to have been created */ - JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ - JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ - JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ -} J_BUF_MODE; - -/* Values of global_state field (jdapi.c has some dependencies on ordering!) */ -#define CSTATE_START 100 /* after create_compress */ -#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */ -#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */ -#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */ -#define DSTATE_START 200 /* after create_decompress */ -#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */ -#define DSTATE_READY 202 /* found SOS, ready for start_decompress */ -#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/ -#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */ -#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */ -#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */ -#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */ -#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */ -#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */ -#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */ - - -/* Declarations for compression modules */ - -/* Master control module */ -struct jpeg_comp_master { - JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo)); - JMETHOD(void, pass_startup, (j_compress_ptr cinfo)); - JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); - - /* State variables made visible to other modules */ - boolean call_pass_startup; /* True if pass_startup must be called */ - boolean is_last_pass; /* True during last pass */ -}; - -/* Main buffer control (downsampled-data buffer) */ -struct jpeg_c_main_controller { - JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(void, process_data, (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail)); -}; - -/* Compression preprocessing (downsampling input buffer control) */ -struct jpeg_c_prep_controller { - JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, - JSAMPARRAY input_buf, - JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail, - JSAMPIMAGE output_buf, - JDIMENSION *out_row_group_ctr, - JDIMENSION out_row_groups_avail)); -}; - -/* Coefficient buffer control */ -struct jpeg_c_coef_controller { - JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(boolean, compress_data, (j_compress_ptr cinfo, - JSAMPIMAGE input_buf)); -}; - -/* Colorspace conversion */ -struct jpeg_color_converter { - JMETHOD(void, start_pass, (j_compress_ptr cinfo)); - JMETHOD(void, color_convert, (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows)); -}; - -/* Downsampling */ -struct jpeg_downsampler { - JMETHOD(void, start_pass, (j_compress_ptr cinfo)); - JMETHOD(void, downsample, (j_compress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_index, - JSAMPIMAGE output_buf, - JDIMENSION out_row_group_index)); - - boolean need_context_rows; /* TRUE if need rows above & below */ -}; - -/* Forward DCT (also controls coefficient quantization) */ -struct jpeg_forward_dct { - JMETHOD(void, start_pass, (j_compress_ptr cinfo)); - /* perhaps this should be an array??? */ - JMETHOD(void, forward_DCT, (j_compress_ptr cinfo, - jpeg_component_info * compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, - JDIMENSION start_row, JDIMENSION start_col, - JDIMENSION num_blocks)); -}; - -/* Entropy encoding */ -struct jpeg_entropy_encoder { - JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics)); - JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data)); - JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); -}; - -/* Marker writing */ -struct jpeg_marker_writer { - /* write_any_marker is exported for use by applications */ - /* Probably only COM and APPn markers should be written */ - JMETHOD(void, write_any_marker, (j_compress_ptr cinfo, int marker, - const JOCTET *dataptr, unsigned int datalen)); - JMETHOD(void, write_file_header, (j_compress_ptr cinfo)); - JMETHOD(void, write_frame_header, (j_compress_ptr cinfo)); - JMETHOD(void, write_scan_header, (j_compress_ptr cinfo)); - JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo)); - JMETHOD(void, write_tables_only, (j_compress_ptr cinfo)); -}; - - -/* Declarations for decompression modules */ - -/* Master control module */ -struct jpeg_decomp_master { - JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo)); - - /* State variables made visible to other modules */ - boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */ -}; - -/* Input control module */ -struct jpeg_input_controller { - JMETHOD(int, consume_input, (j_decompress_ptr cinfo)); - JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo)); - JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo)); - - /* State variables made visible to other modules */ - boolean has_multiple_scans; /* True if file has multiple scans */ - boolean eoi_reached; /* True when EOI has been consumed */ -}; - -/* Main buffer control (downsampled-data buffer) */ -struct jpeg_d_main_controller { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(void, process_data, (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -}; - -/* Coefficient buffer control */ -struct jpeg_d_coef_controller { - JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); - JMETHOD(int, consume_data, (j_decompress_ptr cinfo)); - JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo)); - JMETHOD(int, decompress_data, (j_decompress_ptr cinfo, - JSAMPIMAGE output_buf)); - /* Pointer to array of coefficient virtual arrays, or NULL if none */ - jvirt_barray_ptr *coef_arrays; -}; - -/* Decompression postprocessing (color quantization buffer control) */ -struct jpeg_d_post_controller { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, - JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -}; - -/* Marker reading & parsing */ -struct jpeg_marker_reader { - JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo)); - /* Read markers until SOS or EOI. - * Returns same codes as are defined for jpeg_consume_input: - * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. - */ - JMETHOD(int, read_markers, (j_decompress_ptr cinfo)); - /* Read a restart marker --- exported for use by entropy decoder only */ - jpeg_marker_parser_method read_restart_marker; - /* Application-overridable marker processing methods */ - jpeg_marker_parser_method process_COM; - jpeg_marker_parser_method process_APPn[16]; - - /* State of marker reader --- nominally internal, but applications - * supplying COM or APPn handlers might like to know the state. - */ - boolean saw_SOI; /* found SOI? */ - boolean saw_SOF; /* found SOF? */ - int next_restart_num; /* next restart number expected (0-7) */ - unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */ -}; - -/* Entropy decoding */ -struct jpeg_entropy_decoder { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); -}; - -/* Inverse DCT (also performs dequantization) */ -typedef JMETHOD(void, inverse_DCT_method_ptr, - (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col)); - -struct jpeg_inverse_dct { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - /* It is useful to allow each component to have a separate IDCT method. */ - inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; -}; - -/* Upsampling (note that upsampler must also call color converter) */ -struct jpeg_upsampler { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, upsample, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, - JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); - - boolean need_context_rows; /* TRUE if need rows above & below */ -}; - -/* Colorspace conversion */ -struct jpeg_color_deconverter { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, color_convert, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows)); -}; - -/* Color quantization or color precision reduction */ -struct jpeg_color_quantizer { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan)); - JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPARRAY output_buf, - int num_rows)); - JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, new_color_map, (j_decompress_ptr cinfo)); -}; - - -/* Miscellaneous useful macros */ - -#undef MAX -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#undef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) - - -/* We assume that right shift corresponds to signed division by 2 with - * rounding towards minus infinity. This is correct for typical "arithmetic - * shift" instructions that shift in copies of the sign bit. But some - * C compilers implement >> with an unsigned shift. For these machines you - * must define RIGHT_SHIFT_IS_UNSIGNED. - * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity. - * It is only applied with constant shift counts. SHIFT_TEMPS must be - * included in the variables of any routine using RIGHT_SHIFT. - */ - -#ifdef RIGHT_SHIFT_IS_UNSIGNED -#define SHIFT_TEMPS INT32 shift_temp; -#define RIGHT_SHIFT(x,shft) \ - ((shift_temp = (x)) < 0 ? \ - (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \ - (shift_temp >> (shft))) -#else -#define SHIFT_TEMPS -#define RIGHT_SHIFT(x,shft) ((x) >> (shft)) -#endif - - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jinit_compress_master jICompress -#define jinit_c_master_control jICMaster -#define jinit_c_main_controller jICMainC -#define jinit_c_prep_controller jICPrepC -#define jinit_c_coef_controller jICCoefC -#define jinit_color_converter jICColor -#define jinit_downsampler jIDownsampler -#define jinit_forward_dct jIFDCT -#define jinit_huff_encoder jIHEncoder -#define jinit_phuff_encoder jIPHEncoder -#define jinit_marker_writer jIMWriter -#define jinit_master_decompress jIDMaster -#define jinit_d_main_controller jIDMainC -#define jinit_d_coef_controller jIDCoefC -#define jinit_d_post_controller jIDPostC -#define jinit_input_controller jIInCtlr -#define jinit_marker_reader jIMReader -#define jinit_huff_decoder jIHDecoder -#define jinit_phuff_decoder jIPHDecoder -#define jinit_inverse_dct jIIDCT -#define jinit_upsampler jIUpsampler -#define jinit_color_deconverter jIDColor -#define jinit_1pass_quantizer jI1Quant -#define jinit_2pass_quantizer jI2Quant -#define jinit_merged_upsampler jIMUpsampler -#define jinit_memory_mgr jIMemMgr -#define jdiv_round_up jDivRound -#define jround_up jRound -#define jcopy_sample_rows jCopySamples -#define jcopy_block_row jCopyBlocks -#define jzero_far jZeroFar -#define jpeg_zigzag_order jZIGTable -#define jpeg_natural_order jZAGTable -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* Compression module initialization routines */ -EXTERN void jinit_compress_master JPP((j_compress_ptr cinfo)); -EXTERN void jinit_c_master_control JPP((j_compress_ptr cinfo, - boolean transcode_only)); -EXTERN void jinit_c_main_controller JPP((j_compress_ptr cinfo, - boolean need_full_buffer)); -EXTERN void jinit_c_prep_controller JPP((j_compress_ptr cinfo, - boolean need_full_buffer)); -EXTERN void jinit_c_coef_controller JPP((j_compress_ptr cinfo, - boolean need_full_buffer)); -EXTERN void jinit_color_converter JPP((j_compress_ptr cinfo)); -EXTERN void jinit_downsampler JPP((j_compress_ptr cinfo)); -EXTERN void jinit_forward_dct JPP((j_compress_ptr cinfo)); -EXTERN void jinit_huff_encoder JPP((j_compress_ptr cinfo)); -EXTERN void jinit_phuff_encoder JPP((j_compress_ptr cinfo)); -EXTERN void jinit_marker_writer JPP((j_compress_ptr cinfo)); -/* Decompression module initialization routines */ -EXTERN void jinit_master_decompress JPP((j_decompress_ptr cinfo)); -EXTERN void jinit_d_main_controller JPP((j_decompress_ptr cinfo, - boolean need_full_buffer)); -EXTERN void jinit_d_coef_controller JPP((j_decompress_ptr cinfo, - boolean need_full_buffer)); -EXTERN void jinit_d_post_controller JPP((j_decompress_ptr cinfo, - boolean need_full_buffer)); -EXTERN void jinit_input_controller JPP((j_decompress_ptr cinfo)); -EXTERN void jinit_marker_reader JPP((j_decompress_ptr cinfo)); -EXTERN void jinit_huff_decoder JPP((j_decompress_ptr cinfo)); -EXTERN void jinit_phuff_decoder JPP((j_decompress_ptr cinfo)); -EXTERN void jinit_inverse_dct JPP((j_decompress_ptr cinfo)); -EXTERN void jinit_upsampler JPP((j_decompress_ptr cinfo)); -EXTERN void jinit_color_deconverter JPP((j_decompress_ptr cinfo)); -EXTERN void jinit_1pass_quantizer JPP((j_decompress_ptr cinfo)); -EXTERN void jinit_2pass_quantizer JPP((j_decompress_ptr cinfo)); -EXTERN void jinit_merged_upsampler JPP((j_decompress_ptr cinfo)); -/* Memory manager initialization */ -EXTERN void jinit_memory_mgr JPP((j_common_ptr cinfo)); - -/* Utility routines in jutils.c */ -EXTERN long jdiv_round_up JPP((long a, long b)); -EXTERN long jround_up JPP((long a, long b)); -EXTERN void jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, - JSAMPARRAY output_array, int dest_row, - int num_rows, JDIMENSION num_cols)); -EXTERN void jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, - JDIMENSION num_blocks)); -EXTERN void jzero_far JPP((void FAR * target, size_t bytestozero)); -/* Constant tables in jutils.c */ -extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ -extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ - -/* Suppress undefined-structure complaints if necessary. */ - -#ifdef INCOMPLETE_TYPES_BROKEN -#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */ -struct jvirt_sarray_control { long dummy; }; -struct jvirt_barray_control { long dummy; }; -#endif -#endif /* INCOMPLETE_TYPES_BROKEN */ diff --git a/libs/jpeg6/jpgload.cpp b/libs/jpeg6/jpgload.cpp deleted file mode 100644 index ca64685..0000000 --- a/libs/jpeg6/jpgload.cpp +++ /dev/null @@ -1,142 +0,0 @@ - - -#include "jpeglib.h" -#include <memory.h> - -GLOBAL void LoadJPGBuff(unsigned char *fbuffer, unsigned char **pic, int *width, int *height ) -{ - /* This struct contains the JPEG decompression parameters and pointers to - * working space (which is allocated as needed by the JPEG library). - */ - struct jpeg_decompress_struct cinfo; - /* We use our private extension JPEG error handler. - * Note that this struct must live as long as the main JPEG parameter - * struct, to avoid dangling-pointer problems. - */ - /* This struct represents a JPEG error handler. It is declared separately - * because applications often want to supply a specialized error handler - * (see the second half of this file for an example). But here we just - * take the easy way out and use the standard error handler, which will - * print a message on stderr and call exit() if compression fails. - * Note that this struct must live as long as the main JPEG parameter - * struct, to avoid dangling-pointer problems. - */ - - struct jpeg_error_mgr jerr; - /* More stuff */ - JSAMPARRAY buffer; /* Output row buffer */ - int row_stride; /* physical row width in output buffer */ - unsigned char *out; - byte *bbuf; - int nSize; - - /* Step 1: allocate and initialize JPEG decompression object */ - - /* We have to set up the error handler first, in case the initialization - * step fails. (Unlikely, but it could happen if you are out of memory.) - * This routine fills in the contents of struct jerr, and returns jerr's - * address which we place into the link field in cinfo. - */ - cinfo.err = jpeg_std_error(&jerr); - - /* Now we can initialize the JPEG decompression object. */ - jpeg_create_decompress(&cinfo); - - /* Step 2: specify data source (eg, a file) */ - - jpeg_stdio_src(&cinfo, fbuffer); - - /* Step 3: read file parameters with jpeg_read_header() */ - - (void) jpeg_read_header(&cinfo, TRUE); - /* We can ignore the return value from jpeg_read_header since - * (a) suspension is not possible with the stdio data source, and - * (b) we passed TRUE to reject a tables-only JPEG file as an error. - * See libjpeg.doc for more info. - */ - - /* Step 4: set parameters for decompression */ - - /* In this example, we don't need to change any of the defaults set by - * jpeg_read_header(), so we do nothing here. - */ - - /* Step 5: Start decompressor */ - - (void) jpeg_start_decompress(&cinfo); - /* We can ignore the return value since suspension is not possible - * with the stdio data source. - */ - - /* We may need to do some setup of our own at this point before reading - * the data. After jpeg_start_decompress() we have the correct scaled - * output image dimensions available, as well as the output colormap - * if we asked for color quantization. - * In this example, we need to make an output work buffer of the right size. - */ - /* JSAMPLEs per row in output buffer */ - row_stride = cinfo.output_width * cinfo.output_components; - - nSize = cinfo.output_width*cinfo.output_height*cinfo.output_components; - out = reinterpret_cast<unsigned char*>(malloc(nSize+1)); - memset(out, 0, nSize+1); - - *pic = out; - *width = cinfo.output_width; - *height = cinfo.output_height; - - /* Step 6: while (scan lines remain to be read) */ - /* jpeg_read_scanlines(...); */ - - /* Here we use the library's state variable cinfo.output_scanline as the - * loop counter, so that we don't have to keep track ourselves. - */ - while (cinfo.output_scanline < cinfo.output_height) { - /* jpeg_read_scanlines expects an array of pointers to scanlines. - * Here the array is only one element long, but you could ask for - * more than one scanline at a time if that's more convenient. - */ - bbuf = ((out+(row_stride*cinfo.output_scanline))); - buffer = &bbuf; - (void) jpeg_read_scanlines(&cinfo, buffer, 1); - } - - // clear all the alphas to 255 - { - int i, j; - byte *buf; - - buf = *pic; - - j = cinfo.output_width * cinfo.output_height * 4; - for ( i = 3 ; i < j ; i+=4 ) { - buf[i] = 255; - } - } - - /* Step 7: Finish decompression */ - - (void) jpeg_finish_decompress(&cinfo); - /* We can ignore the return value since suspension is not possible - * with the stdio data source. - */ - - /* Step 8: Release JPEG decompression object */ - - /* This is an important step since it will release a good deal of memory. */ - jpeg_destroy_decompress(&cinfo); - - /* After finish_decompress, we can close the input file. - * Here we postpone it until after no more JPEG errors are possible, - * so as to simplify the setjmp error logic above. (Actually, I don't - * think that jpeg_destroy can do an error exit, but why assume anything...) - */ - //free (fbuffer); - - /* At this point you may want to check to see whether any corrupt-data - * warnings occurred (test whether jerr.pub.num_warnings is nonzero). - */ - - /* And we're done! */ -} - diff --git a/libs/jpeg6/jutils.cpp b/libs/jpeg6/jutils.cpp deleted file mode 100644 index 4ba2a54..0000000 --- a/libs/jpeg6/jutils.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/* - * jutils.c - * - * Copyright (C) 1991-1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains tables and miscellaneous utility routines needed - * for both compression and decompression. - * Note we prefix all global names with "j" to minimize conflicts with - * a surrounding application. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element - * of a DCT block read in natural order (left to right, top to bottom). - */ - -const int jpeg_zigzag_order[DCTSIZE2] = { - 0, 1, 5, 6, 14, 15, 27, 28, - 2, 4, 7, 13, 16, 26, 29, 42, - 3, 8, 12, 17, 25, 30, 41, 43, - 9, 11, 18, 24, 31, 40, 44, 53, - 10, 19, 23, 32, 39, 45, 52, 54, - 20, 22, 33, 38, 46, 51, 55, 60, - 21, 34, 37, 47, 50, 56, 59, 61, - 35, 36, 48, 49, 57, 58, 62, 63 -}; - -/* - * jpeg_natural_order[i] is the natural-order position of the i'th element - * of zigzag order. - * - * When reading corrupted data, the Huffman decoders could attempt - * to reference an entry beyond the end of this array (if the decoded - * zero run length reaches past the end of the block). To prevent - * wild stores without adding an inner-loop test, we put some extra - * "63"s after the real entries. This will cause the extra coefficient - * to be stored in location 63 of the block, not somewhere random. - * The worst case would be a run-length of 15, which means we need 16 - * fake entries. - */ - -const int jpeg_natural_order[DCTSIZE2+16] = { - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, - 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, - 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, - 53, 60, 61, 54, 47, 55, 62, 63, - 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ - 63, 63, 63, 63, 63, 63, 63, 63 -}; - - -/* - * Arithmetic utilities - */ - -GLOBAL long -jdiv_round_up (long a, long b) -/* Compute a/b rounded up to next integer, ie, ceil(a/b) */ -/* Assumes a >= 0, b > 0 */ -{ - return (a + b - 1L) / b; -} - - -GLOBAL long -jround_up (long a, long b) -/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */ -/* Assumes a >= 0, b > 0 */ -{ - a += b - 1L; - return a - (a % b); -} - - -/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays - * and coefficient-block arrays. This won't work on 80x86 because the arrays - * are FAR and we're assuming a small-pointer memory model. However, some - * DOS compilers provide far-pointer versions of memcpy() and memset() even - * in the small-model libraries. These will be used if USE_FMEM is defined. - * Otherwise, the routines below do it the hard way. (The performance cost - * is not all that great, because these routines aren't very heavily used.) - */ - -#ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */ -#define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size) -#define FMEMZERO(target,size) MEMZERO(target,size) -#else /* 80x86 case, define if we can */ -#ifdef USE_FMEM -#define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size)) -#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) -#endif -#endif - - -GLOBAL void -jcopy_sample_rows (JSAMPARRAY input_array, int source_row, - JSAMPARRAY output_array, int dest_row, - int num_rows, JDIMENSION num_cols) -/* Copy some rows of samples from one place to another. - * num_rows rows are copied from input_array[source_row++] - * to output_array[dest_row++]; these areas may overlap for duplication. - * The source and destination arrays must be at least as wide as num_cols. - */ -{ - register JSAMPROW inptr, outptr; -#ifdef FMEMCOPY - register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE)); -#else - register JDIMENSION count; -#endif - register int row; - - input_array += source_row; - output_array += dest_row; - - for (row = num_rows; row > 0; row--) { - inptr = *input_array++; - outptr = *output_array++; -#ifdef FMEMCOPY - FMEMCOPY(outptr, inptr, count); -#else - for (count = num_cols; count > 0; count--) - *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */ -#endif - } -} - - -GLOBAL void -jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, - JDIMENSION num_blocks) -/* Copy a row of coefficient blocks from one place to another. */ -{ -#ifdef FMEMCOPY - FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))); -#else - register JCOEFPTR inptr, outptr; - register long count; - - inptr = (JCOEFPTR) input_row; - outptr = (JCOEFPTR) output_row; - for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) { - *outptr++ = *inptr++; - } -#endif -} - - -GLOBAL void -jzero_far (void FAR * target, size_t bytestozero) -/* Zero out a chunk of FAR memory. */ -/* This might be sample-array data, block-array data, or alloc_large data. */ -{ -#ifdef FMEMZERO - FMEMZERO(target, bytestozero); -#else - register char FAR * ptr = (char FAR *) target; - register size_t count; - - for (count = bytestozero; count > 0; count--) { - *ptr++ = 0; - } -#endif -} diff --git a/libs/jpeg6/jversion.h b/libs/jpeg6/jversion.h deleted file mode 100644 index f2f1b8d..0000000 --- a/libs/jpeg6/jversion.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * jversion.h - * - * Copyright (C) 1991-1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains software version identification. - */ - - -#define JVERSION "6 2-Aug-95" - -#define JCOPYRIGHT "Copyright (C) 1995, Thomas G. Lane" diff --git a/libs/jpeglib.h b/libs/jpeglib.h deleted file mode 100644 index e93ab53..0000000 --- a/libs/jpeglib.h +++ /dev/null @@ -1,1087 +0,0 @@ -/* - * jpeglib.h - * - * Copyright (C) 1991-1995, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file defines the application interface for the JPEG library. - * Most applications using the library need only include this file, - * and perhaps jerror.h if they want to know the exact error codes. - */ - -#ifndef JPEGLIB_H -#define JPEGLIB_H - -#ifdef __cplusplus -extern "C" -{ -#endif - - - -#ifdef __MACOS__ - -// JDC: stuff to make mac version compile -#define boolean qboolean -#define register -#define INT32 int - -#endif - -// rad additions -// 11.29.99 - -//#include "cmdlib.h" -#ifdef _WIN32 -#include "windows.h" -#include "stdio.h" -#endif - -#ifndef INT32 -#define INT32 int -#endif - -extern void LoadJPGBuff(unsigned char *fbuffer, unsigned char **pic, int *width, int *height ); -// rad end - - -/* - * First we include the configuration files that record how this - * installation of the JPEG library is set up. jconfig.h can be - * generated automatically for many systems. jmorecfg.h contains - * manual configuration options that most people need not worry about. - */ - -#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ -#include "jpeg6/jconfig.h" /* widely used configuration options */ -#endif -#include "jpeg6/jmorecfg.h" /* seldom changed options */ - - -/* Version ID for the JPEG library. - * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". - */ - -#define JPEG_LIB_VERSION 60 /* Version 6 */ - - -/* Various constants determining the sizes of things. - * All of these are specified by the JPEG standard, so don't change them - * if you want to be compatible. - */ - -#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ -#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ -#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ -#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ -#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ -#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ -#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ -/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; - * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. - * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU - * to handle it. We even let you do this from the jconfig.h file. However, - * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe - * sometimes emits noncompliant files doesn't mean you should too. - */ -#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ -#ifndef D_MAX_BLOCKS_IN_MCU -#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ -#endif - - -/* This macro is used to declare a "method", that is, a function pointer. - * We want to supply prototype parameters if the compiler can cope. - * Note that the arglist parameter must be parenthesized! - */ - -#ifdef HAVE_PROTOTYPES -#define JMETHOD(type,methodname,arglist) type (*methodname) arglist -#else -#define JMETHOD(type,methodname,arglist) type (*methodname) () -#endif - - -/* Data structures for images (arrays of samples and of DCT coefficients). - * On 80x86 machines, the image arrays are too big for near pointers, - * but the pointer arrays can fit in near memory. - */ - -typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ -typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ -typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ - -typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ -typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ -typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ -typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ - -typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ - - -/* Types for JPEG compression parameters and working tables. */ - - -/* DCT coefficient quantization tables. */ - -typedef struct { - /* This field directly represents the contents of a JPEG DQT marker. - * Note: the values are always given in zigzag order. - */ - UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ - /* This field is used only during compression. It's initialized FALSE when - * the table is created, and set TRUE when it's been output to the file. - * You could suppress output of a table by setting this to TRUE. - * (See jpeg_suppress_tables for an example.) - */ - boolean sent_table; /* TRUE when table has been output */ -} JQUANT_TBL; - - -/* Huffman coding tables. */ - -typedef struct { - /* These two fields directly represent the contents of a JPEG DHT marker */ - UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ - /* length k bits; bits[0] is unused */ - UINT8 huffval[256]; /* The symbols, in order of incr code length */ - /* This field is used only during compression. It's initialized FALSE when - * the table is created, and set TRUE when it's been output to the file. - * You could suppress output of a table by setting this to TRUE. - * (See jpeg_suppress_tables for an example.) - */ - boolean sent_table; /* TRUE when table has been output */ -} JHUFF_TBL; - - -/* Basic info about one component (color channel). */ - -typedef struct { - /* These values are fixed over the whole image. */ - /* For compression, they must be supplied by parameter setup; */ - /* for decompression, they are read from the SOF marker. */ - int component_id; /* identifier for this component (0..255) */ - int component_index; /* its index in SOF or cinfo->comp_info[] */ - int h_samp_factor; /* horizontal sampling factor (1..4) */ - int v_samp_factor; /* vertical sampling factor (1..4) */ - int quant_tbl_no; /* quantization table selector (0..3) */ - /* These values may vary between scans. */ - /* For compression, they must be supplied by parameter setup; */ - /* for decompression, they are read from the SOS marker. */ - /* The decompressor output side may not use these variables. */ - int dc_tbl_no; /* DC entropy table selector (0..3) */ - int ac_tbl_no; /* AC entropy table selector (0..3) */ - - /* Remaining fields should be treated as private by applications. */ - - /* These values are computed during compression or decompression startup: */ - /* Component's size in DCT blocks. - * Any dummy blocks added to complete an MCU are not counted; therefore - * these values do not depend on whether a scan is interleaved or not. - */ - JDIMENSION width_in_blocks; - JDIMENSION height_in_blocks; - /* Size of a DCT block in samples. Always DCTSIZE for compression. - * For decompression this is the size of the output from one DCT block, - * reflecting any scaling we choose to apply during the IDCT step. - * Values of 1,2,4,8 are likely to be supported. Note that different - * components may receive different IDCT scalings. - */ - int DCT_scaled_size; - /* The downsampled dimensions are the component's actual, unpadded number - * of samples at the main buffer (preprocessing/compression interface), thus - * downsampled_width = ceil(image_width * Hi/Hmax) - * and similarly for height. For decompression, IDCT scaling is included, so - * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE) - */ - JDIMENSION downsampled_width; /* actual width in samples */ - JDIMENSION downsampled_height; /* actual height in samples */ - /* This flag is used only for decompression. In cases where some of the - * components will be ignored (eg grayscale output from YCbCr image), - * we can skip most computations for the unused components. - */ - boolean component_needed; /* do we need the value of this component? */ - - /* These values are computed before starting a scan of the component. */ - /* The decompressor output side may not use these variables. */ - int MCU_width; /* number of blocks per MCU, horizontally */ - int MCU_height; /* number of blocks per MCU, vertically */ - int MCU_blocks; /* MCU_width * MCU_height */ - int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */ - int last_col_width; /* # of non-dummy blocks across in last MCU */ - int last_row_height; /* # of non-dummy blocks down in last MCU */ - - /* Saved quantization table for component; NULL if none yet saved. - * See jdinput.c comments about the need for this information. - * This field is not currently used by the compressor. - */ - JQUANT_TBL * quant_table; - - /* Private per-component storage for DCT or IDCT subsystem. */ - void * dct_table; -} jpeg_component_info; - - -/* The script for encoding a multiple-scan file is an array of these: */ - -typedef struct { - int comps_in_scan; /* number of components encoded in this scan */ - int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ - int Ss, Se; /* progressive JPEG spectral selection parms */ - int Ah, Al; /* progressive JPEG successive approx. parms */ -} jpeg_scan_info; - - -/* Known color spaces. */ - -typedef enum { - JCS_UNKNOWN, /* error/unspecified */ - JCS_GRAYSCALE, /* monochrome */ - JCS_RGB, /* red/green/blue */ - JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ - JCS_CMYK, /* C/M/Y/K */ - JCS_YCCK /* Y/Cb/Cr/K */ -} J_COLOR_SPACE; - -/* DCT/IDCT algorithm options. */ - -typedef enum { - JDCT_ISLOW, /* slow but accurate integer algorithm */ - JDCT_IFAST, /* faster, less accurate integer method */ - JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ -} J_DCT_METHOD; - -#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ -#define JDCT_DEFAULT JDCT_ISLOW -#endif -#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ -#define JDCT_FASTEST JDCT_IFAST -#endif - -/* Dithering options for decompression. */ - -typedef enum { - JDITHER_NONE, /* no dithering */ - JDITHER_ORDERED, /* simple ordered dither */ - JDITHER_FS /* Floyd-Steinberg error diffusion dither */ -} J_DITHER_MODE; - - -/* Common fields between JPEG compression and decompression master structs. */ - -#define jpeg_common_fields \ - struct jpeg_error_mgr * err; /* Error handler module */\ - struct jpeg_memory_mgr * mem; /* Memory manager module */\ - struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ - boolean is_decompressor; /* so common code can tell which is which */\ - int global_state /* for checking call sequence validity */ - -/* Routines that are to be used by both halves of the library are declared - * to receive a pointer to this structure. There are no actual instances of - * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. - */ -struct jpeg_common_struct { - jpeg_common_fields; /* Fields common to both master struct types */ - /* Additional fields follow in an actual jpeg_compress_struct or - * jpeg_decompress_struct. All three structs must agree on these - * initial fields! (This would be a lot cleaner in C++.) - */ -}; - -typedef struct jpeg_common_struct * j_common_ptr; -typedef struct jpeg_compress_struct * j_compress_ptr; -typedef struct jpeg_decompress_struct * j_decompress_ptr; - - -/* Master record for a compression instance */ - -struct jpeg_compress_struct { - jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ - - /* Destination for compressed data */ - struct jpeg_destination_mgr * dest; - - /* Description of source image --- these fields must be filled in by - * outer application before starting compression. in_color_space must - * be correct before you can even call jpeg_set_defaults(). - */ - - JDIMENSION image_width; /* input image width */ - JDIMENSION image_height; /* input image height */ - int input_components; /* # of color components in input image */ - J_COLOR_SPACE in_color_space; /* colorspace of input image */ - - double input_gamma; /* image gamma of input image */ - - /* Compression parameters --- these fields must be set before calling - * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to - * initialize everything to reasonable defaults, then changing anything - * the application specifically wants to change. That way you won't get - * burnt when new parameters are added. Also note that there are several - * helper routines to simplify changing parameters. - */ - - int data_precision; /* bits of precision in image data */ - - int num_components; /* # of color components in JPEG image */ - J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ - - jpeg_component_info * comp_info; - /* comp_info[i] describes component that appears i'th in SOF */ - - JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; - /* ptrs to coefficient quantization tables, or NULL if not defined */ - - JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; - JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; - /* ptrs to Huffman coding tables, or NULL if not defined */ - - UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ - UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ - UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ - - int num_scans; /* # of entries in scan_info array */ - const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ - /* The default value of scan_info is NULL, which causes a single-scan - * sequential JPEG file to be emitted. To create a multi-scan file, - * set num_scans and scan_info to point to an array of scan definitions. - */ - - boolean raw_data_in; /* TRUE=caller supplies downsampled data */ - boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ - boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ - boolean CCIR601_sampling; /* TRUE=first samples are cosited */ - int smoothing_factor; /* 1..100, or 0 for no input smoothing */ - J_DCT_METHOD dct_method; /* DCT algorithm selector */ - - /* The restart interval can be specified in absolute MCUs by setting - * restart_interval, or in MCU rows by setting restart_in_rows - * (in which case the correct restart_interval will be figured - * for each scan). - */ - unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ - int restart_in_rows; /* if > 0, MCU rows per restart interval */ - - /* Parameters controlling emission of special markers. */ - - boolean write_JFIF_header; /* should a JFIF marker be written? */ - /* These three values are not used by the JPEG code, merely copied */ - /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ - /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ - /* ratio is defined by X_density/Y_density even when density_unit=0. */ - UINT8 density_unit; /* JFIF code for pixel size units */ - UINT16 X_density; /* Horizontal pixel density */ - UINT16 Y_density; /* Vertical pixel density */ - boolean write_Adobe_marker; /* should an Adobe marker be written? */ - - /* State variable: index of next scanline to be written to - * jpeg_write_scanlines(). Application may use this to control its - * processing loop, e.g., "while (next_scanline < image_height)". - */ - - JDIMENSION next_scanline; /* 0 .. image_height-1 */ - - /* Remaining fields are known throughout compressor, but generally - * should not be touched by a surrounding application. - */ - - /* - * These fields are computed during compression startup - */ - boolean progressive_mode; /* TRUE if scan script uses progressive mode */ - int max_h_samp_factor; /* largest h_samp_factor */ - int max_v_samp_factor; /* largest v_samp_factor */ - - JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ - /* The coefficient controller receives data in units of MCU rows as defined - * for fully interleaved scans (whether the JPEG file is interleaved or not). - * There are v_samp_factor * DCTSIZE sample rows of each component in an - * "iMCU" (interleaved MCU) row. - */ - - /* - * These fields are valid during any one scan. - * They describe the components and MCUs actually appearing in the scan. - */ - int comps_in_scan; /* # of JPEG components in this scan */ - jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; - /* *cur_comp_info[i] describes component that appears i'th in SOS */ - - JDIMENSION MCUs_per_row; /* # of MCUs across the image */ - JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ - - int blocks_in_MCU; /* # of DCT blocks per MCU */ - int MCU_membership[C_MAX_BLOCKS_IN_MCU]; - /* MCU_membership[i] is index in cur_comp_info of component owning */ - /* i'th block in an MCU */ - - int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ - - /* - * Links to compression subobjects (methods and private variables of modules) - */ - struct jpeg_comp_master * master; - struct jpeg_c_main_controller * main; - struct jpeg_c_prep_controller * prep; - struct jpeg_c_coef_controller * coef; - struct jpeg_marker_writer * marker; - struct jpeg_color_converter * cconvert; - struct jpeg_downsampler * downsample; - struct jpeg_forward_dct * fdct; - struct jpeg_entropy_encoder * entropy; -}; - - -/* Master record for a decompression instance */ - -struct jpeg_decompress_struct { - jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ - - /* Source of compressed data */ - struct jpeg_source_mgr * src; - - /* Basic description of image --- filled in by jpeg_read_header(). */ - /* Application may inspect these values to decide how to process image. */ - - JDIMENSION image_width; /* nominal image width (from SOF marker) */ - JDIMENSION image_height; /* nominal image height */ - int num_components; /* # of color components in JPEG image */ - J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ - - /* Decompression processing parameters --- these fields must be set before - * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes - * them to default values. - */ - - J_COLOR_SPACE out_color_space; /* colorspace for output */ - - unsigned int scale_num, scale_denom; /* fraction by which to scale image */ - - double output_gamma; /* image gamma wanted in output */ - - boolean buffered_image; /* TRUE=multiple output passes */ - boolean raw_data_out; /* TRUE=downsampled data wanted */ - - J_DCT_METHOD dct_method; /* IDCT algorithm selector */ - boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ - boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ - - boolean quantize_colors; /* TRUE=colormapped output wanted */ - /* the following are ignored if not quantize_colors: */ - J_DITHER_MODE dither_mode; /* type of color dithering to use */ - boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ - int desired_number_of_colors; /* max # colors to use in created colormap */ - /* these are significant only in buffered-image mode: */ - boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ - boolean enable_external_quant;/* enable future use of external colormap */ - boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ - - /* Description of actual output image that will be returned to application. - * These fields are computed by jpeg_start_decompress(). - * You can also use jpeg_calc_output_dimensions() to determine these values - * in advance of calling jpeg_start_decompress(). - */ - - JDIMENSION output_width; /* scaled image width */ - JDIMENSION output_height; /* scaled image height */ - int out_color_components; /* # of color components in out_color_space */ - int output_components; /* # of color components returned */ - /* output_components is 1 (a colormap index) when quantizing colors; - * otherwise it equals out_color_components. - */ - int rec_outbuf_height; /* min recommended height of scanline buffer */ - /* If the buffer passed to jpeg_read_scanlines() is less than this many rows - * high, space and time will be wasted due to unnecessary data copying. - * Usually rec_outbuf_height will be 1 or 2, at most 4. - */ - - /* When quantizing colors, the output colormap is described by these fields. - * The application can supply a colormap by setting colormap non-NULL before - * calling jpeg_start_decompress; otherwise a colormap is created during - * jpeg_start_decompress or jpeg_start_output. - * The map has out_color_components rows and actual_number_of_colors columns. - */ - int actual_number_of_colors; /* number of entries in use */ - JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ - - /* State variables: these variables indicate the progress of decompression. - * The application may examine these but must not modify them. - */ - - /* Row index of next scanline to be read from jpeg_read_scanlines(). - * Application may use this to control its processing loop, e.g., - * "while (output_scanline < output_height)". - */ - JDIMENSION output_scanline; /* 0 .. output_height-1 */ - - /* Current input scan number and number of iMCU rows completed in scan. - * These indicate the progress of the decompressor input side. - */ - int input_scan_number; /* Number of SOS markers seen so far */ - JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ - - /* The "output scan number" is the notional scan being displayed by the - * output side. The decompressor will not allow output scan/row number - * to get ahead of input scan/row, but it can fall arbitrarily far behind. - */ - int output_scan_number; /* Nominal scan number being displayed */ - JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ - - /* Current progression status. coef_bits[c][i] indicates the precision - * with which component c's DCT coefficient i (in zigzag order) is known. - * It is -1 when no data has yet been received, otherwise it is the point - * transform (shift) value for the most recent scan of the coefficient - * (thus, 0 at completion of the progression). - * This pointer is NULL when reading a non-progressive file. - */ - int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ - - /* Internal JPEG parameters --- the application usually need not look at - * these fields. Note that the decompressor output side may not use - * any parameters that can change between scans. - */ - - /* Quantization and Huffman tables are carried forward across input - * datastreams when processing abbreviated JPEG datastreams. - */ - - JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; - /* ptrs to coefficient quantization tables, or NULL if not defined */ - - JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; - JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; - /* ptrs to Huffman coding tables, or NULL if not defined */ - - /* These parameters are never carried across datastreams, since they - * are given in SOF/SOS markers or defined to be reset by SOI. - */ - - int data_precision; /* bits of precision in image data */ - - jpeg_component_info * comp_info; - /* comp_info[i] describes component that appears i'th in SOF */ - - boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ - boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ - - UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ - UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ - UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ - - unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ - - /* These fields record data obtained from optional markers recognized by - * the JPEG library. - */ - boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ - /* Data copied from JFIF marker: */ - UINT8 density_unit; /* JFIF code for pixel size units */ - UINT16 X_density; /* Horizontal pixel density */ - UINT16 Y_density; /* Vertical pixel density */ - boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ - UINT8 Adobe_transform; /* Color transform code from Adobe marker */ - - boolean CCIR601_sampling; /* TRUE=first samples are cosited */ - - /* Remaining fields are known throughout decompressor, but generally - * should not be touched by a surrounding application. - */ - - /* - * These fields are computed during decompression startup - */ - int max_h_samp_factor; /* largest h_samp_factor */ - int max_v_samp_factor; /* largest v_samp_factor */ - - int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ - - JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ - /* The coefficient controller's input and output progress is measured in - * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows - * in fully interleaved JPEG scans, but are used whether the scan is - * interleaved or not. We define an iMCU row as v_samp_factor DCT block - * rows of each component. Therefore, the IDCT output contains - * v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row. - */ - - JSAMPLE * sample_range_limit; /* table for fast range-limiting */ - - /* - * These fields are valid during any one scan. - * They describe the components and MCUs actually appearing in the scan. - * Note that the decompressor output side must not use these fields. - */ - int comps_in_scan; /* # of JPEG components in this scan */ - jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; - /* *cur_comp_info[i] describes component that appears i'th in SOS */ - - JDIMENSION MCUs_per_row; /* # of MCUs across the image */ - JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ - - int blocks_in_MCU; /* # of DCT blocks per MCU */ - int MCU_membership[D_MAX_BLOCKS_IN_MCU]; - /* MCU_membership[i] is index in cur_comp_info of component owning */ - /* i'th block in an MCU */ - - int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ - - /* This field is shared between entropy decoder and marker parser. - * It is either zero or the code of a JPEG marker that has been - * read from the data source, but has not yet been processed. - */ - int unread_marker; - - /* - * Links to decompression subobjects (methods, private variables of modules) - */ - struct jpeg_decomp_master * master; - struct jpeg_d_main_controller * main; - struct jpeg_d_coef_controller * coef; - struct jpeg_d_post_controller * post; - struct jpeg_input_controller * inputctl; - struct jpeg_marker_reader * marker; - struct jpeg_entropy_decoder * entropy; - struct jpeg_inverse_dct * idct; - struct jpeg_upsampler * upsample; - struct jpeg_color_deconverter * cconvert; - struct jpeg_color_quantizer * cquantize; -}; - - -/* "Object" declarations for JPEG modules that may be supplied or called - * directly by the surrounding application. - * As with all objects in the JPEG library, these structs only define the - * publicly visible methods and state variables of a module. Additional - * private fields may exist after the public ones. - */ - - -/* Error handler object */ - -struct jpeg_error_mgr { - /* Error exit handler: does not return to caller */ - JMETHOD(void, error_exit, (j_common_ptr cinfo)); - /* Conditionally emit a trace or warning message */ - JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); - /* Routine that actually outputs a trace or error message */ - JMETHOD(void, output_message, (j_common_ptr cinfo)); - /* Format a message string for the most recent JPEG error or message */ - JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); -#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ - /* Reset error state variables at start of a new image */ - JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); - - /* The message ID code and any parameters are saved here. - * A message can have one string parameter or up to 8 int parameters. - */ - int msg_code; -#define JMSG_STR_PARM_MAX 80 - union { - int i[8]; - char s[JMSG_STR_PARM_MAX]; - } msg_parm; - - /* Standard state variables for error facility */ - - int trace_level; /* max msg_level that will be displayed */ - - /* For recoverable corrupt-data errors, we emit a warning message, - * but keep going unless emit_message chooses to abort. emit_message - * should count warnings in num_warnings. The surrounding application - * can check for bad data by seeing if num_warnings is nonzero at the - * end of processing. - */ - long num_warnings; /* number of corrupt-data warnings */ - - /* These fields point to the table(s) of error message strings. - * An application can change the table pointer to switch to a different - * message list (typically, to change the language in which errors are - * reported). Some applications may wish to add additional error codes - * that will be handled by the JPEG library error mechanism; the second - * table pointer is used for this purpose. - * - * First table includes all errors generated by JPEG library itself. - * Error code 0 is reserved for a "no such error string" message. - */ - const char * const * jpeg_message_table; /* Library errors */ - int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ - /* Second table can be added by application (see cjpeg/djpeg for example). - * It contains strings numbered first_addon_message..last_addon_message. - */ - const char * const * addon_message_table; /* Non-library errors */ - int first_addon_message; /* code for first string in addon table */ - int last_addon_message; /* code for last string in addon table */ -}; - - -/* Progress monitor object */ - -struct jpeg_progress_mgr { - JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); - - long pass_counter; /* work units completed in this pass */ - long pass_limit; /* total number of work units in this pass */ - int completed_passes; /* passes completed so far */ - int total_passes; /* total number of passes expected */ -}; - - -/* Data destination object for compression */ - -struct jpeg_destination_mgr { - JOCTET * next_output_byte; /* => next byte to write in buffer */ - size_t free_in_buffer; /* # of byte spaces remaining in buffer */ - - JMETHOD(void, init_destination, (j_compress_ptr cinfo)); - JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); - JMETHOD(void, term_destination, (j_compress_ptr cinfo)); -}; - - -/* Data source object for decompression */ - -struct jpeg_source_mgr { - const JOCTET * next_input_byte; /* => next byte to read from buffer */ - size_t bytes_in_buffer; /* # of bytes remaining in buffer */ - - JMETHOD(void, init_source, (j_decompress_ptr cinfo)); - JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); - JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); - JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); - JMETHOD(void, term_source, (j_decompress_ptr cinfo)); -}; - - -/* Memory manager object. - * Allocates "small" objects (a few K total), "large" objects (tens of K), - * and "really big" objects (virtual arrays with backing store if needed). - * The memory manager does not allow individual objects to be freed; rather, - * each created object is assigned to a pool, and whole pools can be freed - * at once. This is faster and more convenient than remembering exactly what - * to free, especially where malloc()/free() are not too speedy. - * NB: alloc routines never return NULL. They exit to error_exit if not - * successful. - */ - -#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ -#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ -#define JPOOL_NUMPOOLS 2 - -typedef struct jvirt_sarray_control * jvirt_sarray_ptr; -typedef struct jvirt_barray_control * jvirt_barray_ptr; - - -struct jpeg_memory_mgr { - /* Method pointers */ - JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, - size_t sizeofobject)); - JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, - size_t sizeofobject)); - JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, - JDIMENSION samplesperrow, - JDIMENSION numrows)); - JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, - JDIMENSION blocksperrow, - JDIMENSION numrows)); - JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, - int pool_id, - boolean pre_zero, - JDIMENSION samplesperrow, - JDIMENSION numrows, - JDIMENSION maxaccess)); - JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, - int pool_id, - boolean pre_zero, - JDIMENSION blocksperrow, - JDIMENSION numrows, - JDIMENSION maxaccess)); - JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); - JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, - jvirt_sarray_ptr ptr, - JDIMENSION start_row, - JDIMENSION num_rows, - boolean writable)); - JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, - jvirt_barray_ptr ptr, - JDIMENSION start_row, - JDIMENSION num_rows, - boolean writable)); - JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); - JMETHOD(void, self_destruct, (j_common_ptr cinfo)); - - /* Limit on memory allocation for this JPEG object. (Note that this is - * merely advisory, not a guaranteed maximum; it only affects the space - * used for virtual-array buffers.) May be changed by outer application - * after creating the JPEG object. - */ - long max_memory_to_use; -}; - - -/* Routine signature for application-supplied marker processing methods. - * Need not pass marker code since it is stored in cinfo->unread_marker. - */ -typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); - - -/* Declarations for routines called by application. - * The JPP macro hides prototype parameters from compilers that can't cope. - * Note JPP requires double parentheses. - */ - -#ifdef HAVE_PROTOTYPES -#define JPP(arglist) arglist -#else -#define JPP(arglist) () -#endif - - -/* Short forms of external names for systems with brain-damaged linkers. - * We shorten external names to be unique in the first six letters, which - * is good enough for all known systems. - * (If your compiler itself needs names to be unique in less than 15 - * characters, you are out of luck. Get a better compiler.) - */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_std_error jStdError -#define jpeg_create_compress jCreaCompress -#define jpeg_create_decompress jCreaDecompress -#define jpeg_destroy_compress jDestCompress -#define jpeg_destroy_decompress jDestDecompress -#define jpeg_stdio_dest jStdDest -#define jpeg_stdio_src jStdSrc -#define jpeg_set_defaults jSetDefaults -#define jpeg_set_colorspace jSetColorspace -#define jpeg_default_colorspace jDefColorspace -#define jpeg_set_quality jSetQuality -#define jpeg_set_linear_quality jSetLQuality -#define jpeg_add_quant_table jAddQuantTable -#define jpeg_quality_scaling jQualityScaling -#define jpeg_simple_progression jSimProgress -#define jpeg_suppress_tables jSuppressTables -#define jpeg_alloc_quant_table jAlcQTable -#define jpeg_alloc_huff_table jAlcHTable -#define jpeg_start_compress jStrtCompress -#define jpeg_write_scanlines jWrtScanlines -#define jpeg_finish_compress jFinCompress -#define jpeg_write_raw_data jWrtRawData -#define jpeg_write_marker jWrtMarker -#define jpeg_write_tables jWrtTables -#define jpeg_read_header jReadHeader -#define jpeg_start_decompress jStrtDecompress -#define jpeg_read_scanlines jReadScanlines -#define jpeg_finish_decompress jFinDecompress -#define jpeg_read_raw_data jReadRawData -#define jpeg_has_multiple_scans jHasMultScn -#define jpeg_start_output jStrtOutput -#define jpeg_finish_output jFinOutput -#define jpeg_input_complete jInComplete -#define jpeg_new_colormap jNewCMap -#define jpeg_consume_input jConsumeInput -#define jpeg_calc_output_dimensions jCalcDimensions -#define jpeg_set_marker_processor jSetMarker -#define jpeg_read_coefficients jReadCoefs -#define jpeg_write_coefficients jWrtCoefs -#define jpeg_copy_critical_parameters jCopyCrit -#define jpeg_abort_compress jAbrtCompress -#define jpeg_abort_decompress jAbrtDecompress -#define jpeg_abort jAbort -#define jpeg_destroy jDestroy -#define jpeg_resync_to_restart jResyncRestart -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* Default error-management setup */ -EXTERN struct jpeg_error_mgr *jpeg_std_error JPP((struct jpeg_error_mgr *err)); - -/* Initialization and destruction of JPEG compression objects */ -/* NB: you must set up the error-manager BEFORE calling jpeg_create_xxx */ -EXTERN void jpeg_create_compress JPP((j_compress_ptr cinfo)); -EXTERN void jpeg_create_decompress JPP((j_decompress_ptr cinfo)); -EXTERN void jpeg_destroy_compress JPP((j_compress_ptr cinfo)); -EXTERN void jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); - -/* Standard data source and destination managers: stdio streams. */ -/* Caller is responsible for opening the file before and closing after. */ -EXTERN void jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); -EXTERN void jpeg_stdio_src JPP((j_decompress_ptr cinfo, unsigned char *infile)); - -/* Default parameter setup for compression */ -EXTERN void jpeg_set_defaults JPP((j_compress_ptr cinfo)); -/* Compression parameter setup aids */ -EXTERN void jpeg_set_colorspace JPP((j_compress_ptr cinfo, - J_COLOR_SPACE colorspace)); -EXTERN void jpeg_default_colorspace JPP((j_compress_ptr cinfo)); -EXTERN void jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, - boolean force_baseline)); -EXTERN void jpeg_set_linear_quality JPP((j_compress_ptr cinfo, - int scale_factor, - boolean force_baseline)); -EXTERN void jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, - const unsigned int *basic_table, - int scale_factor, - boolean force_baseline)); -EXTERN int jpeg_quality_scaling JPP((int quality)); -EXTERN void jpeg_simple_progression JPP((j_compress_ptr cinfo)); -EXTERN void jpeg_suppress_tables JPP((j_compress_ptr cinfo, - boolean suppress)); -EXTERN JQUANT_TBL * jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); -EXTERN JHUFF_TBL * jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); - -/* Main entry points for compression */ -EXTERN void jpeg_start_compress JPP((j_compress_ptr cinfo, - boolean write_all_tables)); -EXTERN JDIMENSION jpeg_write_scanlines JPP((j_compress_ptr cinfo, - JSAMPARRAY scanlines, - JDIMENSION num_lines)); -EXTERN void jpeg_finish_compress JPP((j_compress_ptr cinfo)); - -/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ -EXTERN JDIMENSION jpeg_write_raw_data JPP((j_compress_ptr cinfo, - JSAMPIMAGE data, - JDIMENSION num_lines)); - -/* Write a special marker. See libjpeg.doc concerning safe usage. */ -EXTERN void jpeg_write_marker JPP((j_compress_ptr cinfo, int marker, - const JOCTET *dataptr, unsigned int datalen)); - -/* Alternate compression function: just write an abbreviated table file */ -EXTERN void jpeg_write_tables JPP((j_compress_ptr cinfo)); - -/* Decompression startup: read start of JPEG datastream to see what's there */ -EXTERN int jpeg_read_header JPP((j_decompress_ptr cinfo, - boolean require_image)); -/* Return value is one of: */ -#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ -#define JPEG_HEADER_OK 1 /* Found valid image datastream */ -#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ -/* If you pass require_image = TRUE (normal case), you need not check for - * a TABLES_ONLY return code; an abbreviated file will cause an error exit. - * JPEG_SUSPENDED is only possible if you use a data source module that can - * give a suspension return (the stdio source module doesn't). - */ - -/* Main entry points for decompression */ -EXTERN boolean jpeg_start_decompress JPP((j_decompress_ptr cinfo)); -EXTERN JDIMENSION jpeg_read_scanlines JPP((j_decompress_ptr cinfo, - JSAMPARRAY scanlines, - JDIMENSION max_lines)); -EXTERN boolean jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); - -/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ -EXTERN JDIMENSION jpeg_read_raw_data JPP((j_decompress_ptr cinfo, - JSAMPIMAGE data, - JDIMENSION max_lines)); - -/* Additional entry points for buffered-image mode. */ -EXTERN boolean jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); -EXTERN boolean jpeg_start_output JPP((j_decompress_ptr cinfo, - int scan_number)); -EXTERN boolean jpeg_finish_output JPP((j_decompress_ptr cinfo)); -EXTERN boolean jpeg_input_complete JPP((j_decompress_ptr cinfo)); -EXTERN void jpeg_new_colormap JPP((j_decompress_ptr cinfo)); -EXTERN int jpeg_consume_input JPP((j_decompress_ptr cinfo)); -/* Return value is one of: */ -/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ -#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ -#define JPEG_REACHED_EOI 2 /* Reached end of image */ -#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ -#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ - -/* Precalculate output dimensions for current decompression parameters. */ -EXTERN void jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); - -/* Install a special processing method for COM or APPn markers. */ -EXTERN void jpeg_set_marker_processor JPP((j_decompress_ptr cinfo, - int marker_code, - jpeg_marker_parser_method routine)); - -/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ -EXTERN jvirt_barray_ptr * jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); -EXTERN void jpeg_write_coefficients JPP((j_compress_ptr cinfo, - jvirt_barray_ptr * coef_arrays)); -EXTERN void jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, - j_compress_ptr dstinfo)); - -/* If you choose to abort compression or decompression before completing - * jpeg_finish_(de)compress, then you need to clean up to release memory, - * temporary files, etc. You can just call jpeg_destroy_(de)compress - * if you're done with the JPEG object, but if you want to clean it up and - * reuse it, call this: - */ -EXTERN void jpeg_abort_compress JPP((j_compress_ptr cinfo)); -EXTERN void jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); - -/* Generic versions of jpeg_abort and jpeg_destroy that work on either - * flavor of JPEG object. These may be more convenient in some places. - */ -EXTERN void jpeg_abort JPP((j_common_ptr cinfo)); -EXTERN void jpeg_destroy JPP((j_common_ptr cinfo)); - -/* Default restart-marker-resync procedure for use by data source modules */ -EXTERN boolean jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, - int desired)); - - -/* These marker codes are exported since applications and data source modules - * are likely to want to use them. - */ - -#define JPEG_RST0 0xD0 /* RST0 marker code */ -#define JPEG_EOI 0xD9 /* EOI marker code */ -#define JPEG_APP0 0xE0 /* APP0 marker code */ -#define JPEG_COM 0xFE /* COM marker code */ - - -/* If we have a brain-damaged compiler that emits warnings (or worse, errors) - * for structure definitions that are never filled in, keep it quiet by - * supplying dummy definitions for the various substructures. - */ - -#ifdef INCOMPLETE_TYPES_BROKEN -#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ -struct jvirt_sarray_control { long dummy; }; -struct jvirt_barray_control { long dummy; }; -struct jpeg_comp_master { long dummy; }; -struct jpeg_c_main_controller { long dummy; }; -struct jpeg_c_prep_controller { long dummy; }; -struct jpeg_c_coef_controller { long dummy; }; -struct jpeg_marker_writer { long dummy; }; -struct jpeg_color_converter { long dummy; }; -struct jpeg_downsampler { long dummy; }; -struct jpeg_forward_dct { long dummy; }; -struct jpeg_entropy_encoder { long dummy; }; -struct jpeg_decomp_master { long dummy; }; -struct jpeg_d_main_controller { long dummy; }; -struct jpeg_d_coef_controller { long dummy; }; -struct jpeg_d_post_controller { long dummy; }; -struct jpeg_input_controller { long dummy; }; -struct jpeg_marker_reader { long dummy; }; -struct jpeg_entropy_decoder { long dummy; }; -struct jpeg_inverse_dct { long dummy; }; -struct jpeg_upsampler { long dummy; }; -struct jpeg_color_deconverter { long dummy; }; -struct jpeg_color_quantizer { long dummy; }; -#endif /* JPEG_INTERNALS */ -#endif /* INCOMPLETE_TYPES_BROKEN */ - - -/* - * The JPEG library modules define JPEG_INTERNALS before including this file. - * The internal structure declarations are read only when that is true. - * Applications using the library should not include jpegint.h, but may wish - * to include jerror.h. - */ - -#ifdef JPEG_INTERNALS -#include "jpegint.h" /* fetch private declarations */ -#include "jerror.h" /* fetch error codes too */ -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* JPEGLIB_H */ diff --git a/libs/pak/pak.vcproj b/libs/pak/pak.vcproj deleted file mode 100644 index 196a45a..0000000 --- a/libs/pak/pak.vcproj +++ /dev/null @@ -1,173 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="7.10" - Name="pak" - SccProjectName=""$/source/q3radiant", FEFAAAAA" - SccLocalPath="..\..\q3radiant"> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory=".\Debug" - IntermediateDirectory=".\Debug" - ConfigurationType="4" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories=".." - PreprocessorDefinitions="WIN32;_DEBUG;_LIB" - BasicRuntimeChecks="3" - RuntimeLibrary="1" - RuntimeTypeInfo="TRUE" - UsePrecompiledHeader="2" - PrecompiledHeaderFile=".\Debug/pak.pch" - AssemblerListingLocation=".\Debug/" - ObjectFile=".\Debug/" - ProgramDataBaseFileName=".\Debug/" - WarningLevel="3" - SuppressStartupBanner="TRUE" - DebugInformationFormat="4" - CompileAs="0"/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCLibrarianTool" - OutputFile="..\pakd.lib" - SuppressStartupBanner="TRUE"/> - <Tool - Name="VCMIDLTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="_DEBUG" - Culture="1033"/> - <Tool - Name="VCWebServiceProxyGeneratorTool"/> - <Tool - Name="VCXMLDataGeneratorTool"/> - <Tool - Name="VCManagedWrapperGeneratorTool"/> - <Tool - Name="VCAuxiliaryManagedWrapperGeneratorTool"/> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory=".\Release" - IntermediateDirectory=".\Release" - ConfigurationType="4" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories=".." - PreprocessorDefinitions="WIN32;NDEBUG;_LIB" - RuntimeLibrary="0" - RuntimeTypeInfo="TRUE" - UsePrecompiledHeader="2" - PrecompiledHeaderFile=".\Release/pak.pch" - AssemblerListingLocation=".\Release/" - ObjectFile=".\Release/" - ProgramDataBaseFileName=".\Release/" - WarningLevel="3" - SuppressStartupBanner="TRUE" - CompileAs="0"/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCLibrarianTool" - OutputFile="..\pak.lib" - SuppressStartupBanner="TRUE"/> - <Tool - Name="VCMIDLTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="NDEBUG" - Culture="1033"/> - <Tool - Name="VCWebServiceProxyGeneratorTool"/> - <Tool - Name="VCXMLDataGeneratorTool"/> - <Tool - Name="VCManagedWrapperGeneratorTool"/> - <Tool - Name="VCAuxiliaryManagedWrapperGeneratorTool"/> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="Source Files" - Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"> - <File - RelativePath="pakstuff.cpp"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="unzip.cpp"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BasicRuntimeChecks="3"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - </Filter> - <Filter - Name="Header Files" - Filter="h;hpp;hxx;hm;inl"> - <File - RelativePath="..\pakstuff.h"> - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/libs/pak/pakstuff.cpp b/libs/pak/pakstuff.cpp deleted file mode 100644 index 011c27d..0000000 --- a/libs/pak/pakstuff.cpp +++ /dev/null @@ -1,1209 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include <stdio.h> -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> -#include <windows.h> -#include "io.h" -#include "pakstuff.h" -#include "unzip.h" -//#include "cmdlib.h" -#include "str.h" - -int m_nPAKIndex; -FILE* pakfile[16]; -struct PACKDirectory pakdir; -PACKDirPtr pakdirptr = &pakdir; -UInt16 dirsize; -boolean pakopen = false; -int f_type; -DIRECTORY *paktextures = NULL; -boolean HavePakColormap; -UInt32 PakColormapOffset; -UInt32 PakColormapSize; -DIRECTORY *dirhead = NULL; -boolean g_bPK3 = false; -char g_strBasePath[1024]; - -struct PK3FileInfo -{ - unzFile m_zFile; - char *m_pName; - unz_s m_zInfo; - long m_lSize; - ~PK3FileInfo() - { - delete []m_pName; - } - bool operator ==(const PK3FileInfo& rhs) const { return strcmp(m_pName, rhs.m_pName) == 0; } -}; - -#define __PATHSEPERATOR '/' - -#define LOG_PAKFAIL - -#ifdef LOG_PAKFAIL - -class LogFile -{ -public: - FILE *m_pFile; - LogFile(const char* pName) - { - m_pFile = fopen(pName, "w"); - } - ~LogFile() - { - if (m_pFile) - { - fclose(m_pFile); - } - } - void Log(const char *pFormat, ...) - { - va_list arg_ptr; - va_start(arg_ptr, pFormat); - fprintf(m_pFile, pFormat, arg_ptr); - va_end(arg_ptr); - } -}; - -LogFile g_LogFile("c:\\paklog.txt"); -#endif - -template <class T> class StrPtr : public Str -{ -protected: - T* m_pPtr; - StrPtr() - { - m_pPtr = NULL; - } - - StrPtr(const char *pStr, T *p) : Str(pStr) - { - m_pPtr = p; - } - - T* Ptr() - { - return m_pPtr; - } - - T& Ref() - { - return *m_pPtr; - } - - -}; -// PtrList -// a list of ptrs -// -template <class T> class PtrList -{ -protected: - T *m_pPtr; - PtrList *m_pNext; - -public: - - PtrList() - { - m_pNext = NULL; - m_pPtr = NULL; - } - - PtrList(T *ip) - { - m_pNext = NULL; - m_pPtr = ip; - } - - ~PtrList() - { - delete m_pPtr; - } - - PtrList* Next() - { - return m_pNext; - } - - void Add(T *ip) - { - PtrList *pl = this; - while (pl && pl->m_pNext) - { - pl = pl->Next(); - } - pl->m_pNext = new PtrList(ip); - } - - void Remove() - { - PtrList *p = m_pNext; - if (p) - { - while (p->m_pNext != this && p->m_pNext != NULL) - { - p = p->m_pNext; - } - if (p->m_pNext == this) - { - p->m_pNext = m_pNext; - } - } - } - - virtual PtrList* Find(T *ip) - { - PtrList *p = m_pNext; - while (p) - { - if (*p->m_pPtr == *ip) - { - return p; - } - p = p->m_pNext; - } - return NULL; - } - - // remove vp from the list - void Remove(T *ip) - { - PtrList *p = Find(ip); - if (p) - { - p->Remove(); - } - } - - T* Ptr() - { - return m_pPtr; - } - - T& Ref() - { - return *m_pPtr; - } - - void RemoveAll() - { - PtrList *p = m_pNext; - while (p) - { - PtrList *p2 = p; - p = p->m_pNext; - delete p2; - } - } -}; - - -typedef PtrList<unzFile> ZFileList; -typedef PtrList<Str> StrList; -typedef PtrList<PK3FileInfo> PK3List; - - -StrList g_PK3TexturePaths; -PK3List g_PK3Files; -ZFileList g_zFiles; -#define WORK_LEN 1024 -#define TEXTURE_PATH "textures" -#define PATH_SEPERATORS "/\\:\0" - - -char* __StrDup(char* pStr) -{ - if (pStr) - { - return strcpy(new char[strlen(pStr)+1], pStr); - } - return NULL; -} - -char* __StrDup(const char* pStr) -{ - if (pStr) - { - return strcpy(new char[strlen(pStr)+1], pStr); - } - return NULL; -} - -#define MEM_BLOCKSIZE 4096 -void* __qblockmalloc(size_t nSize) -{ - void *b; - // round up to threshold - int nAllocSize = nSize % MEM_BLOCKSIZE; - if ( nAllocSize > 0) - { - nSize += MEM_BLOCKSIZE - nAllocSize; - } - b = malloc(nSize + 1); - memset (b, 0, nSize); - return b; -} - -void* __qmalloc (size_t nSize) -{ - void *b; - b = malloc(nSize + 1); - memset (b, 0, nSize); - return b; -} - - -/* -==================== -Extract file parts -==================== -*/ -void __ExtractFilePath (const char *path, char *dest) -{ - const char *src; - - src = path + strlen(path) - 1; - -// -// back up until a \ or the start -// - while (src != path && *(src-1) != __PATHSEPERATOR) - src--; - - memcpy (dest, path, src-path); - dest[src-path] = 0; -} - -void __ExtractFileName (const char *path, char *dest) -{ - const char *src; - - src = path + strlen(path) - 1; - -// -// back up until a \ or the start -// - while (src != path && *(src-1) != '/' - && *(src-1) != '\\' ) - src--; - - while (*src) - { - *dest++ = *src++; - } - *dest = 0; -} - -void __ExtractFileBase (const char *path, char *dest) -{ - const char *src; - - src = path + strlen(path) - 1; - -// -// back up until a \ or the start -// - while (src != path && *(src-1) != '/' - && *(src-1) != '\\' ) - src--; - - while (*src && *src != '.') - { - *dest++ = *src++; - } - *dest = 0; -} - -void __ExtractFileExtension (const char *path, char *dest) -{ - const char *src; - - src = path + strlen(path) - 1; - -// -// back up until a . or the start -// - while (src != path && *(src-1) != '.') - src--; - if (src == path) - { - *dest = 0; // no extension - return; - } - - strcpy (dest,src); -} - - -void __ConvertDOSToUnixName( char *dst, const char *src ) -{ - while ( *src ) - { - if ( *src == '\\' ) - *dst = '/'; - else - *dst = *src; - dst++; src++; - } - *dst = 0; -} - - - - - -void AddSlash(Str& str) -{ - int nLen = str.GetLength(); - if (nLen > 0) - { - if (str[nLen-1] != '\\' && str[nLen-1] != '/') - str += '\\'; - } -} - -void FindReplace(Str& strContents, const char* pTag, const char* pValue) -{ - if (strcmp(pTag, pValue) == 0) - return; - for (int nPos = strContents.Find(pTag); nPos >= 0; nPos = strContents.Find(pTag)) - { - int nRightLen = strContents.GetLength() - strlen(pTag) - nPos; - Str strLeft(strContents.Left(nPos)); - Str strRight(strContents.Right(nRightLen)); - strLeft += pValue; - strLeft += strRight; - strContents = strLeft; - } -} - - - - - -void ProgError(char *errstr, ...) -{ - va_list args; - - va_start(args, errstr); - printf("\nProgram Error: *** "); - vprintf(errstr, args); - printf(" ***\n"); - va_end(args); - exit(5); -} - -boolean ReadBytes(FILE *file, void *addr, UInt32 size) -{ - while (size > 0x8000) - { - if (fread(addr, 1, 0x8000, file) != 0x8000) - return false; - addr = (char *)addr + 0x8000; - size -= 0x8000; - } - if (fread(addr, 1, size, file) != size) - return false; - return true; -} -int ReadMagic(FILE *file) -{ - UInt8 buf[4]; - - if (ReadBytes(file, buf, 4) == FALSE) - return FTYPE_ERROR; - if (!strncmp(reinterpret_cast<const char*>(&buf[0]), "IWAD", 4)) - return FTYPE_IWAD; - if (!strncmp(reinterpret_cast<const char*>(&buf[0]), "PWAD", 4)) - return FTYPE_PWAD; - if (!strncmp(reinterpret_cast<const char*>(&buf[0]), "PACK", 4)) - return FTYPE_PACK; - if (!strncmp(reinterpret_cast<const char*>(&buf[0]), "WAD2", 4)) - return FTYPE_WAD2; - if (buf[0] == 0x17 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0) - return FTYPE_BSP; - if (!strncmp(reinterpret_cast<const char*>(&buf[0]), "IDPO", 4)) - return FTYPE_MODEL; - if (!strncmp(reinterpret_cast<const char*>(&buf[0]), "IDSP", 4)) - return FTYPE_SPRITE; - if (!strncmp(reinterpret_cast<const char*>(&buf[0]), "RIFF", 4)) - return FTYPE_WAV; - if (!strncmp(reinterpret_cast<const char*>(&buf[0]), ".snd", 4)) - return FTYPE_AU; - if (buf[0] == 'P') - { - if (buf[1] == '1') - return FTYPE_PBM_ASC; - if (buf[1] == '2') - return FTYPE_PGM_ASC; - if (buf[1] == '3') - return FTYPE_PPM_ASC; - if (buf[1] == '4') - return FTYPE_PBM_RAW; - if (buf[1] == '5') - return FTYPE_PGM_RAW; - if (buf[1] == '6') - return FTYPE_PPM_RAW; - } - if (buf[0] == 'B' && buf[1] == 'M') - return FTYPE_BMP; - if (!strncmp(reinterpret_cast<const char*>(&buf[0]), "GIF8", 4)) - return FTYPE_GIF; - if (buf[0] == 0x0a && buf[1] == 0x05 && buf[2] == 0x01 && buf[3] == 0x08) - return FTYPE_PCX; - return FTYPE_UNKNOWN; -} -FILE *OpenFileReadMagic(const char *filename, int *ftype_r) -{ - FILE *f; - - *ftype_r = FTYPE_ERROR; - if ((f = fopen(filename, "rb")) == NULL) - return NULL; - *ftype_r = ReadMagic(f); - if (*ftype_r == FTYPE_ERROR) - { - fclose(f); - return NULL; - } - return f; -} -boolean WriteBytes(FILE *file, void *addr, UInt32 size) -{ - while (size > 0x8000) - { - if (fwrite(addr, 1, 0x8000, file) != 0x8000) - return FALSE; - addr = (char *)addr + 0x8000; - size -= 0x8000; - } - if (fwrite(addr, 1, size, file) != size) - return FALSE; - return TRUE; -} -char *ConvertFilePath(char *filename) -{ - char *cp; - - if (filename == NULL) - ProgError("BUG: cannot convert a NULL pathname"); - for (cp = filename; *cp; cp++) - if (*cp == '/' || *cp == '\\') - { -#ifdef QEU_DOS - *cp = '\\'; -#else - *cp = '/'; -#endif - } - return filename; -} - -/* - * Read the PACK directory into memory. The optional offset to the - * start of the PACK file is given in "offset". The number of files in - * the directory is returned in *dirsize_r. - */ -PACKDirPtr ReadPACKDirectory(FILE *packfile, UInt32 offset, UInt16 *dirsize_r) -{ - PACKDirPtr dir; - UInt32 pos, size; - UInt16 max, i; - - *dirsize_r = 0; - if (packfile == NULL) - return NULL; - if ((fseek(packfile, offset, SEEK_SET) < 0) - || (ReadMagic(packfile) != FTYPE_PACK) - || (ReadInt32(packfile, &pos) == FALSE) - || (ReadInt32(packfile, &size) == FALSE) - || (size == 0L) - || (size / sizeof(struct PACKDirectory) > 65535L) - || (fseek(packfile, offset + pos, SEEK_SET) < 0)) - return NULL; - dir = (PACKDirPtr)__qmalloc(size); - max = (UInt16)(size / sizeof(struct PACKDirectory)); - for (i = 0; i < max; i++) - { - if (ReadBytes(packfile, &dir[i], sizeof(struct PACKDirectory)) == FALSE) - { - free(dir); - return NULL; - } - ConvertFilePath(dir[i].name); - dir[i].offset = SwapInt32(dir[i].offset); - dir[i].size = SwapInt32(dir[i].size); - } - *dirsize_r = max; - return dir; -} - -/* - * Print the contents of the PACK directory in "outf". - */ -void DumpPACKDirectory(FILE *outf, PACKDirPtr dir, UInt16 dirsize) -{ - UInt16 i; - UInt32 sum; - char buf[57]; - - if (outf == NULL || dir == NULL || dirsize == 0) - return; - fprintf(outf, "num offset size file name\n"); - fprintf(outf, " (hex) (dec)\n"); - sum = 0L; - for (i = 0; i < dirsize; i++) - { - if(!strnicmp(dir[i].name, "textures", 8)) - { - strncpy(buf, dir[i].name, 56); - buf[56] = '\0'; - fprintf(outf, "%3u 0x%08lx %6ld %s\n", - i, dir[i].offset, dir[i].size, buf); - sum += dir[i].size; - } - } - fprintf(outf, "\nTotal size for %3u entries: %7lu bytes.\n", dirsize, sum); - fprintf(outf, "Size of the PACK directory: %7lu bytes.\n", - (UInt32)dirsize * (UInt32)sizeof(struct PACKDirectory)); - fprintf(outf, "Total (header + data + dir): %7lu bytes.\n", - 12L + sum + (UInt32)dirsize * (UInt32)sizeof(struct PACKDirectory)); -} - -void ClearFileList(FILELIST **list) -{ - FILELIST *temp; - - while(*list) - { - temp = *list; - *list = (*list)->next; - free(temp); - } -} - -void ClearDirList(DIRLIST **list) -{ - DIRLIST *temp; - - while(*list) - { - temp = *list; - *list = (*list)->next; - free(temp); - } -} - -DIRECTORY *FindPakDir(DIRECTORY *dir, char *name) -{ - DIRECTORY *currentPtr; - - for(currentPtr = dir; currentPtr; currentPtr = currentPtr->next) - { - if(!stricmp(name, currentPtr->name)) - { - return currentPtr; - } - } - return NULL; -} - - -// LoadPK3FileList -// --------------- -// -// This gets passed a file mask which we want to remove as -// we are only interested in the directory name and any given -// extension. Only handles explicit filenames or *.something -// -boolean LoadPK3FileList(FILELIST **filelist, const char *pattern) -{ - char cSearch[WORK_LEN]; - __ConvertDOSToUnixName( cSearch, pattern ); - char cPath[WORK_LEN]; - char cExt[WORK_LEN]; - char cFile[WORK_LEN]; - char cWork[WORK_LEN]; - __ExtractFilePath(pattern, cPath); - __ExtractFileName(pattern, cFile); - __ExtractFileExtension(pattern, cExt); - const char *pCompare = (strnicmp(cFile, "*.", 2) == 0) ? cExt : cFile; - strcpy(cWork, cPath); - sprintf(cPath, "textures/%s", cWork); - - PK3List *p = g_PK3Files.Next(); - while (p != NULL) - { - // qualify the path - PK3FileInfo *pKey = p->Ptr(); - if (strstr(pKey->m_pName, cPath) && strstr(pKey->m_pName, pCompare)) - { - __ExtractFileName(pKey->m_pName, cWork); - AddToFileListAlphabetized(filelist, cWork, 0, 0, false); - } - p = p->Next(); - } - return (*filelist) != NULL; -} - -boolean GetPackFileList(FILELIST **filelist, char *pattern) -{ - char *str1, *str2; - int i; - DIRECTORY *dummy = paktextures; - FILELIST *temp; - - if (!pakopen) - return false; - - if (g_bPK3) - { - return LoadPK3FileList(filelist, pattern); - } - - str1 = pattern; - - for(i = 0; pattern[i] != '\0'; i++) - { - if(pattern[i] == '\\') - pattern[i] = '/'; - } - - while(strchr(str1, '/')) - { - str2 = strchr(str1, '/'); - *str2++ = '\0'; - dummy = FindPakDir(dummy, str1); - if(!dummy) - return false; - str1 = str2; - } - for(temp = dummy->files; temp; temp=temp->next) - { - AddToFileListAlphabetized(filelist, temp->filename, temp->offset, 0, false); - } - return true; -} - -boolean GetPackTextureDirs(DIRLIST **dirlist) -{ - UInt16 i; - char buf[57]; - - if (!pakopen) - return 1; - - if (g_bPK3) - { - StrList *pl = g_PK3TexturePaths.Next(); - while (pl != NULL) - { - AddToDirListAlphabetized(dirlist, pl->Ref(), 0); - pl = pl->Next(); - } - return true; - } - - for (i = 0; i < dirsize; i++) - { - if(!strnicmp(pakdirptr[i].name, "textures", 8)) - { - strncpy(buf, &(pakdirptr[i].name[9]), 46); - if(strchr(buf, '\\')) - *strchr(buf, '\\') = '\0'; - else if(strchr(buf, '/')) - *strchr(buf, '/') = '\0'; - else - buf[56] = '\0'; - - if(strchr(buf, '.')) - continue; - - AddToDirListAlphabetized(dirlist, buf, 0); - } - } - return true; -} - -boolean AddToDirListAlphabetized(DIRLIST **list, char *dirname, int from) -{ - DIRLIST *currentPtr, *previousPtr, *newPtr; - - strlwr(dirname); - for(currentPtr = *list; currentPtr; currentPtr = currentPtr->next) - { - if(!stricmp(dirname, currentPtr->dirname)) - { - return false; - } - } - previousPtr = NULL; - currentPtr = *list; - - if((newPtr = (DIRLIST *)__qmalloc(sizeof(DIRLIST))) == NULL) - return false; - - strcpy(newPtr->dirname, dirname); - newPtr->from = from; - - while(currentPtr != NULL && stricmp(dirname, currentPtr->dirname) > 0) - { - previousPtr = currentPtr; - currentPtr = currentPtr->next; - } //End while - if(previousPtr == NULL) - { - newPtr->next = *list; - *list = newPtr; - } //End if - else - { - previousPtr->next = newPtr; - newPtr->next = currentPtr; - } //End else - return true; -} - -boolean AddToFileListAlphabetized(FILELIST **list, char *filename, UInt32 offset, UInt32 size, boolean dirs) -{ - FILELIST *currentPtr, *previousPtr, *newPtr; - - for(currentPtr = *list; currentPtr; currentPtr = currentPtr->next) - { - if(!stricmp(filename, currentPtr->filename)) - { - return false; - } - } - previousPtr = NULL; - currentPtr = *list; - - if((newPtr = (FILELIST *)__qmalloc(sizeof(FILELIST))) == NULL) - return false; - - strcpy(newPtr->filename, filename); - newPtr->offset = offset; - newPtr->size = size; - - while(currentPtr != NULL && stricmp(filename, currentPtr->filename) > 0) - { - previousPtr = currentPtr; - currentPtr = currentPtr->next; - } //End while - if(previousPtr == NULL) - { - newPtr->next = *list; - *list = newPtr; - } //End if - else - { - previousPtr->next = newPtr; - newPtr->next = currentPtr; - } //End else - return true; -} - -boolean PakLoadFile(const char *filename, void **bufferptr) -{ - FILELIST *p = NULL; - DIRECTORY *dummy; - void *buffer; - char *str1, *str2; - - if(!pakopen) - return false; - - Str str(filename); - __ConvertDOSToUnixName(str, str); - - dummy = paktextures; - str1 = str; - - while(strchr(str1, '/')) - { - str2 = strchr(str1, '/'); - *str2++ = '\0'; - dummy = FindPakDir(dummy, str1); - if(!dummy) - return false; - str1 = str2; - } - - // FIXME: add error handling routines - for(p = dummy->files; p; p = p->next) - { - if(!stricmp(str1, p->filename)) - { - if (fseek(pakfile[m_nPAKIndex], p->offset, SEEK_SET) < 0) - { - //Sys_Printf("Unexpected EOF in pakfile\n"); - return false; - } - if((buffer = __qmalloc(p->size+5)) == NULL) - //Error("Could not allocate memory"); - - if(fread(buffer, 1, p->size, pakfile[m_nPAKIndex]) != p->size) - { - //Sys_Printf("Error reading %s from pak\n", str1); - free(buffer); - return false; - } - *bufferptr = buffer; - return true; - } - } - return false; -} - -int PakLoadAnyFile(const char *filename, void **bufferptr) -{ - char cWork[WORK_LEN]; - if (g_bPK3) - { - PK3FileInfo *pInfo; - Str strKey; - // need to lookup the file without the base/texture path on it - Str strBase(g_strBasePath); - AddSlash(strBase); - __ConvertDOSToUnixName(cWork, strBase); - Str strFile(filename); - __ConvertDOSToUnixName(strFile, strFile); - strFile.MakeLower(); - strlwr(cWork); - FindReplace(strFile, cWork, ""); - - PK3FileInfo infoFind; - infoFind.m_pName = __StrDup(strFile.GetBuffer()); - PK3List *pList = g_PK3Files.Find(&infoFind); - if (pList) - { - pInfo = pList->Ptr(); - memcpy(pInfo->m_zFile, &pInfo->m_zInfo, sizeof(unz_s)); - if (unzOpenCurrentFile(pInfo->m_zFile) == UNZ_OK) - { - void *buffer = __qblockmalloc(pInfo->m_lSize+1); - int n = unzReadCurrentFile(pInfo->m_zFile , buffer, pInfo->m_lSize); - *bufferptr = buffer; - unzCloseCurrentFile(pInfo->m_zFile); - return n; - } - } -#ifdef LOG_PAKFAIL - sprintf(cWork, "PAK failed on %s\n", filename); - g_LogFile.Log(cWork); -#endif - return -1; - } - - for (int i = 0; i < dirsize; i++) - { - if(!stricmp(filename, pakdirptr[i].name)) - { - if (fseek(pakfile[m_nPAKIndex], pakdirptr[i].offset, SEEK_SET) >= 0) - { - void *buffer = __qmalloc (pakdirptr[i].size+1); - ((char *)buffer)[pakdirptr[i].size] = 0; - if (fread(buffer, 1, pakdirptr[i].size, pakfile[m_nPAKIndex]) == pakdirptr[i].size) - { - *bufferptr = buffer; - return pakdirptr[i].size; - } - } - } - } -#ifdef LOG_PAKFAIL - sprintf(cWork, "PAK failed on %s\n", filename); - g_LogFile.Log(cWork); -#endif - return -1; -} - - - -DIRECTORY *AddPakDir(DIRECTORY **dir, char *name) -{ - DIRECTORY *currentPtr, *previousPtr, *newPtr; - - for(currentPtr = *dir; currentPtr; currentPtr = currentPtr->next) - { - if(!stricmp(name, currentPtr->name)) - { - return currentPtr; - } - } - previousPtr = NULL; - currentPtr = *dir; - - if((newPtr = (DIRECTORY *)__qmalloc(sizeof(DIRECTORY))) == NULL) - return NULL; - - strcpy(newPtr->name, name); - newPtr->files = NULL; - - while(currentPtr != NULL && stricmp(name, currentPtr->name) > 0) - { - previousPtr = currentPtr; - currentPtr = currentPtr->next; - } - if(previousPtr == NULL) - { - newPtr->next = *dir; - *dir = newPtr; - } - else - { - previousPtr->next = newPtr; - newPtr->next = currentPtr; - } - return newPtr; -} - - -// OpenPK3 -// ------- -// Opens a PK3 ( or zip ) file and creates a list of filenames -// and zip info structures -// -boolean OpenPK3(const char *filename) -{ - char cFilename[WORK_LEN]; - char cName[WORK_LEN]; - char cWork[WORK_LEN]; - unz_file_info zInfo; - unzFile *zFile = new unzFile(unzOpen(filename)); - g_zFiles.Add(zFile); - if (zFile != NULL) - { - int nStatus = unzGoToFirstFile(*zFile); - while (nStatus == UNZ_OK) - { - cFilename[0] = '\0'; - unzGetCurrentFileInfo(*zFile, &zInfo, cFilename, WORK_LEN, NULL, 0, NULL, 0); - strlwr(cFilename); - __ConvertDOSToUnixName( cWork, cFilename); - if (strstr(cWork, ".") != NULL) - { - PK3FileInfo *pInfo = new PK3FileInfo(); - pInfo->m_pName = __StrDup(cWork); - memcpy(&pInfo->m_zInfo, (unz_s*)*zFile, sizeof(unz_s)); - pInfo->m_lSize = zInfo.uncompressed_size; - pInfo->m_zFile = *zFile; - g_PK3Files.Add(pInfo); - } - char *p = strstr(cFilename, TEXTURE_PATH); - if (p != NULL) - { - // FIXME: path differences per os ? - // catch solo directory entry - if (strlen(p) > strlen(TEXTURE_PATH) + 1) - { - // skip textures + path seperator - p += strlen(TEXTURE_PATH) + 1; - int nEnd = strcspn(p, PATH_SEPERATORS); - strncpy(cName, p, nEnd); - cName[nEnd] = '\0'; - - boolean bFound = false; - StrList *pl = g_PK3TexturePaths.Next(); - while (pl != NULL) - { - if (strcmpi(pl->Ref(), cName) == 0) - { - // already have this, continue - bFound = true; - break; - } - pl = pl->Next(); - } - if (!bFound) - { - g_PK3TexturePaths.Add(new Str(cName)); - } - } - } - nStatus = unzGoToNextFile(*zFile); - } - } - return (zFile != NULL); -} - -void closePK3(unzFile zf) -{ - unzClose(zf); -} - -void OpenPakFile(const char *filename) -{ - int i; - char *str1, *str2; - DIRECTORY *dummy; - - if(!pakopen) - paktextures = NULL; - - HavePakColormap = false; - - Str strTest(filename); - strTest.MakeLower(); - if (strTest.Find("pk3") >= 0 || strTest.Find("zip") >= 0) - { - pakopen = g_bPK3 = OpenPK3(filename); - return; - } - - - if((pakfile[m_nPAKIndex] = OpenFileReadMagic(filename, &f_type)) == NULL) - { - //FIXME: error routine - //Sys_Printf("ERROR: Could not open %s", filename); - return; - } - if(f_type != FTYPE_PACK) - { - //Sys_Printf("ERROR: %s is not a valid pack file", filename); - if(f_type != FTYPE_ERROR) - fclose(pakfile[m_nPAKIndex]); - return; - } - pakdirptr = ReadPACKDirectory(pakfile[m_nPAKIndex], 0, &dirsize); - if (pakdirptr == NULL) - { - //Sys_Printf("ERROR: Could not read pack directory", filename); - fclose(pakfile[m_nPAKIndex]); - return; - } - if (dirsize == 0) - { - fclose(pakfile[m_nPAKIndex]); - return; - } - for (i = 0; i < dirsize; i++) - { - if(!strnicmp("textures/", pakdirptr[i].name, 9)) - { - dummy = paktextures; - str1 = pakdirptr[i].name+9; - while(strchr(str1, '/')) - { - str2 = strchr(str1, '/'); - *str2++ = '\0'; - dummy = AddPakDir(dummy==paktextures?&paktextures:&dummy, str1); - str1 = str2; - } - - AddToFileListAlphabetized(&(dummy->files), str1, pakdirptr[i].offset, pakdirptr[i].size, true); - } - else if(!strnicmp("pics/colormap.pcx", pakdirptr[i].name, 17)) - { - HavePakColormap = true; - PakColormapOffset = pakdirptr[i].offset; - PakColormapSize = pakdirptr[i].size; - } - } - pakopen = true; - -} - -void ClearPaKDir(DIRECTORY **dir) -{ - DIRECTORY *d1 = *dir, *d2; - - while(d1) - { - ClearFileList(&(d1->files)); - d2 = d1; - d1 = d1->next; - free(d2); - } -} - -void CleanUpPakDirs() -{ - ClearPaKDir(&paktextures); - paktextures = NULL; - dirhead = NULL; - g_PK3TexturePaths.RemoveAll(); - g_PK3Files.RemoveAll(); -} - -void ClosePakFile(void) -{ - if(pakopen) - { - if (g_bPK3) - { - ZFileList *p = g_zFiles.Next(); - while (p != NULL) - { - unzFile uz = p->Ref(); - closePK3(uz); - p = p->Next(); - } - } - else - { - fclose(pakfile[m_nPAKIndex]); - } - } - pakopen = false; - CleanUpPakDirs(); -} - - -void WINAPI InitPakFile(const char * pBasePath, const char *pName) -{ - m_nPAKIndex = 0; - pakopen = false; - paktextures = NULL; - strcpy(g_strBasePath, pBasePath); - if (pName == NULL) - { - char cWork[WORK_LEN]; - Str strPath(pBasePath); - AddSlash(strPath); - strPath += "*.pk3"; - bool bGo = true; - struct _finddata_t fileinfo; - int handle = _findfirst (strPath, &fileinfo); - if (handle != -1) - { - do - { - sprintf(cWork, "%s\\%s", pBasePath, fileinfo.name); - OpenPakFile(cWork); - } while (_findnext( handle, &fileinfo ) != -1); - _findclose (handle); - } - } - else - { - OpenPakFile(pName); - } -} - diff --git a/libs/pak/unzip.cpp b/libs/pak/unzip.cpp deleted file mode 100644 index 8dc82c4..0000000 --- a/libs/pak/unzip.cpp +++ /dev/null @@ -1,4546 +0,0 @@ -/***************************************************************************** - * name: unzip.c - * - * desc: IO on .zip files using portions of zlib - * - * $Archive: /source/code/qcommon/unzip.c $ - * $Author: ttimo $ - * $Revision: 1.1.1.3 $ - * $Modtime: 10/19/99 3:59p $ - * $Date: 2000/01/11 16:37:27 $ - * - *****************************************************************************/ - -#include <stdio.h> -#include <string.h> -#include <windows.h> -#include "unzip.h" -//#include "cmdlib.h" - -/* unzip.h -- IO for uncompress .zip files using zlib - Version 0.15 beta, Mar 19th, 1998, - - Copyright (C) 1998 Gilles Vollant - - This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g - WinZip, InfoZip tools and compatible. - Encryption and multi volume ZipFile (span) are not supported. - Old compressions used by old PKZip 1.x are not supported - - THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE - CAN CHANGE IN FUTURE VERSION !! - I WAIT FEEDBACK at mail info@winimage.com - Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution - - Condition of use and distribution are the same than zlib : - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - -*/ -/* for more info about .ZIP format, see - ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip - PkWare has also a specification at : - ftp://ftp.pkware.com/probdesc.zip */ - -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.1.3, July 9th, 1998 - - Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - - - The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt - (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). -*/ - -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-1998 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id: unzip.cpp,v 1.1.1.3 2000/01/11 16:37:27 ttimo Exp $ */ - -#ifndef _ZCONF_H -#define _ZCONF_H - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -#define OF(args) args -#endif - -typedef unsigned char Byte; /* 8 bits */ -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ -typedef Byte *voidp; - -#ifndef SEEK_SET -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif - -#endif /* _ZCONF_H */ - -#define ZLIB_VERSION "1.1.3" - -/* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed - data. This version of the library supports only one compression method - (deflation) but other algorithms will be added later and will have the same - stream interface. - - Compression can be done in a single step if the buffers are large - enough (for example if an input file is mmap'ed), or can be done by - repeated calls of the compression function. In the latter case, the - application must provide more input and/or consume the output - (providing more output space) before each call. - - The library also supports reading and writing files in gzip (.gz) format - with an interface similar to that of stdio. - - The library does not install any signal handler. The decoder checks - the consistency of the compressed data, so the library should never - crash even in case of corrupted input. -*/ - -/* - The application must update next_in and avail_in when avail_in has - dropped to zero. It must update next_out and avail_out when avail_out - has dropped to zero. The application must initialize zalloc, zfree and - opaque before calling the init function. All other fields are set by the - compression library and must not be updated by the application. - - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the - opaque value. - - zalloc must return Z_NULL if there is not enough memory for the object. - If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. - - On 16-bit systems, the functions zalloc and zfree must be able to allocate - exactly 65536 bytes, but will not be required to allocate more than this - if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, - pointers returned by zalloc for objects of exactly 65536 bytes *must* - have their offset normalized to zero. The default allocation function - provided by this library ensures this (see zutil.c). To reduce memory - requirements and avoid any allocation of 64K objects, at the expense of - compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). - - The fields total_in and total_out can be used for statistics or - progress reports. After compression, total_in holds the total size of - the uncompressed data and may be saved for use in the decompressor - (particularly if the decompressor wants to decompress everything in - a single step). -*/ - - /* constants */ - -#define Z_NO_FLUSH 0 -#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ -#define Z_SYNC_FLUSH 2 -#define Z_FULL_FLUSH 3 -#define Z_FINISH 4 -/* Allowed flush values; see deflate() below for details */ - -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_NEED_DICT 2 -#define Z_ERRNO (-1) -#define Z_STREAM_ERROR (-2) -#define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) -#define Z_VERSION_ERROR (-6) -/* Return codes for the compression/decompression functions. Negative - * values are errors, positive values are used for special but normal events. - */ - -#define Z_NO_COMPRESSION 0 -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 -#define Z_DEFAULT_COMPRESSION (-1) -/* compression levels */ - -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_DEFAULT_STRATEGY 0 -/* compression strategy; see deflateInit2() below for details */ - -#define Z_BINARY 0 -#define Z_ASCII 1 -#define Z_UNKNOWN 2 -/* Possible values of the data_type field */ - -#define Z_DEFLATED 8 -/* The deflate compression method (the only one supported in this version) */ - -#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ - -#define zlib_version zlibVersion() -/* for compatibility with versions < 1.0.2 */ - - /* basic functions */ - -const char * zlibVersion OF((void)); -/* The application can compare zlibVersion and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is - not compatible with the zlib.h header file used by the application. - This check is automatically made by deflateInit and inflateInit. - */ - -/* -int deflateInit OF((z_streamp strm, int level)); - - Initializes the internal stream state for compression. The fields - zalloc, zfree and opaque must be initialized before by the caller. - If zalloc and zfree are set to Z_NULL, deflateInit updates them to - use default allocation functions. - - The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: - 1 gives best speed, 9 gives best compression, 0 gives no compression at - all (the input data is simply copied a block at a time). - Z_DEFAULT_COMPRESSION requests a default compromise between speed and - compression (currently equivalent to level 6). - - deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if level is not a valid compression level, - Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible - with the version assumed by the caller (ZLIB_VERSION). - msg is set to null if there is no error message. deflateInit does not - perform any compression: this will be done by deflate(). -*/ - - -int deflate OF((z_streamp strm, int flush)); -/* - deflate compresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce some - output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. deflate performs one or both of the - following actions: - - - Compress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in and avail_in are updated and - processing will resume at this point for the next call of deflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. This action is forced if the parameter flush is non zero. - Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). - Some output may be provided even if flush is not set. - - Before the call of deflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating avail_in or avail_out accordingly; avail_out - should never be zero before the call. The application can consume the - compressed output when it wants, for example when the output buffer is full - (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK - and with zero avail_out, it must be called again after making room in the - output buffer because there might be more output pending. - - If the parameter flush is set to Z_SYNC_FLUSH, all pending output is - flushed to the output buffer and the output is aligned on a byte boundary, so - that the decompressor can get all input data available so far. (In particular - avail_in is zero after the call if enough output space has been provided - before the call.) Flushing may degrade compression for some compression - algorithms and so it should be used only when necessary. - - If flush is set to Z_FULL_FLUSH, all output is flushed as with - Z_SYNC_FLUSH, and the compression state is reset so that decompression can - restart from this point if previous compressed data has been damaged or if - random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - the compression. - - If deflate returns with avail_out == 0, this function must be called again - with the same value of the flush parameter and more output space (updated - avail_out), until the flush is complete (deflate returns with non-zero - avail_out). - - If the parameter flush is set to Z_FINISH, pending input is processed, - pending output is flushed and deflate returns with Z_STREAM_END if there - was enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the - stream are deflateReset or deflateEnd. - - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least - 0.1% larger than avail_in plus 12 bytes. If deflate does not return - Z_STREAM_END, then it must be called again as described above. - - deflate() sets strm->adler to the adler32 checksum of all input read - so (that is, total_in bytes). - - deflate() may update data_type if it can make a good guess about - the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered - binary. This field is only for information purposes and does not affect - the compression algorithm in any manner. - - deflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if all input has been - consumed and all output has been produced (only when flush is set to - Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). -*/ - - -int deflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the - stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, - msg may be set but then points to a static string (which must not be - deallocated). -*/ - - -/* -int inflateInit OF((z_streamp strm)); - - Initializes the internal stream state for decompression. The fields - next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the exact - value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller. msg is set to null if there is no error - message. inflateInit does not perform any decompression apart from reading - the zlib header if present: this will be done by inflate(). (So next_in and - avail_in may be modified, but next_out and avail_out are unchanged.) -*/ - - -int inflate OF((z_streamp strm, int flush)); -/* - inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may some - introduce some output latency (reading input without producing any output) - except when forced to flush. - - The detailed semantics are as follows. inflate performs one or both of the - following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing - will resume at this point for the next call of inflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there - is no more input data or no more space in the output buffer (see below - about the flush parameter). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating the next_* and avail_* values accordingly. - The application can consume the uncompressed output when it wants, for - example when the output buffer is full (avail_out == 0), or after each - call of inflate(). If inflate returns Z_OK and with zero avail_out, it - must be called again after making room in the output buffer because there - might be more output pending. - - If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much - output as possible to the output buffer. The flushing behavior of inflate is - not specified for values of the flush parameter other than Z_SYNC_FLUSH - and Z_FINISH, but the current implementation actually flushes as much output - as possible anyway. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step - (a single call of inflate), the parameter flush should be set to - Z_FINISH. In this case all pending input is processed and all pending - output is flushed; avail_out must be large enough to hold all the - uncompressed data. (The size of the uncompressed data may have been saved - by the compressor for this purpose.) The next operation on this stream must - be inflateEnd to deallocate the decompression state. The use of Z_FINISH - is never required, but can be used to inform inflate that a faster routine - may be used for the single inflate() call. - - If a preset dictionary is needed at this point (see inflateSetDictionary - below), inflate sets strm-adler to the adler32 checksum of the - dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise - it sets strm->adler to the adler32 checksum of all output produced - so (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or - an error code as described below. At the end of the stream, inflate() - checks that its computed adler32 checksum is equal to that saved by the - compressor and returns Z_STREAM_END only if the checksum is correct. - - inflate() returns Z_OK if some progress has been made (more input processed - or more output produced), Z_STREAM_END if the end of the compressed data has - been reached and all uncompressed output has been produced, Z_NEED_DICT if a - preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect - adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent - (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if no progress is possible or if there was not - enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR - case, the application may then call inflateSync to look for a good - compression block. -*/ - - -int inflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). -*/ - - /* Advanced functions */ - -/* - The following functions are needed only in some special applications. -*/ - -/* -int deflateInit2 OF((z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy)); - - This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by - the caller. - - The method parameter is the compression method. It must be Z_DEFLATED in - this version of the library. - - The windowBits parameter is the base two logarithm of the window size - (the size of the history buffer). It should be in the range 8..15 for this - version of the library. Larger values of this parameter result in better - compression at the expense of memory usage. The default value is 15 if - deflateInit is used instead. - - The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but - is slow and reduces compression ratio; memLevel=9 uses maximum memory - for optimal speed. The default value is 8. See zconf.h for total memory - usage as a function of windowBits and memLevel. - - The strategy parameter is used to tune the compression algorithm. Use the - value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match). Filtered data consists mostly of small values with a - somewhat random distribution. In this case, the compression algorithm is - tuned to compress them better. The effect of Z_FILTERED is to force more - Huffman coding and less string matching; it is somewhat intermediate - between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects - the compression ratio but not the correctness of the compressed output even - if it is not set appropriately. - - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid - method). msg is set to null if there is no error message. deflateInit2 does - not perform any compression: this will be done by deflate(). -*/ - -int deflateSetDictionary OF((z_streamp strm, - const Byte *dictionary, - uInt dictLength)); -/* - Initializes the compression dictionary from the given byte sequence - without producing any compressed output. This function must be called - immediately after deflateInit, deflateInit2 or deflateReset, before any - call of deflate. The compressor and decompressor must use exactly the same - dictionary (see inflateSetDictionary). - - The dictionary should consist of strings (byte sequences) that are likely - to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a - dictionary is most useful when the data to be compressed is short and can be - predicted with good accuracy; the data can then be compressed better than - with the default empty dictionary. - - Depending on the size of the compression data structures selected by - deflateInit or deflateInit2, a part of the dictionary may in effect be - discarded, for example if the dictionary is larger than the window size in - deflate or deflate2. Thus the strings most likely to be useful should be - put at the end of the dictionary, not at the front. - - Upon return of this function, strm->adler is set to the Adler32 value - of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The Adler32 value - applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) - - deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is - inconsistent (for example if deflate has already been called for this stream - or if the compression method is bsort). deflateSetDictionary does not - perform any compression: this will be done by deflate(). -*/ - -int deflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when several compression strategies will be - tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed - by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and - can consume lots of memory. - - deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and - destination. -*/ - -int deflateReset OF((z_streamp strm)); -/* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. - The stream will keep the same compression level and any other attributes - that may have been set by deflateInit2. - - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - -int deflateParams OF((z_streamp strm, - int level, - int strategy)); -/* - Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be - used to switch between compression and straight copy of the input data, or - to switch to a different kind of input data requiring a different - strategy. If the compression level is changed, the input available so far - is compressed with the old level (and may be flushed); the new level will - take effect only at the next call of deflate(). - - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to - be compressed and flushed. In particular, strm->avail_out must be non-zero. - - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR - if strm->avail_out was zero. -*/ - -/* -int inflateInit2 OF((z_streamp strm, - int windowBits)); - - This is another version of inflateInit with an extra parameter. The - fields next_in, avail_in, zalloc, zfree and opaque must be initialized - before by the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library. The default value is 15 if inflateInit is used - instead. If a compressed stream with a larger window size is given as - input, inflate() will return with the error code Z_DATA_ERROR instead of - trying to allocate a larger window. - - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative - memLevel). msg is set to null if there is no error message. inflateInit2 - does not perform any decompression apart from reading the zlib header if - present: this will be done by inflate(). (So next_in and avail_in may be - modified, but next_out and avail_out are unchanged.) -*/ - -int inflateSetDictionary OF((z_streamp strm, - const Byte *dictionary, - uInt dictLength)); -/* - Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate - if this call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the Adler32 value returned by this call of - inflate. The compressor and decompressor must use exactly the same - dictionary (see deflateSetDictionary). - - inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is - inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect Adler32 value). inflateSetDictionary does not - perform any decompression: this will be done by subsequent calls of - inflate(). -*/ - -int inflateSync OF((z_streamp strm)); -/* - Skips invalid compressed data until a full flush point (see above the - description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. - - inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR - if no more input was provided, Z_DATA_ERROR if no flush point has been found, - or Z_STREAM_ERROR if the stream structure was inconsistent. In the success - case, the application may save the current current value of total_in which - indicates where valid compressed data was found. In the error case, the - application may repeatedly call inflateSync, providing more input each time, - until success or end of the input data. -*/ - -int inflateReset OF((z_streamp strm)); -/* - This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. - The stream will keep attributes that may have been set by inflateInit2. - - inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - - - /* utility functions */ - -/* - The following utility functions are implemented on top of the - basic stream-oriented functions. To simplify the interface, some - default options are assumed (compression level and memory usage, - standard memory allocation functions). The source code of these - utility functions can easily be modified if you need special options. -*/ - -int compress OF((Byte *dest, uLong *destLen, - const Byte *source, uLong sourceLen)); -/* - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be at least 0.1% larger than - sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the - compressed buffer. - This function can be used to compress a whole file at once if the - input file is mmap'ed. - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. -*/ - -int compress2 OF((Byte *dest, uLong *destLen, - const Byte *source, uLong sourceLen, - int level)); -/* - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least 0.1% larger than sourceLen plus - 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ - -int uncompress OF((Byte *dest, uLong *destLen, - const Byte *source, uLong sourceLen)); -/* - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. - This function can be used to decompress a whole file at once if the - input file is mmap'ed. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted. -*/ - - -typedef voidp gzFile; - -gzFile gzopen OF((const char *path, const char *mode)); -/* - Opens a gzip (.gz) file for reading or writing. The mode parameter - is as in fopen ("rb" or "wb") but can also include a compression level - ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for - Huffman only compression as in "wb1h". (See the description - of deflateInit2 for more information about the strategy parameter.) - - gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. - - gzopen returns NULL if the file could not be opened or if there was - insufficient memory to allocate the (de)compression state; errno - can be checked to distinguish the two cases (if errno is zero, the - zlib error is Z_MEM_ERROR). */ - -gzFile gzdopen OF((int fd, const char *mode)); -/* - gzdopen() associates a gzFile with the file descriptor fd. File - descriptors are obtained from calls like open, dup, creat, pipe or - fileno (in the file has been previously opened with fopen). - The mode parameter is as in gzopen. - The next call of gzclose on the returned gzFile will also close the - file descriptor fd, just like fclose(fdopen(fd), mode) closes the file - descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). - gzdopen returns NULL if there was insufficient memory to allocate - the (de)compression state. -*/ - -int gzsetparams OF((gzFile file, int level, int strategy)); -/* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. -*/ - -int gzread OF((gzFile file, voidp buf, unsigned len)); -/* - Reads the given number of uncompressed bytes from the compressed file. - If the input file was not in gzip format, gzread copies the given number - of bytes into the buffer. - gzread returns the number of uncompressed bytes actually read (0 for - end of file, -1 for error). */ - -int gzwrite OF((gzFile file, - const voidp buf, unsigned len)); -/* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes actually written - (0 in case of error). -*/ - -int gzprintf OF((gzFile file, const char *format, ...)); -/* - Converts, formats, and writes the args to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written (0 in case of error). -*/ - -int gzputs OF((gzFile file, const char *s)); -/* - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - gzputs returns the number of characters written, or -1 in case of error. -*/ - -char * gzgets OF((gzFile file, char *buf, int len)); -/* - Reads bytes from the compressed file until len-1 characters are read, or - a newline character is read and transferred to buf, or an end-of-file - condition is encountered. The string is then terminated with a null - character. - gzgets returns buf, or Z_NULL in case of error. -*/ - -int gzputc OF((gzFile file, int c)); -/* - Writes c, converted to an unsigned char, into the compressed file. - gzputc returns the value that was written, or -1 in case of error. -*/ - -int gzgetc OF((gzFile file)); -/* - Reads one byte from the compressed file. gzgetc returns this byte - or -1 in case of end of file or error. -*/ - -int gzflush OF((gzFile file, int flush)); -/* - Flushes all pending output into the compressed file. The parameter - flush is as in the deflate() function. The return value is the zlib - error number (see function gzerror below). gzflush returns Z_OK if - the flush parameter is Z_FINISH and all output could be flushed. - gzflush should be called only when strictly necessary because it can - degrade compression. -*/ - -long gzseek OF((gzFile file, - long offset, int whence)); -/* - Sets the starting position for the next gzread or gzwrite on the - given compressed file. The offset represents a number of bytes in the - uncompressed data stream. The whence parameter is defined as in lseek(2); - the value SEEK_END is not supported. - If the file is opened for reading, this function is emulated but can be - extremely slow. If the file is opened for writing, only forward seeks are - supported; gzseek then compresses a sequence of zeroes up to the new - starting position. - - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error, in - particular if the file is opened for writing and the new starting position - would be before the current position. -*/ - -int gzrewind OF((gzFile file)); -/* - Rewinds the given file. This function is supported only for reading. - - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -*/ - -long gztell OF((gzFile file)); -/* - Returns the starting position for the next gzread or gzwrite on the - given compressed file. This position represents a number of bytes in the - uncompressed data stream. - - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -*/ - -int gzeof OF((gzFile file)); -/* - Returns 1 when EOF has previously been detected reading the given - input stream, otherwise zero. -*/ - -int gzclose OF((gzFile file)); -/* - Flushes all pending output if necessary, closes the compressed file - and deallocates all the (de)compression state. The return value is the zlib - error number (see function gzerror below). -*/ - -const char * gzerror OF((gzFile file, int *errnum)); -/* - Returns the error message for the last error which occurred on the - given compressed file. errnum is set to zlib error number. If an - error occurred in the file system and not in the compression library, - errnum is set to Z_ERRNO and the application may consult errno - to get the exact error code. -*/ - - /* checksum functions */ - -/* - These functions are not related to compression but are exported - anyway because they might be useful in applications using the - compression library. -*/ - -uLong adler32 OF((uLong adler, const Byte *buf, uInt len)); - -/* - Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is NULL, this function returns - the required initial value for the checksum. - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed - much faster. Usage example: - - uLong adler = adler32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - adler = adler32(adler, buffer, length); - } - if (adler != original_adler) error(); -*/ - -uLong crc32 OF((uLong crc, const Byte *buf, uInt len)); -/* - Update a running crc with the bytes buf[0..len-1] and return the updated - crc. If buf is NULL, this function returns the required initial value - for the crc. Pre- and post-conditioning (one's complement) is performed - within this function so it shouldn't be done by the application. - Usage example: - - uLong crc = crc32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - crc = crc32(crc, buffer, length); - } - if (crc != original_crc) error(); -*/ - -// private stuff to not include cmdlib.h -/* -============================================================================ - - BYTE ORDER FUNCTIONS - -============================================================================ -*/ - -#ifdef _SGI_SOURCE -#define __BIG_ENDIAN__ -#endif - -#ifdef __BIG_ENDIAN__ - -short __LittleShort (short l) -{ - byte b1,b2; - - b1 = l&255; - b2 = (l>>8)&255; - - return (b1<<8) + b2; -} - -short __BigShort (short l) -{ - return l; -} - - -int __LittleLong (int l) -{ - byte b1,b2,b3,b4; - - b1 = l&255; - b2 = (l>>8)&255; - b3 = (l>>16)&255; - b4 = (l>>24)&255; - - return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; -} - -int __BigLong (int l) -{ - return l; -} - - -float __LittleFloat (float l) -{ - union {byte b[4]; float f;} in, out; - - in.f = l; - out.b[0] = in.b[3]; - out.b[1] = in.b[2]; - out.b[2] = in.b[1]; - out.b[3] = in.b[0]; - - return out.f; -} - -float __BigFloat (float l) -{ - return l; -} - - -#else - - -short __BigShort (short l) -{ - byte b1,b2; - - b1 = l&255; - b2 = (l>>8)&255; - - return (b1<<8) + b2; -} - -short __LittleShort (short l) -{ - return l; -} - - -int __BigLong (int l) -{ - byte b1,b2,b3,b4; - - b1 = l&255; - b2 = (l>>8)&255; - b3 = (l>>16)&255; - b4 = (l>>24)&255; - - return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; -} - -int __LittleLong (int l) -{ - return l; -} - -float __BigFloat (float l) -{ - union {byte b[4]; float f;} in, out; - - in.f = l; - out.b[0] = in.b[3]; - out.b[1] = in.b[2]; - out.b[2] = in.b[1]; - out.b[3] = in.b[0]; - - return out.f; -} - -float __LittleFloat (float l) -{ - return l; -} - - - -#endif - - - - - /* various hacks, don't look :) */ - -/* deflateInit and inflateInit are macros to allow checking the zlib version - * and the compiler's view of z_stream: - */ -int deflateInit_ OF((z_streamp strm, int level, - const char *version, int stream_size)); -int inflateInit_ OF((z_streamp strm, - const char *version, int stream_size)); -int deflateInit2_ OF((z_streamp strm, int level, int method, - int windowBits, int memLevel, - int strategy, const char *version, - int stream_size)); -int inflateInit2_ OF((z_streamp strm, int windowBits, - const char *version, int stream_size)); -#define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) - - -const char * zError OF((int err)); -int inflateSyncPoint OF((z_streamp z)); -const uLong * get_crc_table OF((void)); - -typedef unsigned char uch; -typedef unsigned short ush; -typedef unsigned long ulg; - -extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ -/* (size given to avoid silly warnings with Visual C++) */ - -#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] - -#define ERR_RETURN(strm,err) \ - return (strm->msg = (char*)ERR_MSG(err), (err)) -/* To be used only when the state is known to be valid */ - - /* common constants */ - -#ifndef DEF_WBITS -# define DEF_WBITS MAX_WBITS -#endif -/* default windowBits for decompression. MAX_WBITS is for compression only */ - -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif -/* default memLevel */ - -#define STORED_BLOCK 0 -#define STATIC_TREES 1 -#define DYN_TREES 2 -/* The three kinds of block type */ - -#define MIN_MATCH 3 -#define MAX_MATCH 258 -/* The minimum and maximum match lengths */ - -#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ - - /* target dependencies */ - - /* Common defaults */ - -#ifndef OS_CODE -# define OS_CODE 0x03 /* assume Unix */ -#endif - -#ifndef F_OPEN -# define F_OPEN(name, mode) fopen((name), (mode)) -#endif - - /* functions */ - -#ifdef HAVE_STRERROR - extern char *strerror OF((int)); -# define zstrerror(errnum) strerror(errnum) -#else -# define zstrerror(errnum) "" -#endif - -#define zmemcpy memcpy -#define zmemcmp memcmp -#define zmemzero(dest, len) memset(dest, 0, len) - -/* Diagnostic functions */ -#ifdef _ZIP_DEBUG_ - int z_verbose = 0; -# define Assert(cond,msg) assert(cond); - //{if(!(cond)) Sys_Error(msg);} -# define Trace(x) {if (z_verbose>=0) Sys_Error x ;} -# define Tracev(x) {if (z_verbose>0) Sys_Error x ;} -# define Tracevv(x) {if (z_verbose>1) Sys_Error x ;} -# define Tracec(c,x) {if (z_verbose>0 && (c)) Sys_Error x ;} -# define Tracecv(c,x) {if (z_verbose>1 && (c)) Sys_Error x ;} -#else -# define Assert(cond,msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) -#endif - - -typedef uLong (*check_func) OF((uLong check, const Byte *buf, uInt len)); -voidp zcalloc OF((voidp opaque, unsigned items, unsigned size)); -void zcfree OF((voidp opaque, voidp ptr)); - -#define ZALLOC(strm, items, size) \ - (*((strm)->zalloc))((strm)->opaque, (items), (size)) -#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidp)(addr)) -#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} - - -#if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \ - !defined(CASESENSITIVITYDEFAULT_NO) -#define CASESENSITIVITYDEFAULT_NO -#endif - - -#ifndef UNZ_BUFSIZE -#define UNZ_BUFSIZE (65536) -#endif - -#ifndef UNZ_MAXFILENAMEINZIP -#define UNZ_MAXFILENAMEINZIP (256) -#endif - -#ifndef ALLOC -# define ALLOC(size) (malloc(size)) -#endif -#ifndef TRYFREE -# define TRYFREE(p) {if (p) free(p);} -#endif - -#define SIZECENTRALDIRITEM (0x2e) -#define SIZEZIPLOCALHEADER (0x1e) - - - -/* =========================================================================== - Read a byte from a gz_stream; update next_in and avail_in. Return EOF - for end of file. - IN assertion: the stream s has been sucessfully opened for reading. -*/ - -/* -static int unzlocal_getByte(FILE *fin,int *pi) -{ - unsigned char c; - int err = fread(&c, 1, 1, fin); - if (err==1) - { - *pi = (int)c; - return UNZ_OK; - } - else - { - if (ferror(fin)) - return UNZ_ERRNO; - else - return UNZ_EOF; - } -} -*/ - -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets -*/ -static int unzlocal_getShort (FILE* fin, uLong *pX) -{ - short v; - - fread( &v, sizeof(v), 1, fin ); - - *pX = __LittleShort( v); - return UNZ_OK; - -/* - uLong x ; - int i; - int err; - - err = unzlocal_getByte(fin,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unzlocal_getByte(fin,&i); - x += ((uLong)i)<<8; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -*/ -} - -static int unzlocal_getLong (FILE *fin, uLong *pX) -{ - int v; - - fread( &v, sizeof(v), 1, fin ); - - *pX = __LittleLong( v); - return UNZ_OK; - -/* - uLong x ; - int i; - int err; - - err = unzlocal_getByte(fin,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unzlocal_getByte(fin,&i); - x += ((uLong)i)<<8; - - if (err==UNZ_OK) - err = unzlocal_getByte(fin,&i); - x += ((uLong)i)<<16; - - if (err==UNZ_OK) - err = unzlocal_getByte(fin,&i); - x += ((uLong)i)<<24; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -*/ -} - - -/* My own strcmpi / strcasecmp */ -static int strcmpcasenosensitive_internal (const char* fileName1,const char* fileName2) -{ - for (;;) - { - char c1=*(fileName1++); - char c2=*(fileName2++); - if ((c1>='a') && (c1<='z')) - c1 -= 0x20; - if ((c2>='a') && (c2<='z')) - c2 -= 0x20; - if (c1=='\0') - return ((c2=='\0') ? 0 : -1); - if (c2=='\0') - return 1; - if (c1<c2) - return -1; - if (c1>c2) - return 1; - } -} - - -#ifdef CASESENSITIVITYDEFAULT_NO -#define CASESENSITIVITYDEFAULTVALUE 2 -#else -#define CASESENSITIVITYDEFAULTVALUE 1 -#endif - -#ifndef STRCMPCASENOSENTIVEFUNCTION -#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal -#endif - -/* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi - or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system - (like 1 on Unix, 2 on Windows) - -*/ -extern int unzStringFileNameCompare (const char* fileName1,const char* fileName2,int iCaseSensitivity) -{ - if (iCaseSensitivity==0) - iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; - - if (iCaseSensitivity==1) - return strcmp(fileName1,fileName2); - - return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); -} - -#define BUFREADCOMMENT (0x400) - -/* - Locate the Central directory of a zipfile (at the end, just before - the global comment) -*/ -static uLong unzlocal_SearchCentralDir(FILE *fin) -{ - unsigned char* buf; - uLong uSizeFile; - uLong uBackRead; - uLong uMaxBack=0xffff; /* maximum size of global comment */ - uLong uPosFound=0; - - if (fseek(fin,0,SEEK_END) != 0) - return 0; - - - uSizeFile = ftell( fin ); - - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; - - buf = (unsigned char*)malloc(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; - - uBackRead = 4; - while (uBackRead<uMaxBack) - { - uLong uReadSize,uReadPos ; - int i; - if (uBackRead+BUFREADCOMMENT>uMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); - if (fseek(fin,uReadPos,SEEK_SET)!=0) - break; - - if (fread(buf,(uInt)uReadSize,1,fin)!=1) - break; - - for (i=(int)uReadSize-3; (i--)>0;) - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && - ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) - { - uPosFound = uReadPos+i; - break; - } - - if (uPosFound!=0) - break; - } - free(buf); - return uPosFound; -} - -extern unzFile unzReOpen (const char* path, unzFile file) -{ - unz_s *s; - FILE * fin; - - fin=fopen(path,"rb"); - if (fin==NULL) - return NULL; - - s=(unz_s*)malloc(sizeof(unz_s)); - memcpy(s, (unz_s*)file, sizeof(unz_s)); - - s->file = fin; - return (unzFile)s; -} - -/* - Open a Zip file. path contain the full pathname (by example, - on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer - "zlib/zlib109.zip". - If the zipfile cannot be opened (file don't exist or in not valid), the - return value is NULL. - Else, the return value is a unzFile Handle, usable with other function - of this unzip package. -*/ -extern unzFile unzOpen (const char* path) -{ - unz_s us; - unz_s *s; - uLong central_pos,uL; - FILE * fin ; - - uLong number_disk; /* number of the current dist, used for - spaning ZIP, unsupported, always 0*/ - uLong number_disk_with_CD; /* number the the disk with central dir, used - for spaning ZIP, unsupported, always 0*/ - uLong number_entry_CD; /* total number of entries in - the central dir - (same than number_entry on nospan) */ - - int err=UNZ_OK; - - fin=fopen(path,"rb"); - if (fin==NULL) - return NULL; - - central_pos = unzlocal_SearchCentralDir(fin); - if (central_pos==0) - err=UNZ_ERRNO; - - if (fseek(fin,central_pos,SEEK_SET)!=0) - err=UNZ_ERRNO; - - /* the signature, already checked */ - if (unzlocal_getLong(fin,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of this disk */ - if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of the disk with the start of the central directory */ - if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central dir on this disk */ - if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central dir */ - if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - if ((number_entry_CD!=us.gi.number_entry) || - (number_disk_with_CD!=0) || - (number_disk!=0)) - err=UNZ_BADZIPFILE; - - /* size of the central directory */ - if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - /* offset of start of central directory with respect to the - starting disk number */ - if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - /* zipfile comment length */ - if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK) - err=UNZ_ERRNO; - - if ((central_pos<us.offset_central_dir+us.size_central_dir) && - (err==UNZ_OK)) - err=UNZ_BADZIPFILE; - - if (err!=UNZ_OK) - { - fclose(fin); - return NULL; - } - - us.file=fin; - us.byte_before_the_zipfile = central_pos - - (us.offset_central_dir+us.size_central_dir); - us.central_pos = central_pos; - us.pfile_in_zip_read = NULL; - - - s=(unz_s*)malloc(sizeof(unz_s)); - *s=us; -// unzGoToFirstFile((unzFile)s); - return (unzFile)s; -} - - -/* - Close a ZipFile opened with unzipOpen. - If there is files inside the .Zip opened with unzipOpenCurrentFile (see later), - these files MUST be closed with unzipCloseCurrentFile before call unzipClose. - return UNZ_OK if there is no problem. */ -extern int unzClose (unzFile file) -{ - unz_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - - if (s->pfile_in_zip_read!=NULL) - unzCloseCurrentFile(file); - - fclose(s->file); - free(s); - return UNZ_OK; -} - - -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. */ -extern int unzGetGlobalInfo (unzFile file,unz_global_info *pglobal_info) -{ - unz_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - *pglobal_info=s->gi; - return UNZ_OK; -} - - -/* - Translate date/time from Dos format to tm_unz (readable more easilty) -*/ -static void unzlocal_DosDateToTmuDate (uLong ulDosDate, tm_unz* ptm) -{ - uLong uDate; - uDate = (uLong)(ulDosDate>>16); - ptm->tm_mday = (uInt)(uDate&0x1f) ; - ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; - ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; - - ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); - ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; - ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; -} - -/* - Get Info about the current file in the zipfile, with internal only info -*/ -static int unzlocal_GetCurrentFileInfoInternal (unzFile file, - unz_file_info *pfile_info, - unz_file_info_internal - *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize) -{ - unz_s* s; - unz_file_info file_info; - unz_file_info_internal file_info_internal; - int err=UNZ_OK; - uLong uMagic; - long lSeek=0; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0) - err=UNZ_ERRNO; - - - /* we check the magic */ - if (err==UNZ_OK) - if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x02014b50) - err=UNZ_BADZIPFILE; - - if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK) - err=UNZ_ERRNO; - - unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); - - if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK) - err=UNZ_ERRNO; - - lSeek+=file_info.size_filename; - if ((err==UNZ_OK) && (szFileName!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_filename<fileNameBufferSize) - { - *(szFileName+file_info.size_filename)='\0'; - uSizeRead = file_info.size_filename; - } - else - uSizeRead = fileNameBufferSize; - - if ((file_info.size_filename>0) && (fileNameBufferSize>0)) - if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1) - err=UNZ_ERRNO; - lSeek -= uSizeRead; - } - - - if ((err==UNZ_OK) && (extraField!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_extra<extraFieldBufferSize) - uSizeRead = file_info.size_file_extra; - else - uSizeRead = extraFieldBufferSize; - - if (lSeek!=0) - if (fseek(s->file,lSeek,SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) - if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1) - err=UNZ_ERRNO; - lSeek += file_info.size_file_extra - uSizeRead; - } - else - lSeek+=file_info.size_file_extra; - - - if ((err==UNZ_OK) && (szComment!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_comment<commentBufferSize) - { - *(szComment+file_info.size_file_comment)='\0'; - uSizeRead = file_info.size_file_comment; - } - else - uSizeRead = commentBufferSize; - - if (lSeek!=0) - if (fseek(s->file,lSeek,SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - if ((file_info.size_file_comment>0) && (commentBufferSize>0)) - if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1) - err=UNZ_ERRNO; - lSeek+=file_info.size_file_comment - uSizeRead; - } - else - lSeek+=file_info.size_file_comment; - - if ((err==UNZ_OK) && (pfile_info!=NULL)) - *pfile_info=file_info; - - if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) - *pfile_info_internal=file_info_internal; - - return err; -} - - - -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. -*/ -extern int unzGetCurrentFileInfo ( unzFile file, unz_file_info *pfile_info, - char *szFileName, uLong fileNameBufferSize, - void *extraField, uLong extraFieldBufferSize, - char *szComment, uLong commentBufferSize) -{ - return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, - szFileName,fileNameBufferSize, - extraField,extraFieldBufferSize, - szComment,commentBufferSize); -} - -/* - Set the current file of the zipfile to the first file. - return UNZ_OK if there is no problem -*/ -extern int unzGoToFirstFile (unzFile file) -{ - int err=UNZ_OK; - unz_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - s->pos_in_central_dir=s->offset_central_dir; - s->num_file=0; - err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - - -/* - Set the current file of the zipfile to the next file. - return UNZ_OK if there is no problem - return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -*/ -extern int unzGoToNextFile (unzFile file) -{ - unz_s* s; - int err; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - if (s->num_file+1==s->gi.number_entry) - return UNZ_END_OF_LIST_OF_FILE; - - s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + - s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; - s->num_file++; - err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - - -/* - Try locate the file szFileName in the zipfile. - For the iCaseSensitivity signification, see unzipStringFileNameCompare - - return value : - UNZ_OK if the file is found. It becomes the current file. - UNZ_END_OF_LIST_OF_FILE if the file is not found -*/ -extern int unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity) -{ - unz_s* s; - int err; - - - uLong num_fileSaved; - uLong pos_in_central_dirSaved; - - - if (file==NULL) - return UNZ_PARAMERROR; - - if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) - return UNZ_PARAMERROR; - - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - - num_fileSaved = s->num_file; - pos_in_central_dirSaved = s->pos_in_central_dir; - - err = unzGoToFirstFile(file); - - while (err == UNZ_OK) - { - char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; - unzGetCurrentFileInfo(file,NULL, - szCurrentFileName,sizeof(szCurrentFileName)-1, - NULL,0,NULL,0); - if (unzStringFileNameCompare(szCurrentFileName, - szFileName,iCaseSensitivity)==0) - return UNZ_OK; - err = unzGoToNextFile(file); - } - - s->num_file = num_fileSaved ; - s->pos_in_central_dir = pos_in_central_dirSaved ; - return err; -} - - -/* - Read the static header of the current zipfile - Check the coherency of the static header and info in the end of central - directory about this file - store in *piSizeVar the size of extra info in static header - (filename and size of extra field data) -*/ -static int unzlocal_CheckCurrentFileCoherencyHeader (unz_s* s, uInt* piSizeVar, - uLong *poffset_local_extrafield, - uInt *psize_local_extrafield) -{ - uLong uMagic,uData,uFlags; - uLong size_filename; - uLong size_extra_field; - int err=UNZ_OK; - - *piSizeVar = 0; - *poffset_local_extrafield = 0; - *psize_local_extrafield = 0; - - if (fseek(s->file,s->cur_file_info_internal.offset_curfile + - s->byte_before_the_zipfile,SEEK_SET)!=0) - return UNZ_ERRNO; - - - if (err==UNZ_OK) - if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x04034b50) - err=UNZ_BADZIPFILE; - - if (unzlocal_getShort(s->file,&uData) != UNZ_OK) - err=UNZ_ERRNO; -/* - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) - err=UNZ_BADZIPFILE; -*/ - if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&uData) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) - err=UNZ_BADZIPFILE; - - if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && - (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */ - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - - if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) - err=UNZ_BADZIPFILE; - - *piSizeVar += (uInt)size_filename; - - if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK) - err=UNZ_ERRNO; - *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + - SIZEZIPLOCALHEADER + size_filename; - *psize_local_extrafield = (uInt)size_extra_field; - - *piSizeVar += (uInt)size_extra_field; - - return err; -} - -/* - Open for reading data the current file in the zipfile. - If there is no error and the file is opened, the return value is UNZ_OK. -*/ -extern int unzOpenCurrentFile (unzFile file) -{ - int err=UNZ_OK; - int Store; - uInt iSizeVar; - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - uLong offset_local_extrafield; /* offset of the static extra field */ - uInt size_local_extrafield; /* size of the static extra field */ - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_PARAMERROR; - - if (s->pfile_in_zip_read != NULL) - unzCloseCurrentFile(file); - - if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, - &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) - return UNZ_BADZIPFILE; - - pfile_in_zip_read_info = (file_in_zip_read_info_s*) - malloc(sizeof(file_in_zip_read_info_s)); - if (pfile_in_zip_read_info==NULL) - return UNZ_INTERNALERROR; - - pfile_in_zip_read_info->read_buffer=(char*)malloc(UNZ_BUFSIZE); - pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; - pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; - pfile_in_zip_read_info->pos_local_extrafield=0; - - if (pfile_in_zip_read_info->read_buffer==NULL) - { - free(pfile_in_zip_read_info); - return UNZ_INTERNALERROR; - } - - pfile_in_zip_read_info->stream_initialised=0; - - if ((s->cur_file_info.compression_method!=0) && - (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; - Store = s->cur_file_info.compression_method==0; - - pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; - pfile_in_zip_read_info->crc32=0; - pfile_in_zip_read_info->compression_method = - s->cur_file_info.compression_method; - pfile_in_zip_read_info->file=s->file; - pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; - - pfile_in_zip_read_info->stream.total_out = 0; - - if (!Store) - { - pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; - pfile_in_zip_read_info->stream.zfree = (free_func)0; - pfile_in_zip_read_info->stream.opaque = (voidp)0; - - err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); - if (err == Z_OK) - pfile_in_zip_read_info->stream_initialised=1; - /* windowBits is passed < 0 to tell that there is no zlib header. - * Note that in this case inflate *requires* an extra "dummy" byte - * after the compressed stream in order to complete decompression and - * return Z_STREAM_END. - * In unzip, i don't wait absolutely Z_STREAM_END because I known the - * size of both compressed and uncompressed data - */ - } - pfile_in_zip_read_info->rest_read_compressed = - s->cur_file_info.compressed_size ; - pfile_in_zip_read_info->rest_read_uncompressed = - s->cur_file_info.uncompressed_size ; - - - pfile_in_zip_read_info->pos_in_zipfile = - s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + - iSizeVar; - - pfile_in_zip_read_info->stream.avail_in = (uInt)0; - - - s->pfile_in_zip_read = pfile_in_zip_read_info; - return UNZ_OK; -} - - -/* - Read bytes from the current file. - buf contain buffer where data must be copied - len the size of buf. - - return the number of byte copied if somes bytes are copied - return 0 if the end of file was reached - return <0 with error code if there is an error - (UNZ_ERRNO for IO error, or zLib error for uncompress error) -*/ -extern int unzReadCurrentFile (unzFile file, void *buf, unsigned len) -{ - int err=UNZ_OK; - uInt iRead = 0; - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if ((pfile_in_zip_read_info->read_buffer == NULL)) - return UNZ_END_OF_LIST_OF_FILE; - if (len==0) - return 0; - - pfile_in_zip_read_info->stream.next_out = (Byte*)buf; - - pfile_in_zip_read_info->stream.avail_out = (uInt)len; - - if (len>pfile_in_zip_read_info->rest_read_uncompressed) - pfile_in_zip_read_info->stream.avail_out = - (uInt)pfile_in_zip_read_info->rest_read_uncompressed; - - while (pfile_in_zip_read_info->stream.avail_out>0) - { - if ((pfile_in_zip_read_info->stream.avail_in==0) && - (pfile_in_zip_read_info->rest_read_compressed>0)) - { - uInt uReadThis = UNZ_BUFSIZE; - if (pfile_in_zip_read_info->rest_read_compressed<uReadThis) - uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed; - if (uReadThis == 0) - return UNZ_EOF; - if (s->cur_file_info.compressed_size == pfile_in_zip_read_info->rest_read_compressed) - if (fseek(pfile_in_zip_read_info->file, - pfile_in_zip_read_info->pos_in_zipfile + - pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0) - return UNZ_ERRNO; - if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1, - pfile_in_zip_read_info->file)!=1) - return UNZ_ERRNO; - pfile_in_zip_read_info->pos_in_zipfile += uReadThis; - - pfile_in_zip_read_info->rest_read_compressed-=uReadThis; - - pfile_in_zip_read_info->stream.next_in = - (Byte*)pfile_in_zip_read_info->read_buffer; - pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; - } - - if (pfile_in_zip_read_info->compression_method==0) - { - uInt uDoCopy,i ; - if (pfile_in_zip_read_info->stream.avail_out < - pfile_in_zip_read_info->stream.avail_in) - uDoCopy = pfile_in_zip_read_info->stream.avail_out ; - else - uDoCopy = pfile_in_zip_read_info->stream.avail_in ; - - for (i=0;i<uDoCopy;i++) - *(pfile_in_zip_read_info->stream.next_out+i) = - *(pfile_in_zip_read_info->stream.next_in+i); - - pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, - pfile_in_zip_read_info->stream.next_out, - uDoCopy); - pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; - pfile_in_zip_read_info->stream.avail_in -= uDoCopy; - pfile_in_zip_read_info->stream.avail_out -= uDoCopy; - pfile_in_zip_read_info->stream.next_out += uDoCopy; - pfile_in_zip_read_info->stream.next_in += uDoCopy; - pfile_in_zip_read_info->stream.total_out += uDoCopy; - iRead += uDoCopy; - } - else - { - uLong uTotalOutBefore,uTotalOutAfter; - const Byte *bufBefore; - uLong uOutThis; - int flush=Z_SYNC_FLUSH; - - uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; - bufBefore = pfile_in_zip_read_info->stream.next_out; - - /* - if ((pfile_in_zip_read_info->rest_read_uncompressed == - pfile_in_zip_read_info->stream.avail_out) && - (pfile_in_zip_read_info->rest_read_compressed == 0)) - flush = Z_FINISH; - */ - err=inflate(&pfile_in_zip_read_info->stream,flush); - - uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; - uOutThis = uTotalOutAfter-uTotalOutBefore; - - pfile_in_zip_read_info->crc32 = - crc32(pfile_in_zip_read_info->crc32,bufBefore, - (uInt)(uOutThis)); - - pfile_in_zip_read_info->rest_read_uncompressed -= - uOutThis; - - iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); - - if (err==Z_STREAM_END) - return (iRead==0) ? UNZ_EOF : iRead; - if (err!=Z_OK) - break; - } - } - - if (err==Z_OK) - return iRead; - return err; -} - - -/* - Give the current position in uncompressed data -*/ -extern long unztell (unzFile file) -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - return (long)pfile_in_zip_read_info->stream.total_out; -} - - -/* - return 1 if the end of file was reached, 0 elsewhere -*/ -extern int unzeof (unzFile file) -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - if (pfile_in_zip_read_info->rest_read_uncompressed == 0) - return 1; - else - return 0; -} - - - -/* - Read extra field from the current file (opened by unzOpenCurrentFile) - This is the static-header version of the extra field (sometimes, there is - more info in the static-header version than in the central-header) - - if buf==NULL, it return the size of the static extra field that can be read - - if buf!=NULL, len is the size of the buffer, the extra header is copied in - buf. - the return value is the number of bytes copied in buf, or (if <0) - the error code -*/ -extern int unzGetLocalExtrafield (unzFile file,void *buf,unsigned len) -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - uInt read_now; - uLong size_to_read; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - size_to_read = (pfile_in_zip_read_info->size_local_extrafield - - pfile_in_zip_read_info->pos_local_extrafield); - - if (buf==NULL) - return (int)size_to_read; - - if (len>size_to_read) - read_now = (uInt)size_to_read; - else - read_now = (uInt)len ; - - if (read_now==0) - return 0; - - if (fseek(pfile_in_zip_read_info->file, - pfile_in_zip_read_info->offset_local_extrafield + - pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0) - return UNZ_ERRNO; - - if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1) - return UNZ_ERRNO; - - return (int)read_now; -} - -/* - Close the file in zip opened with unzipOpenCurrentFile - Return UNZ_CRCERROR if all the file was read but the CRC is not good -*/ -extern int unzCloseCurrentFile (unzFile file) -{ - int err=UNZ_OK; - - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if (pfile_in_zip_read_info->rest_read_uncompressed == 0) - { - if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) - err=UNZ_CRCERROR; - } - - - free(pfile_in_zip_read_info->read_buffer); - pfile_in_zip_read_info->read_buffer = NULL; - if (pfile_in_zip_read_info->stream_initialised) - inflateEnd(&pfile_in_zip_read_info->stream); - - pfile_in_zip_read_info->stream_initialised = 0; - free(pfile_in_zip_read_info); - - s->pfile_in_zip_read=NULL; - - return err; -} - - -/* - Get the global comment string of the ZipFile, in the szComment buffer. - uSizeBuf is the size of the szComment buffer. - return the number of byte copied or an error code <0 -*/ -extern int unzGetGlobalComment (unzFile file, char *szComment, uLong uSizeBuf) -{ - unz_s* s; - uLong uReadThis ; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - - uReadThis = uSizeBuf; - if (uReadThis>s->gi.size_comment) - uReadThis = s->gi.size_comment; - - if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0) - return UNZ_ERRNO; - - if (uReadThis>0) - { - *szComment='\0'; - if (fread(szComment,(uInt)uReadThis,1,s->file)!=1) - return UNZ_ERRNO; - } - - if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) - *(szComment+s->gi.size_comment)='\0'; - return (int)uReadThis; -} - -/* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id: unzip.cpp,v 1.1.1.3 2000/01/11 16:37:27 ttimo Exp $ */ - -#ifdef DYNAMIC_CRC_TABLE - -static int crc_table_empty = 1; -static uLong crc_table[256]; -static void make_crc_table OF((void)); - -/* - Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: - x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. - - Polynomials over GF(2) are represented in binary, one bit per coefficient, - with the lowest powers in the most significant bit. Then adding polynomials - is just exclusive-or, and multiplying a polynomial by x is a right shift by - one. If we call the above polynomial p, and represent a byte as the - polynomial q, also with the lowest power in the most significant bit (so the - byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, - where a mod b means the remainder after dividing a by b. - - This calculation is done using the shift-register method of multiplying and - taking the remainder. The register is initialized to zero, and for each - incoming bit, x^32 is added mod p to the register if the bit is a one (where - x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by - x (which is shifting right by one and adding x^32 mod p if the bit shifted - out is a one). We start with the highest power (least significant bit) of - q and repeat for all eight bits of q. - - The table is simply the CRC of all possible eight bit values. This is all - the information needed to generate CRC's on data a byte at a time for all - combinations of CRC register values and incoming bytes. -*/ -static void make_crc_table() -{ - uLong c; - int n, k; - uLong poly; /* polynomial exclusive-or pattern */ - /* terms of polynomial defining this crc (except x^32): */ - static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; - - /* make exclusive-or pattern from polynomial (0xedb88320L) */ - poly = 0L; - for (n = 0; n < sizeof(p)/sizeof(Byte); n++) - poly |= 1L << (31 - p[n]); - - for (n = 0; n < 256; n++) - { - c = (uLong)n; - for (k = 0; k < 8; k++) - c = c & 1 ? poly ^ (c >> 1) : c >> 1; - crc_table[n] = c; - } - crc_table_empty = 0; -} -#else -/* ======================================================================== - * Table of CRC-32's of all single-byte values (made by make_crc_table) - */ -static const uLong crc_table[256] = { - 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, - 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, - 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, - 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, - 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, - 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, - 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, - 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, - 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, - 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, - 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, - 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, - 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, - 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, - 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, - 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, - 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, - 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, - 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, - 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, - 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, - 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, - 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, - 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, - 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, - 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, - 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, - 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, - 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, - 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, - 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, - 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, - 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, - 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, - 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, - 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, - 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, - 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, - 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, - 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, - 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, - 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, - 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, - 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, - 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, - 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, - 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, - 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, - 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, - 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, - 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, - 0x2d02ef8dL -}; -#endif - -/* ========================================================================= - * This function can be used by asm versions of crc32() - */ -const uLong * get_crc_table() -{ -#ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) make_crc_table(); -#endif - return (const uLong *)crc_table; -} - -/* ========================================================================= */ -#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); -#define DO2(buf) DO1(buf); DO1(buf); -#define DO4(buf) DO2(buf); DO2(buf); -#define DO8(buf) DO4(buf); DO4(buf); - -/* ========================================================================= */ -uLong crc32(uLong crc, const Byte *buf, uInt len) -{ - if (buf == Z_NULL) return 0L; -#ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); -#endif - crc = crc ^ 0xffffffffL; - while (len >= 8) - { - DO8(buf); - len -= 8; - } - if (len) do { - DO1(buf); - } while (--len); - return crc ^ 0xffffffffL; -} - -/* infblock.h -- header to use infblock.c - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -struct inflate_blocks_state; -typedef struct inflate_blocks_state inflate_blocks_statef; - -extern inflate_blocks_statef * inflate_blocks_new OF(( - z_streamp z, - check_func c, /* check function */ - uInt w)); /* window size */ - -extern int inflate_blocks OF(( - inflate_blocks_statef *, - z_streamp , - int)); /* initial return code */ - -extern void inflate_blocks_reset OF(( - inflate_blocks_statef *, - z_streamp , - uLong *)); /* check value on output */ - -extern int inflate_blocks_free OF(( - inflate_blocks_statef *, - z_streamp)); - -extern void inflate_set_dictionary OF(( - inflate_blocks_statef *s, - const Byte *d, /* dictionary */ - uInt n)); /* dictionary length */ - -extern int inflate_blocks_sync_point OF(( - inflate_blocks_statef *s)); - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - -/* Table for deflate from PKZIP's appnote.txt. */ -static const uInt border[] = { /* Order of the bit length code lengths */ - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - -/* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* Huffman code lookup table entry--this entry is four bytes for machines - that have 16-bit pointers (e.g. PC's in the small or medium model). */ - -typedef struct inflate_huft_s inflate_huft; - -struct inflate_huft_s { - union { - struct { - Byte Exop; /* number of extra bits or operation */ - Byte Bits; /* number of bits in this code or subcode */ - } what; - uInt pad; /* pad structure to a power of 2 (4 bytes for */ - } word; /* 16-bit, 8 bytes for 32-bit int's) */ - uInt base; /* literal, length base, distance base, - or table offset */ -}; - -/* Maximum size of dynamic tree. The maximum found in a long but non- - exhaustive search was 1004 huft structures (850 for length/literals - and 154 for distances, the latter actually the result of an - exhaustive search). The actual maximum is not known, but the - value below is more than safe. */ -#define MANY 1440 - -extern int inflate_trees_bits OF(( - uInt *, /* 19 code lengths */ - uInt *, /* bits tree desired/actual depth */ - inflate_huft * *, /* bits tree result */ - inflate_huft *, /* space for trees */ - z_streamp)); /* for messages */ - -extern int inflate_trees_dynamic OF(( - uInt, /* number of literal/length codes */ - uInt, /* number of distance codes */ - uInt *, /* that many (total) code lengths */ - uInt *, /* literal desired/actual bit depth */ - uInt *, /* distance desired/actual bit depth */ - inflate_huft * *, /* literal/length tree result */ - inflate_huft * *, /* distance tree result */ - inflate_huft *, /* space for trees */ - z_streamp)); /* for messages */ - -extern int inflate_trees_fixed OF(( - uInt *, /* literal desired/actual bit depth */ - uInt *, /* distance desired/actual bit depth */ - inflate_huft * *, /* literal/length tree result */ - inflate_huft * *, /* distance tree result */ - z_streamp)); /* for memory allocation */ - - -/* infcodes.h -- header to use infcodes.c - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -struct inflate_codes_state; -typedef struct inflate_codes_state inflate_codes_statef; - -extern inflate_codes_statef *inflate_codes_new OF(( - uInt, uInt, - inflate_huft *, inflate_huft *, - z_streamp )); - -extern int inflate_codes OF(( - inflate_blocks_statef *, - z_streamp , - int)); - -extern void inflate_codes_free OF(( - inflate_codes_statef *, - z_streamp )); - -/* infutil.h -- types and macros common to blocks and codes - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -#ifndef _INFUTIL_H -#define _INFUTIL_H - -typedef enum { - TYPE, /* get type bits (3, including end bit) */ - LENS, /* get lengths for stored */ - STORED, /* processing stored block */ - TABLE, /* get table lengths */ - BTREE, /* get bit lengths tree for a dynamic block */ - DTREE, /* get length, distance trees for a dynamic block */ - CODES, /* processing fixed or dynamic block */ - DRY, /* output remaining window bytes */ - DONE, /* finished last block, done */ - BAD} /* got a data error--stuck here */ -inflate_block_mode; - -/* inflate blocks semi-private state */ -struct inflate_blocks_state { - - /* mode */ - inflate_block_mode mode; /* current inflate_block mode */ - - /* mode dependent information */ - union { - uInt left; /* if STORED, bytes left to copy */ - struct { - uInt table; /* table lengths (14 bits) */ - uInt index; /* index into blens (or border) */ - uInt *blens; /* bit lengths of codes */ - uInt bb; /* bit length tree depth */ - inflate_huft *tb; /* bit length decoding tree */ - } trees; /* if DTREE, decoding info for trees */ - struct { - inflate_codes_statef - *codes; - } decode; /* if CODES, current state */ - } sub; /* submode */ - uInt last; /* true if this block is the last block */ - - /* mode independent information */ - uInt bitk; /* bits in bit buffer */ - uLong bitb; /* bit buffer */ - inflate_huft *hufts; /* single malloc for tree space */ - Byte *window; /* sliding window */ - Byte *end; /* one byte after sliding window */ - Byte *read; /* window read pointer */ - Byte *write; /* window write pointer */ - check_func checkfn; /* check function */ - uLong check; /* check on output */ - -}; - - -/* defines for inflate input/output */ -/* update pointers and return */ -#define UPDBITS {s->bitb=b;s->bitk=k;} -#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} -#define UPDOUT {s->write=q;} -#define UPDATE {UPDBITS UPDIN UPDOUT} -#define LEAVE {UPDATE return inflate_flush(s,z,r);} -/* get bytes and bits */ -#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} -#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} -#define NEXTBYTE (n--,*p++) -#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}} -#define DUMPBITS(j) {b>>=(j);k-=(j);} -/* output bytes */ -#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q) -#define LOADOUT {q=s->write;m=(uInt)WAVAIL;} -#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} -#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} -#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} -#define OUTBYTE(a) {*q++=(Byte)(a);m--;} -/* load static pointers */ -#define LOAD {LOADIN LOADOUT} - -/* masks for lower bits (size given to avoid silly warnings with Visual C++) */ -extern uInt inflate_mask[17]; - -/* copy as much as possible from the sliding window to the output area */ -extern int inflate_flush OF(( - inflate_blocks_statef *, - z_streamp , - int)); - -#endif - - -/* - Notes beyond the 1.93a appnote.txt: - - 1. Distance pointers never point before the beginning of the output - stream. - 2. Distance pointers can point back across blocks, up to 32k away. - 3. There is an implied maximum of 7 bits for the bit length table and - 15 bits for the actual data. - 4. If only one code exists, then it is encoded using one bit. (Zero - would be more efficient, but perhaps a little confusing.) If two - codes exist, they are coded using one bit each (0 and 1). - 5. There is no way of sending zero distance codes--a dummy must be - sent if there are none. (History: a pre 2.0 version of PKZIP would - store blocks with no distance codes, but this was discovered to be - too harsh a criterion.) Valid only for 1.93a. 2.04c does allow - zero distance codes, which is sent as one code of zero bits in - length. - 6. There are up to 286 literal/length codes. Code 256 represents the - end-of-block. Note however that the static length tree defines - 288 codes just to fill out the Huffman codes. Codes 286 and 287 - cannot be used though, since there is no length base or extra bits - defined for them. Similarily, there are up to 30 distance codes. - However, static trees define 32 codes (all 5 bits) to fill out the - Huffman codes, but the last two had better not show up in the data. - 7. Unzip can check dynamic Huffman blocks for complete code sets. - The exception is that a single code would not be complete (see #4). - 8. The five bits following the block type is really the number of - literal codes sent minus 257. - 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits - (1+6+6). Therefore, to output three times the length, you output - three codes (1+1+1), whereas to output four times the same length, - you only need two codes (1+3). Hmm. - 10. In the tree reconstruction algorithm, Code = Code + Increment - only if BitLength(i) is not zero. (Pretty obvious.) - 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) - 12. Note: length code 284 can represent 227-258, but length code 285 - really is 258. The last length deserves its own, short code - since it gets used a lot in very redundant files. The length - 258 is special since 258 - 3 (the min match length) is 255. - 13. The literal/length and distance code bit lengths are read as a - single stream of lengths. It is possible (and advantageous) for - a repeat code (16, 17, or 18) to go across the boundary between - the two sets of lengths. - */ - - -void inflate_blocks_reset(inflate_blocks_statef *s, z_streamp z, uLong *c) -{ - if (c != Z_NULL) - *c = s->check; - if (s->mode == BTREE || s->mode == DTREE) - ZFREE(z, s->sub.trees.blens); - if (s->mode == CODES) - inflate_codes_free(s->sub.decode.codes, z); - s->mode = TYPE; - s->bitk = 0; - s->bitb = 0; - s->read = s->write = s->window; - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(0L, (const Byte *)Z_NULL, 0); - Tracev(("inflate: blocks reset\n")); -} - - -inflate_blocks_statef *inflate_blocks_new(z_streamp z, check_func c, uInt w) -{ - inflate_blocks_statef *s; - - if ((s = (inflate_blocks_statef *)ZALLOC - (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) - return s; - if ((s->hufts = - (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL) - { - ZFREE(z, s); - return Z_NULL; - } - if ((s->window = (Byte *)ZALLOC(z, 1, w)) == Z_NULL) - { - ZFREE(z, s->hufts); - ZFREE(z, s); - return Z_NULL; - } - s->end = s->window + w; - s->checkfn = c; - s->mode = TYPE; - Tracev(("inflate: blocks allocated\n")); - inflate_blocks_reset(s, z, Z_NULL); - return s; -} - - -int inflate_blocks(inflate_blocks_statef *s, z_streamp z, int r) -{ - uInt t; /* temporary storage */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Byte *p; /* input data pointer */ - uInt n; /* bytes available there */ - Byte *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - - /* copy input/output information to locals (UPDATE macro restores) */ - LOAD - - /* process input based on current state */ - while (1) switch (s->mode) - { - case TYPE: - NEEDBITS(3) - t = (uInt)b & 7; - s->last = t & 1; - switch (t >> 1) - { - case 0: /* stored */ - Tracev(("inflate: stored block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - t = k & 7; /* go to byte boundary */ - DUMPBITS(t) - s->mode = LENS; /* get length of stored block */ - break; - case 1: /* fixed */ - Tracev(("inflate: fixed codes block%s\n", - s->last ? " (last)" : "")); - { - uInt bl, bd; - inflate_huft *tl, *td; - - inflate_trees_fixed(&bl, &bd, &tl, &td, z); - s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); - if (s->sub.decode.codes == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - } - DUMPBITS(3) - s->mode = CODES; - break; - case 2: /* dynamic */ - Tracev(("inflate: dynamic codes block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - s->mode = TABLE; - break; - case 3: /* illegal */ - DUMPBITS(3) - s->mode = BAD; - z->msg = (char*)"invalid block type"; - r = Z_DATA_ERROR; - LEAVE - } - break; - case LENS: - NEEDBITS(32) - if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) - { - s->mode = BAD; - z->msg = (char*)"invalid stored block lengths"; - r = Z_DATA_ERROR; - LEAVE - } - s->sub.left = (uInt)b & 0xffff; - b = k = 0; /* dump bits */ - Tracev(("inflate: stored length %u\n", s->sub.left)); - s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); - break; - case STORED: - if (n == 0) - LEAVE - NEEDOUT - t = s->sub.left; - if (t > n) t = n; - if (t > m) t = m; - zmemcpy(q, p, t); - p += t; n -= t; - q += t; m -= t; - if ((s->sub.left -= t) != 0) - break; - Tracev(("inflate: stored end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - s->mode = s->last ? DRY : TYPE; - break; - case TABLE: - NEEDBITS(14) - s->sub.trees.table = t = (uInt)b & 0x3fff; -#ifndef PKZIP_BUG_WORKAROUND - if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) - { - s->mode = BAD; - z->msg = (char*)"too many length or distance symbols"; - r = Z_DATA_ERROR; - LEAVE - } -#endif - t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); - if ((s->sub.trees.blens = (uInt*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - DUMPBITS(14) - s->sub.trees.index = 0; - Tracev(("inflate: table sizes ok\n")); - s->mode = BTREE; - case BTREE: - while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) - { - NEEDBITS(3) - s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; - DUMPBITS(3) - } - while (s->sub.trees.index < 19) - s->sub.trees.blens[border[s->sub.trees.index++]] = 0; - s->sub.trees.bb = 7; - t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, - &s->sub.trees.tb, s->hufts, z); - if (t != Z_OK) - { - ZFREE(z, s->sub.trees.blens); - r = t; - if (r == Z_DATA_ERROR) - s->mode = BAD; - LEAVE - } - s->sub.trees.index = 0; - Tracev(("inflate: bits tree ok\n")); - s->mode = DTREE; - case DTREE: - while (t = s->sub.trees.table, - s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) - { - inflate_huft *h; - uInt i, j, c; - - t = s->sub.trees.bb; - NEEDBITS(t) - h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); - t = h->bits; - c = h->base; - if (c < 16) - { - DUMPBITS(t) - s->sub.trees.blens[s->sub.trees.index++] = c; - } - else /* c == 16..18 */ - { - i = c == 18 ? 7 : c - 14; - j = c == 18 ? 11 : 3; - NEEDBITS(t + i) - DUMPBITS(t) - j += (uInt)b & inflate_mask[i]; - DUMPBITS(i) - i = s->sub.trees.index; - t = s->sub.trees.table; - if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || - (c == 16 && i < 1)) - { - ZFREE(z, s->sub.trees.blens); - s->mode = BAD; - z->msg = (char*)"invalid bit length repeat"; - r = Z_DATA_ERROR; - LEAVE - } - c = c == 16 ? s->sub.trees.blens[i - 1] : 0; - do { - s->sub.trees.blens[i++] = c; - } while (--j); - s->sub.trees.index = i; - } - } - s->sub.trees.tb = Z_NULL; - { - uInt bl, bd; - inflate_huft *tl, *td; - inflate_codes_statef *c; - - bl = 9; /* must be <= 9 for lookahead assumptions */ - bd = 6; /* must be <= 9 for lookahead assumptions */ - t = s->sub.trees.table; - t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), - s->sub.trees.blens, &bl, &bd, &tl, &td, - s->hufts, z); - ZFREE(z, s->sub.trees.blens); - if (t != Z_OK) - { - if (t == (uInt)Z_DATA_ERROR) - s->mode = BAD; - r = t; - LEAVE - } - Tracev(("inflate: trees ok\n")); - if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - s->sub.decode.codes = c; - } - s->mode = CODES; - case CODES: - UPDATE - if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) - return inflate_flush(s, z, r); - r = Z_OK; - inflate_codes_free(s->sub.decode.codes, z); - LOAD - Tracev(("inflate: codes end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - if (!s->last) - { - s->mode = TYPE; - break; - } - s->mode = DRY; - case DRY: - FLUSH - if (s->read != s->write) - LEAVE - s->mode = DONE; - case DONE: - r = Z_STREAM_END; - LEAVE - case BAD: - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -} - - -int inflate_blocks_free(inflate_blocks_statef *s, z_streamp z) -{ - inflate_blocks_reset(s, z, Z_NULL); - ZFREE(z, s->window); - ZFREE(z, s->hufts); - ZFREE(z, s); - Tracev(("inflate: blocks freed\n")); - return Z_OK; -} - - -void inflate_set_dictionary(inflate_blocks_statef *s, const Byte *d, uInt n) -{ - zmemcpy(s->window, d, n); - s->read = s->write = s->window + n; -} - - -/* Returns true if inflate is currently at the end of a block generated - * by Z_SYNC_FLUSH or Z_FULL_FLUSH. - * IN assertion: s != Z_NULL - */ -int inflate_blocks_sync_point(inflate_blocks_statef *s) -{ - return s->mode == LENS; -} - - -/* And'ing with mask[n] masks the lower n bits */ -uInt inflate_mask[17] = { - 0x0000, - 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, - 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff -}; - - -/* copy as much as possible from the sliding window to the output area */ -int inflate_flush(inflate_blocks_statef *s, z_streamp z, int r) -{ - uInt n; - Byte *p; - Byte *q; - - /* static copies of source and destination pointers */ - p = z->next_out; - q = s->read; - - /* compute number of bytes to copy as as end of window */ - n = (uInt)((q <= s->write ? s->write : s->end) - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - /* update counters */ - z->avail_out -= n; - z->total_out += n; - - /* update check information */ - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(s->check, q, n); - - /* copy as as end of window */ - zmemcpy(p, q, n); - p += n; - q += n; - - /* see if more to copy at beginning of window */ - if (q == s->end) - { - /* wrap pointers */ - q = s->window; - if (s->write == s->end) - s->write = s->window; - - /* compute bytes to copy */ - n = (uInt)(s->write - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - /* update counters */ - z->avail_out -= n; - z->total_out += n; - - /* update check information */ - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(s->check, q, n); - - /* copy */ - zmemcpy(p, q, n); - p += n; - q += n; - } - - /* update pointers */ - z->next_out = p; - s->read = q; - - /* done */ - return r; -} - -/* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -const char inflate_copyright[] = - " inflate 1.1.3 Copyright 1995-1998 Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - - -static int huft_build OF(( - uInt *, /* code lengths in bits */ - uInt, /* number of codes */ - uInt, /* number of "simple" codes */ - const uInt *, /* list of base values for non-simple codes */ - const uInt *, /* list of extra bits for non-simple codes */ - inflate_huft **, /* result: starting table */ - uInt *, /* maximum lookup bits (returns actual) */ - inflate_huft *, /* space for trees */ - uInt *, /* hufts used in space */ - uInt * )); /* space for values */ - -/* Tables for deflate from PKZIP's appnote.txt. */ -static const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - /* see note #13 above about 258 */ -static const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */ -static const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577}; -static const uInt cpdext[30] = { /* Extra bits for distance codes */ - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 13, 13}; - -/* - Huffman code decoding is performed using a multi-level table lookup. - The fastest way to decode is to simply build a lookup table whose - size is determined by the longest code. However, the time it takes - to build this table can also be a factor if the data being decoded - is not very long. The most common codes are necessarily the - shortest codes, so those codes dominate the decoding time, and hence - the speed. The idea is you can have a shorter table that decodes the - shorter, more probable codes, and then point to subsidiary tables for - the longer codes. The time it costs to decode the longer codes is - then traded against the time it takes to make longer tables. - - This results of this trade are in the variables lbits and dbits - below. lbits is the number of bits the first level table for literal/ - length codes can decode in one step, and dbits is the same thing for - the distance codes. Subsequent tables are also less than or equal to - those sizes. These values may be adjusted either when all of the - codes are shorter than that, in which case the longest code length in - bits is used, or when the shortest code is *longer* than the requested - table size, in which case the length of the shortest code in bits is - used. - - There are two different values for the two tables, since they code a - different number of possibilities each. The literal/length table - codes 286 possible values, or in a flat code, a little over eight - bits. The distance table codes 30 possible values, or a little less - than five bits, flat. The optimum values for speed end up being - about one bit more than those, so lbits is 8+1 and dbits is 5+1. - The optimum values may differ though from machine to machine, and - possibly even between compilers. Your mileage may vary. - */ - - -/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ -#define BMAX 15 /* maximum bit length of any code */ - -static int huft_build(uInt *b, uInt n, uInt s, const uInt *d, const uInt *e, inflate_huft ** t, uInt *m, inflate_huft *hp, uInt *hn, uInt *v) -//uInt *b; /* code lengths in bits (all assumed <= BMAX) */ -//uInt n; /* number of codes (assumed <= 288) */ -//uInt s; /* number of simple-valued codes (0..s-1) */ -//const uInt *d; /* list of base values for non-simple codes */ -//const uInt *e; /* list of extra bits for non-simple codes */ -//inflate_huft ** t; /* result: starting table */ -//uInt *m; /* maximum lookup bits, returns actual */ -//inflate_huft *hp; /* space for trees */ -//uInt *hn; /* hufts used in space */ -//uInt *v; /* working area: values in order of bit length */ -/* Given a list of code lengths and a maximum table size, make a set of - tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR - if the given code set is incomplete (the tables are still built in this - case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of - lengths), or Z_MEM_ERROR if not enough memory. */ -{ - - uInt a; /* counter for codes of length k */ - uInt c[BMAX+1]; /* bit length count table */ - uInt f; /* i repeats in table every f entries */ - int g; /* maximum code length */ - int h; /* table level */ - register uInt i; /* counter, current code */ - register uInt j; /* counter */ - register int k; /* number of bits in current code */ - int l; /* bits per table (returned in m) */ - uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */ - register uInt *p; /* pointer into c[], b[], or v[] */ - inflate_huft *q; /* points to current table */ - struct inflate_huft_s r; /* table entry for structure assignment */ - inflate_huft *u[BMAX]; /* table stack */ - register int w; /* bits before this table == (l * h) */ - uInt x[BMAX+1]; /* bit offsets, then code stack */ - uInt *xp; /* pointer into x */ - int y; /* number of dummy codes added */ - uInt z; /* number of entries in current table */ - - - /* Generate counts for each bit length */ - p = c; -#define C0 *p++ = 0; -#define C2 C0 C0 C0 C0 -#define C4 C2 C2 C2 C2 - C4 /* clear c[]--assume BMAX+1 is 16 */ - p = b; i = n; - do { - c[*p++]++; /* assume all entries <= BMAX */ - } while (--i); - if (c[0] == n) /* null input--all zero length codes */ - { - *t = (inflate_huft *)Z_NULL; - *m = 0; - return Z_OK; - } - - - /* Find minimum and maximum length, bound *m by those */ - l = *m; - for (j = 1; j <= BMAX; j++) - if (c[j]) - break; - k = j; /* minimum code length */ - if ((uInt)l < j) - l = j; - for (i = BMAX; i; i--) - if (c[i]) - break; - g = i; /* maximum code length */ - if ((uInt)l > i) - l = i; - *m = l; - - - /* Adjust last length count to fill out codes, if needed */ - for (y = 1 << j; j < i; j++, y <<= 1) - if ((y -= c[j]) < 0) - return Z_DATA_ERROR; - if ((y -= c[i]) < 0) - return Z_DATA_ERROR; - c[i] += y; - - - /* Generate starting offsets into the value table for each length */ - x[1] = j = 0; - p = c + 1; xp = x + 2; - while (--i) { /* note that i == g from above */ - *xp++ = (j += *p++); - } - - - /* Make a table of values in order of bit lengths */ - p = b; i = 0; - do { - if ((j = *p++) != 0) - v[x[j]++] = i; - } while (++i < n); - n = x[g]; /* set n to length of v */ - - - /* Generate the Huffman codes and for each, make the table entries */ - x[0] = i = 0; /* first Huffman code is zero */ - p = v; /* grab values in bit order */ - h = -1; /* no tables yet--level -1 */ - w = -l; /* bits decoded == (l * h) */ - u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ - q = (inflate_huft *)Z_NULL; /* ditto */ - z = 0; /* ditto */ - - /* go through the bit lengths (k already is bits in shortest code) */ - for (; k <= g; k++) - { - a = c[k]; - while (a--) - { - /* here i is the Huffman code of length k bits for value *p */ - /* make tables up to required level */ - while (k > w + l) - { - h++; - w += l; /* previous table always l bits */ - - /* compute minimum size table less than or equal to l bits */ - z = g - w; - z = z > (uInt)l ? l : z; /* table size upper limit */ - if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ - { /* too few codes for k-w bit table */ - f -= a + 1; /* deduct codes from patterns left */ - xp = c + k; - if (j < z) - while (++j < z) /* try smaller tables up to z bits */ - { - if ((f <<= 1) <= *++xp) - break; /* enough codes to use up j bits */ - f -= *xp; /* else deduct codes from patterns */ - } - } - z = 1 << j; /* table entries for j-bit table */ - - /* allocate new table */ - if (*hn + z > MANY) /* (note: doesn't matter for fixed) */ - return Z_MEM_ERROR; /* not enough memory */ - u[h] = q = hp + *hn; - *hn += z; - - /* connect to last table, if there is one */ - if (h) - { - x[h] = i; /* save pattern for backing up */ - r.bits = (Byte)l; /* bits to dump before this table */ - r.exop = (Byte)j; /* bits in this table */ - j = i >> (w - l); - r.base = (uInt)(q - u[h-1] - j); /* offset to this table */ - u[h-1][j] = r; /* connect to last table */ - } - else - *t = q; /* first table is returned result */ - } - - /* set up table entry in r */ - r.bits = (Byte)(k - w); - if (p >= v + n) - r.exop = 128 + 64; /* out of values--invalid code */ - else if (*p < s) - { - r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ - r.base = *p++; /* simple code is just the value */ - } - else - { - r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */ - r.base = d[*p++ - s]; - } - - /* fill code-like entries with r */ - f = 1 << (k - w); - for (j = i >> w; j < z; j += f) - q[j] = r; - - /* backwards increment the k-bit code i */ - for (j = 1 << (k - 1); i & j; j >>= 1) - i ^= j; - i ^= j; - - /* backup over finished tables */ - mask = (1 << w) - 1; /* needed on HP, cc -O bug */ - while ((i & mask) != x[h]) - { - h--; /* don't need to update q */ - w -= l; - mask = (1 << w) - 1; - } - } - } - - - /* Return Z_BUF_ERROR if we were given an incomplete table */ - return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; -} - - -int inflate_trees_bits(uInt *c, uInt *bb, inflate_huft * *tb, inflate_huft *hp, z_streamp z) -//uInt *c; /* 19 code lengths */ -//uInt *bb; /* bits tree desired/actual depth */ -//inflate_huft * *tb; /* bits tree result */ -//inflate_huft *hp; /* space for trees */ -//z_streamp z; /* for messages */ -{ - int r; - uInt hn = 0; /* hufts used in space */ - uInt *v; /* work area for huft_build */ - - if ((v = (uInt*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL) - return Z_MEM_ERROR; - r = huft_build(c, 19, 19, (uInt*)Z_NULL, (uInt*)Z_NULL, - tb, bb, hp, &hn, v); - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed dynamic bit lengths tree"; - else if (r == Z_BUF_ERROR || *bb == 0) - { - z->msg = (char*)"incomplete dynamic bit lengths tree"; - r = Z_DATA_ERROR; - } - ZFREE(z, v); - return r; -} - - -int inflate_trees_dynamic(uInt nl, uInt nd, uInt *c, uInt *bl, uInt *bd, inflate_huft * *tl, inflate_huft * *td, inflate_huft *hp, z_streamp z) -//uInt nl; /* number of literal/length codes */ -//uInt nd; /* number of distance codes */ -//uInt *c; /* that many (total) code lengths */ -//uInt *bl; /* literal desired/actual bit depth */ -//uInt *bd; /* distance desired/actual bit depth */ -//inflate_huft * *tl; /* literal/length tree result */ -//inflate_huft * *td; /* distance tree result */ -//inflate_huft *hp; /* space for trees */ -//z_streamp z; /* for messages */ -{ - int r; - uInt hn = 0; /* hufts used in space */ - uInt *v; /* work area for huft_build */ - - /* allocate work area */ - if ((v = (uInt*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) - return Z_MEM_ERROR; - - /* build literal/length tree */ - r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); - if (r != Z_OK || *bl == 0) - { - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed literal/length tree"; - else if (r != Z_MEM_ERROR) - { - z->msg = (char*)"incomplete literal/length tree"; - r = Z_DATA_ERROR; - } - ZFREE(z, v); - return r; - } - - /* build distance tree */ - r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); - if (r != Z_OK || (*bd == 0 && nl > 257)) - { - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed distance tree"; - else if (r == Z_BUF_ERROR) { -#ifdef PKZIP_BUG_WORKAROUND - r = Z_OK; - } -#else - z->msg = (char*)"incomplete distance tree"; - r = Z_DATA_ERROR; - } - else if (r != Z_MEM_ERROR) - { - z->msg = (char*)"empty distance tree with lengths"; - r = Z_DATA_ERROR; - } - ZFREE(z, v); - return r; -#endif - } - - /* done */ - ZFREE(z, v); - return Z_OK; -} - -/* inffixed.h -- table for decoding fixed codes - * Generated automatically by the maketree.c program - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -static uInt fixed_bl = 9; -static uInt fixed_bd = 5; -static inflate_huft fixed_tl[] = { - {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, - {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192}, - {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160}, - {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224}, - {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144}, - {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208}, - {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176}, - {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240}, - {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, - {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200}, - {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168}, - {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232}, - {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152}, - {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216}, - {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184}, - {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248}, - {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, - {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196}, - {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164}, - {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228}, - {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148}, - {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212}, - {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180}, - {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244}, - {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204}, - {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172}, - {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236}, - {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156}, - {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220}, - {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188}, - {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252}, - {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, - {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194}, - {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162}, - {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226}, - {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146}, - {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210}, - {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178}, - {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242}, - {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, - {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202}, - {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170}, - {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234}, - {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154}, - {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218}, - {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186}, - {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250}, - {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, - {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198}, - {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166}, - {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230}, - {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150}, - {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214}, - {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182}, - {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246}, - {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206}, - {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174}, - {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238}, - {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158}, - {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222}, - {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190}, - {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254}, - {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, - {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193}, - {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161}, - {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225}, - {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145}, - {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209}, - {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177}, - {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241}, - {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, - {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201}, - {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169}, - {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233}, - {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153}, - {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217}, - {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185}, - {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249}, - {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, - {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197}, - {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165}, - {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229}, - {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149}, - {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213}, - {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181}, - {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245}, - {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205}, - {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173}, - {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237}, - {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157}, - {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221}, - {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189}, - {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253}, - {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, - {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195}, - {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163}, - {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227}, - {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147}, - {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211}, - {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179}, - {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243}, - {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, - {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203}, - {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171}, - {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235}, - {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155}, - {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219}, - {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187}, - {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251}, - {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, - {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199}, - {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167}, - {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231}, - {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151}, - {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215}, - {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183}, - {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247}, - {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207}, - {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175}, - {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239}, - {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159}, - {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223}, - {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191}, - {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255} - }; -static inflate_huft fixed_td[] = { - {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097}, - {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385}, - {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193}, - {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577}, - {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145}, - {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577}, - {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289}, - {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577} - }; - -int inflate_trees_fixed(uInt *bl, uInt *bd, inflate_huft * *tl, inflate_huft * *td, z_streamp z) -//uInt *bl; /* literal desired/actual bit depth */ -//uInt *bd; /* distance desired/actual bit depth */ -//inflate_huft * *tl; /* literal/length tree result */ -//inflate_huft * *td; /* distance tree result */ -//z_streamp z; /* for memory allocation */ -{ - *bl = fixed_bl; - *bd = fixed_bd; - *tl = fixed_tl; - *td = fixed_td; - return Z_OK; -} - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - -/* macros for bit input with no checking and for returning unused bytes */ -#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}} -#define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;} - -/* Called with number of bytes left to write in window at least 258 - (the maximum string length) and number of input bytes available - at least ten. The ten bytes are six bytes for the longest length/ - distance pair plus four bytes for overloading the bit buffer. */ - -int inflate_fast(uInt bl, uInt bd, inflate_huft *tl, inflate_huft *td, inflate_blocks_statef *s, z_streamp z) -{ - inflate_huft *t; /* temporary pointer */ - uInt e; /* extra bits or operation */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Byte *p; /* input data pointer */ - uInt n; /* bytes available there */ - Byte *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - uInt ml; /* mask for literal/length tree */ - uInt md; /* mask for distance tree */ - uInt c; /* bytes to copy */ - uInt d; /* distance back to copy from */ - Byte *r; /* copy source pointer */ - - /* load input, output, bit values */ - LOAD - - /* initialize masks */ - ml = inflate_mask[bl]; - md = inflate_mask[bd]; - - /* do until not enough input or output space for fast loop */ - do { /* assume called with m >= 258 && n >= 10 */ - /* get literal/length code */ - GRABBITS(20) /* max bits for literal/length code */ - if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) - { - DUMPBITS(t->bits) - Tracevv((t->base >= 0x20 && t->base < 0x7f ? - "inflate: * literal '%c'\n" : - "inflate: * literal 0x%02x\n", t->base)); - *q++ = (Byte)t->base; - m--; - continue; - } - do { - DUMPBITS(t->bits) - if (e & 16) - { - /* get extra bits for length */ - e &= 15; - c = t->base + ((uInt)b & inflate_mask[e]); - DUMPBITS(e) - Tracevv(("inflate: * length %u\n", c)); - - /* decode distance base of block to copy */ - GRABBITS(15); /* max bits for distance code */ - e = (t = td + ((uInt)b & md))->exop; - do { - DUMPBITS(t->bits) - if (e & 16) - { - /* get extra bits to add to distance base */ - e &= 15; - GRABBITS(e) /* get extra bits (up to 13) */ - d = t->base + ((uInt)b & inflate_mask[e]); - DUMPBITS(e) - Tracevv(("inflate: * distance %u\n", d)); - - /* do the copy */ - m -= c; - if ((uInt)(q - s->window) >= d) /* offset before dest */ - { /* just copy */ - r = q - d; - *q++ = *r++; c--; /* minimum count is three, */ - *q++ = *r++; c--; /* so unroll loop a little */ - } - else /* else offset after destination */ - { - e = d - (uInt)(q - s->window); /* bytes from offset to end */ - r = s->end - e; /* pointer to offset */ - if (c > e) /* if source crosses, */ - { - c -= e; /* copy to end of window */ - do { - *q++ = *r++; - } while (--e); - r = s->window; /* copy rest from start of window */ - } - } - do { /* copy all or what's left */ - *q++ = *r++; - } while (--c); - break; - } - else if ((e & 64) == 0) - { - t += t->base; - e = (t += ((uInt)b & inflate_mask[e]))->exop; - } - else - { - z->msg = (char*)"invalid distance code"; - UNGRAB - UPDATE - return Z_DATA_ERROR; - } - } while (1); - break; - } - if ((e & 64) == 0) - { - t += t->base; - if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0) - { - DUMPBITS(t->bits) - Tracevv((t->base >= 0x20 && t->base < 0x7f ? - "inflate: * literal '%c'\n" : - "inflate: * literal 0x%02x\n", t->base)); - *q++ = (Byte)t->base; - m--; - break; - } - } - else if (e & 32) - { - Tracevv(("inflate: * end of block\n")); - UNGRAB - UPDATE - return Z_STREAM_END; - } - else - { - z->msg = (char*)"invalid literal/length code"; - UNGRAB - UPDATE - return Z_DATA_ERROR; - } - } while (1); - } while (m >= 258 && n >= 10); - - /* not enough input or output--restore pointers and return */ - UNGRAB - UPDATE - return Z_OK; -} - -/* infcodes.c -- process literals and length/distance pairs - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - -typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ - START, /* x: set up for LEN */ - LEN, /* i: get length/literal/eob next */ - LENEXT, /* i: getting length extra (have base) */ - DIST, /* i: get distance next */ - DISTEXT, /* i: getting distance extra */ - COPY, /* o: copying bytes in window, waiting for space */ - LIT, /* o: got literal, waiting for output space */ - WASH, /* o: got eob, possibly still output waiting */ - END, /* x: got eob and all data flushed */ - BADCODE} /* x: got error */ -inflate_codes_mode; - -/* inflate codes private state */ -struct inflate_codes_state { - - /* mode */ - inflate_codes_mode mode; /* current inflate_codes mode */ - - /* mode dependent information */ - uInt len; - union { - struct { - inflate_huft *tree; /* pointer into tree */ - uInt need; /* bits needed */ - } code; /* if LEN or DIST, where in tree */ - uInt lit; /* if LIT, literal */ - struct { - uInt get; /* bits to get for extra */ - uInt dist; /* distance back to copy from */ - } copy; /* if EXT or COPY, where and how much */ - } sub; /* submode */ - - /* mode independent information */ - Byte lbits; /* ltree bits decoded per branch */ - Byte dbits; /* dtree bits decoder per branch */ - inflate_huft *ltree; /* literal/length/eob tree */ - inflate_huft *dtree; /* distance tree */ - -}; - - -inflate_codes_statef *inflate_codes_new(uInt bl, uInt bd, inflate_huft *tl, inflate_huft *td, z_streamp z) -{ - inflate_codes_statef *c; - - if ((c = (inflate_codes_statef *) - ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) - { - c->mode = START; - c->lbits = (Byte)bl; - c->dbits = (Byte)bd; - c->ltree = tl; - c->dtree = td; - Tracev(("inflate: codes new\n")); - } - return c; -} - - -int inflate_codes(inflate_blocks_statef *s, z_streamp z, int r) -{ - uInt j; /* temporary storage */ - inflate_huft *t; /* temporary pointer */ - uInt e; /* extra bits or operation */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Byte *p; /* input data pointer */ - uInt n; /* bytes available there */ - Byte *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - Byte *f; /* pointer to copy strings from */ - inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ - - /* copy input/output information to locals (UPDATE macro restores) */ - LOAD - - /* process input and output based on current state */ - while (1) switch (c->mode) - { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ - case START: /* x: set up for LEN */ -#ifndef SLOW - if (m >= 258 && n >= 10) - { - UPDATE - r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); - LOAD - if (r != Z_OK) - { - c->mode = r == Z_STREAM_END ? WASH : BADCODE; - break; - } - } -#endif /* !SLOW */ - c->sub.code.need = c->lbits; - c->sub.code.tree = c->ltree; - c->mode = LEN; - case LEN: /* i: get length/literal/eob next */ - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e == 0) /* literal */ - { - c->sub.lit = t->base; - Tracevv((t->base >= 0x20 && t->base < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", t->base)); - c->mode = LIT; - break; - } - if (e & 16) /* length */ - { - c->sub.copy.get = e & 15; - c->len = t->base; - c->mode = LENEXT; - break; - } - if ((e & 64) == 0) /* next table */ - { - c->sub.code.need = e; - c->sub.code.tree = t + t->base; - break; - } - if (e & 32) /* end of block */ - { - Tracevv(("inflate: end of block\n")); - c->mode = WASH; - break; - } - c->mode = BADCODE; /* invalid code */ - z->msg = (char*)"invalid literal/length code"; - r = Z_DATA_ERROR; - LEAVE - case LENEXT: /* i: getting length extra (have base) */ - j = c->sub.copy.get; - NEEDBITS(j) - c->len += (uInt)b & inflate_mask[j]; - DUMPBITS(j) - c->sub.code.need = c->dbits; - c->sub.code.tree = c->dtree; - Tracevv(("inflate: length %u\n", c->len)); - c->mode = DIST; - case DIST: /* i: get distance next */ - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e & 16) /* distance */ - { - c->sub.copy.get = e & 15; - c->sub.copy.dist = t->base; - c->mode = DISTEXT; - break; - } - if ((e & 64) == 0) /* next table */ - { - c->sub.code.need = e; - c->sub.code.tree = t + t->base; - break; - } - c->mode = BADCODE; /* invalid code */ - z->msg = (char*)"invalid distance code"; - r = Z_DATA_ERROR; - LEAVE - case DISTEXT: /* i: getting distance extra */ - j = c->sub.copy.get; - NEEDBITS(j) - c->sub.copy.dist += (uInt)b & inflate_mask[j]; - DUMPBITS(j) - Tracevv(("inflate: distance %u\n", c->sub.copy.dist)); - c->mode = COPY; - case COPY: /* o: copying bytes in window, waiting for space */ -#ifndef __TURBOC__ /* Turbo C bug for following expression */ - f = (uInt)(q - s->window) < c->sub.copy.dist ? - s->end - (c->sub.copy.dist - (q - s->window)) : - q - c->sub.copy.dist; -#else - f = q - c->sub.copy.dist; - if ((uInt)(q - s->window) < c->sub.copy.dist) - f = s->end - (c->sub.copy.dist - (uInt)(q - s->window)); -#endif - while (c->len) - { - NEEDOUT - OUTBYTE(*f++) - if (f == s->end) - f = s->window; - c->len--; - } - c->mode = START; - break; - case LIT: /* o: got literal, waiting for output space */ - NEEDOUT - OUTBYTE(c->sub.lit) - c->mode = START; - break; - case WASH: /* o: got eob, possibly more output */ - if (k > 7) /* return unused byte, if any */ - { - Assert(k < 16, "inflate_codes grabbed too many bytes") - k -= 8; - n++; - p--; /* can always return one */ - } - FLUSH - if (s->read != s->write) - LEAVE - c->mode = END; - case END: - r = Z_STREAM_END; - LEAVE - case BADCODE: /* x: got error */ - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -#ifdef NEED_DUMMY_RETURN - return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ -#endif -} - - -void inflate_codes_free(inflate_codes_statef *c, z_streamp z) -{ - ZFREE(z, c); - Tracev(("inflate: codes free\n")); -} - -/* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#define BASE 65521L /* largest prime smaller than 65536 */ -#define NMAX 5552 -/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ - -#undef DO1 -#undef DO2 -#undef DO4 -#undef DO8 - -#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} -#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); -#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); -#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); -#define DO16(buf) DO8(buf,0); DO8(buf,8); - -/* ========================================================================= */ -uLong adler32(uLong adler, const Byte *buf, uInt len) -{ - unsigned long s1 = adler & 0xffff; - unsigned long s2 = (adler >> 16) & 0xffff; - int k; - - if (buf == Z_NULL) return 1L; - - while (len > 0) { - k = len < NMAX ? len : NMAX; - len -= k; - while (k >= 16) { - DO16(buf); - buf += 16; - k -= 16; - } - if (k != 0) do { - s1 += *buf++; - s2 += s1; - } while (--k); - s1 %= BASE; - s2 %= BASE; - } - return (s2 << 16) | s1; -} - -/* @(#) $Id: unzip.cpp,v 1.1.1.3 2000/01/11 16:37:27 ttimo Exp $ */ - -/* infblock.h -- header to use infblock.c - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -extern inflate_blocks_statef * inflate_blocks_new OF(( - z_streamp z, - check_func c, /* check function */ - uInt w)); /* window size */ - -extern int inflate_blocks OF(( - inflate_blocks_statef *, - z_streamp , - int)); /* initial return code */ - -extern void inflate_blocks_reset OF(( - inflate_blocks_statef *, - z_streamp , - uLong *)); /* check value on output */ - -extern int inflate_blocks_free OF(( - inflate_blocks_statef *, - z_streamp)); - -extern void inflate_set_dictionary OF(( - inflate_blocks_statef *s, - const Byte *d, /* dictionary */ - uInt n)); /* dictionary length */ - -extern int inflate_blocks_sync_point OF(( - inflate_blocks_statef *s)); - -typedef enum { - imMETHOD, /* waiting for method byte */ - imFLAG, /* waiting for flag byte */ - imDICT4, /* four dictionary check bytes to go */ - imDICT3, /* three dictionary check bytes to go */ - imDICT2, /* two dictionary check bytes to go */ - imDICT1, /* one dictionary check byte to go */ - imDICT0, /* waiting for inflateSetDictionary */ - imBLOCKS, /* decompressing blocks */ - imCHECK4, /* four check bytes to go */ - imCHECK3, /* three check bytes to go */ - imCHECK2, /* two check bytes to go */ - imCHECK1, /* one check byte to go */ - imDONE, /* finished check, done */ - imBAD} /* got an error--stay here */ -inflate_mode; - -/* inflate private state */ -struct internal_state { - - /* mode */ - inflate_mode mode; /* current inflate mode */ - - /* mode dependent information */ - union { - uInt method; /* if FLAGS, method byte */ - struct { - uLong was; /* computed check value */ - uLong need; /* stream check value */ - } check; /* if CHECK, check values to compare */ - uInt marker; /* if BAD, inflateSync's marker bytes count */ - } sub; /* submode */ - - /* mode independent information */ - int nowrap; /* flag for no wrapper */ - uInt wbits; /* log2(window size) (8..15, defaults to 15) */ - inflate_blocks_statef - *blocks; /* current inflate_blocks state */ - -}; - - -int inflateReset(z_streamp z) -{ - if (z == Z_NULL || z->state == Z_NULL) - return Z_STREAM_ERROR; - z->total_in = z->total_out = 0; - z->msg = Z_NULL; - z->state->mode = z->state->nowrap ? imBLOCKS : imMETHOD; - inflate_blocks_reset(z->state->blocks, z, Z_NULL); - Tracev(("inflate: reset\n")); - return Z_OK; -} - - -int inflateEnd(z_streamp z) -{ - if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) - return Z_STREAM_ERROR; - if (z->state->blocks != Z_NULL) - inflate_blocks_free(z->state->blocks, z); - ZFREE(z, z->state); - z->state = Z_NULL; - Tracev(("inflate: end\n")); - return Z_OK; -} - - - -int inflateInit2_(z_streamp z, int w, const char *version, int stream_size) -{ - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != sizeof(z_stream)) - return Z_VERSION_ERROR; - - /* initialize state */ - if (z == Z_NULL) - return Z_STREAM_ERROR; - z->msg = Z_NULL; - if (z->zalloc == Z_NULL) - { - z->zalloc = (void *(*)(void *, unsigned, unsigned))zcalloc; - z->opaque = (voidp)0; - } - if (z->zfree == Z_NULL) z->zfree = (void (*)(void *, void *))zcfree; - if ((z->state = (struct internal_state *) - ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) - return Z_MEM_ERROR; - z->state->blocks = Z_NULL; - - /* handle undocumented nowrap option (no zlib header or check) */ - z->state->nowrap = 0; - if (w < 0) - { - w = - w; - z->state->nowrap = 1; - } - - /* set window size */ - if (w < 8 || w > 15) - { - inflateEnd(z); - return Z_STREAM_ERROR; - } - z->state->wbits = (uInt)w; - - /* create inflate_blocks state */ - if ((z->state->blocks = - inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) - == Z_NULL) - { - inflateEnd(z); - return Z_MEM_ERROR; - } - Tracev(("inflate: allocated\n")); - - /* reset state */ - inflateReset(z); - return Z_OK; -} - - -int inflateInit_(z_streamp z, const char *version, int stream_size) -{ - return inflateInit2_(z, DEF_WBITS, version, stream_size); -} - - -#define iNEEDBYTE {if(z->avail_in==0)return r;r=f;} -#define iNEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) - -int inflate(z_streamp z, int f) -{ - int r; - uInt b; - - if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) - return Z_STREAM_ERROR; - f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; - r = Z_BUF_ERROR; - while (1) switch (z->state->mode) - { - case imMETHOD: - iNEEDBYTE - if (((z->state->sub.method = iNEXTBYTE) & 0xf) != Z_DEFLATED) - { - z->state->mode = imBAD; - z->msg = (char*)"unknown compression method"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - if ((z->state->sub.method >> 4) + 8 > z->state->wbits) - { - z->state->mode = imBAD; - z->msg = (char*)"invalid window size"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - z->state->mode = imFLAG; - case imFLAG: - iNEEDBYTE - b = iNEXTBYTE; - if (((z->state->sub.method << 8) + b) % 31) - { - z->state->mode = imBAD; - z->msg = (char*)"incorrect header check"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - Tracev(("inflate: zlib header ok\n")); - if (!(b & PRESET_DICT)) - { - z->state->mode = imBLOCKS; - break; - } - z->state->mode = imDICT4; - case imDICT4: - iNEEDBYTE - z->state->sub.check.need = (uLong)iNEXTBYTE << 24; - z->state->mode = imDICT3; - case imDICT3: - iNEEDBYTE - z->state->sub.check.need += (uLong)iNEXTBYTE << 16; - z->state->mode = imDICT2; - case imDICT2: - iNEEDBYTE - z->state->sub.check.need += (uLong)iNEXTBYTE << 8; - z->state->mode = imDICT1; - case imDICT1: - iNEEDBYTE - z->state->sub.check.need += (uLong)iNEXTBYTE; - z->adler = z->state->sub.check.need; - z->state->mode = imDICT0; - return Z_NEED_DICT; - case imDICT0: - z->state->mode = imBAD; - z->msg = (char*)"need dictionary"; - z->state->sub.marker = 0; /* can try inflateSync */ - return Z_STREAM_ERROR; - case imBLOCKS: - r = inflate_blocks(z->state->blocks, z, r); - if (r == Z_DATA_ERROR) - { - z->state->mode = imBAD; - z->state->sub.marker = 0; /* can try inflateSync */ - break; - } - if (r == Z_OK) - r = f; - if (r != Z_STREAM_END) - return r; - r = f; - inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); - if (z->state->nowrap) - { - z->state->mode = imDONE; - break; - } - z->state->mode = imCHECK4; - case imCHECK4: - iNEEDBYTE - z->state->sub.check.need = (uLong)iNEXTBYTE << 24; - z->state->mode = imCHECK3; - case imCHECK3: - iNEEDBYTE - z->state->sub.check.need += (uLong)iNEXTBYTE << 16; - z->state->mode = imCHECK2; - case imCHECK2: - iNEEDBYTE - z->state->sub.check.need += (uLong)iNEXTBYTE << 8; - z->state->mode = imCHECK1; - case imCHECK1: - iNEEDBYTE - z->state->sub.check.need += (uLong)iNEXTBYTE; - - if (z->state->sub.check.was != z->state->sub.check.need) - { - z->state->mode = imBAD; - z->msg = (char*)"incorrect data check"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - Tracev(("inflate: zlib check ok\n")); - z->state->mode = imDONE; - case imDONE: - return Z_STREAM_END; - case imBAD: - return Z_DATA_ERROR; - default: - return Z_STREAM_ERROR; - } -#ifdef NEED_DUMMY_RETURN - return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ -#endif -} - - -int inflateSetDictionary(z_streamp z, const Byte *dictionary, uInt dictLength) -{ - uInt length = dictLength; - - if (z == Z_NULL || z->state == Z_NULL || z->state->mode != imDICT0) - return Z_STREAM_ERROR; - - if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR; - z->adler = 1L; - - if (length >= ((uInt)1<<z->state->wbits)) - { - length = (1<<z->state->wbits)-1; - dictionary += dictLength - length; - } - inflate_set_dictionary(z->state->blocks, dictionary, length); - z->state->mode = imBLOCKS; - return Z_OK; -} - - -int inflateSync(z_streamp z) -{ - uInt n; /* number of bytes to look at */ - Byte *p; /* pointer to bytes */ - uInt m; /* number of marker bytes found in a row */ - uLong r, w; /* temporaries to save total_in and total_out */ - - /* set up */ - if (z == Z_NULL || z->state == Z_NULL) - return Z_STREAM_ERROR; - if (z->state->mode != imBAD) - { - z->state->mode = imBAD; - z->state->sub.marker = 0; - } - if ((n = z->avail_in) == 0) - return Z_BUF_ERROR; - p = z->next_in; - m = z->state->sub.marker; - - /* search */ - while (n && m < 4) - { - static const Byte mark[4] = {0, 0, 0xff, 0xff}; - if (*p == mark[m]) - m++; - else if (*p) - m = 0; - else - m = 4 - m; - p++, n--; - } - - /* restore */ - z->total_in += p - z->next_in; - z->next_in = p; - z->avail_in = n; - z->state->sub.marker = m; - - /* return no joy or set up to restart on a new block */ - if (m != 4) - return Z_DATA_ERROR; - r = z->total_in; w = z->total_out; - inflateReset(z); - z->total_in = r; z->total_out = w; - z->state->mode = imBLOCKS; - return Z_OK; -} - - -/* Returns true if inflate is currently at the end of a block generated - * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP - * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH - * but removes the length bytes of the resulting empty stored block. When - * decompressing, PPP checks that at the end of input packet, inflate is - * waiting for these length bytes. - */ -int inflateSyncPoint(z_streamp z) -{ - if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL) - return Z_STREAM_ERROR; - return inflate_blocks_sync_point(z->state->blocks); -} - -voidp zcalloc (voidp opaque, unsigned items, unsigned size) -{ - if (opaque) items += size - size; /* make compiler happy */ - return (voidp)malloc(items*size); -} - -void zcfree (voidp opaque, voidp ptr) -{ - free(ptr); - if (opaque) return; /* make compiler happy */ -} - diff --git a/libs/pak/unzip.h b/libs/pak/unzip.h deleted file mode 100644 index 79a487e..0000000 --- a/libs/pak/unzip.h +++ /dev/null @@ -1,300 +0,0 @@ - -#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) -/* like the STRICT of WIN32, we define a pointer that cannot be converted - from (void*) without cast */ -typedef struct TagunzFile__ { int unused; } unzFile__; -typedef unzFile__ *unzFile; -#else -typedef void* unzFile; -#endif - - -/* tm_unz contain date/time info */ -typedef struct tm_unz_s -{ - unsigned int tm_sec; /* seconds after the minute - [0,59] */ - unsigned int tm_min; /* minutes after the hour - [0,59] */ - unsigned int tm_hour; /* hours since midnight - [0,23] */ - unsigned int tm_mday; /* day of the month - [1,31] */ - unsigned int tm_mon; /* months since January - [0,11] */ - unsigned int tm_year; /* years - [1980..2044] */ -} tm_unz; - -/* unz_global_info structure contain global data about the ZIPfile - These data comes from the end of central dir */ -typedef struct unz_global_info_s -{ - unsigned long number_entry; /* total number of entries in the central dir on this disk */ - unsigned long size_comment; /* size of the global comment of the zipfile */ -} unz_global_info; - - -/* unz_file_info contain information about a file in the zipfile */ -typedef struct unz_file_info_s -{ - unsigned long version; /* version made by 2 unsigned chars */ - unsigned long version_needed; /* version needed to extract 2 unsigned chars */ - unsigned long flag; /* general purpose bit flag 2 unsigned chars */ - unsigned long compression_method; /* compression method 2 unsigned chars */ - unsigned long dosDate; /* last mod file date in Dos fmt 4 unsigned chars */ - unsigned long crc; /* crc-32 4 unsigned chars */ - unsigned long compressed_size; /* compressed size 4 unsigned chars */ - unsigned long uncompressed_size; /* uncompressed size 4 unsigned chars */ - unsigned long size_filename; /* filename length 2 unsigned chars */ - unsigned long size_file_extra; /* extra field length 2 unsigned chars */ - unsigned long size_file_comment; /* file comment length 2 unsigned chars */ - - unsigned long disk_num_start; /* disk number start 2 unsigned chars */ - unsigned long internal_fa; /* internal file attributes 2 unsigned chars */ - unsigned long external_fa; /* external file attributes 4 unsigned chars */ - - tm_unz tmu_date; -} unz_file_info; - -/* unz_file_info_interntal contain internal info about a file in zipfile*/ -typedef struct unz_file_info_internal_s -{ - unsigned long offset_curfile;/* relative offset of static header 4 unsigned chars */ -} unz_file_info_internal; - -typedef void* (*alloc_func) (void* opaque, unsigned int items, unsigned int size); -typedef void (*free_func) (void* opaque, void* address); - -struct internal_state; - -typedef struct z_stream_s { - unsigned char *next_in; /* next input unsigned char */ - unsigned int avail_in; /* number of unsigned chars available at next_in */ - unsigned long total_in; /* total nb of input unsigned chars read so */ - - unsigned char *next_out; /* next output unsigned char should be put there */ - unsigned int avail_out; /* remaining free space at next_out */ - unsigned long total_out; /* total nb of unsigned chars output so */ - - char *msg; /* last error message, NULL if no error */ - struct internal_state *state; /* not visible by applications */ - - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - unsigned char* opaque; /* private data object passed to zalloc and zfree */ - - int data_type; /* best guess about the data type: ascii or binary */ - unsigned long adler; /* adler32 value of the uncompressed data */ - unsigned long reserved; /* reserved for future use */ -} z_stream; - -typedef z_stream *z_streamp; - - -/* file_in_zip_read_info_s contain internal information about a file in zipfile, - when reading and decompress it */ -typedef struct -{ - char *read_buffer; /* internal buffer for compressed data */ - z_stream stream; /* zLib stream structure for inflate */ - - unsigned long pos_in_zipfile; /* position in unsigned char on the zipfile, for fseek*/ - unsigned long stream_initialised; /* flag set if stream structure is initialised*/ - - unsigned long offset_local_extrafield;/* offset of the static extra field */ - unsigned int size_local_extrafield;/* size of the static extra field */ - unsigned long pos_local_extrafield; /* position in the static extra field in read*/ - - unsigned long crc32; /* crc32 of all data uncompressed */ - unsigned long crc32_wait; /* crc32 we must obtain after decompress all */ - unsigned long rest_read_compressed; /* number of unsigned char to be decompressed */ - unsigned long rest_read_uncompressed;/*number of unsigned char to be obtained after decomp*/ - FILE* file; /* io structore of the zipfile */ - unsigned long compression_method; /* compression method (0==store) */ - unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/ -} file_in_zip_read_info_s; - - -/* unz_s contain internal information about the zipfile -*/ -typedef struct -{ - FILE* file; /* io structore of the zipfile */ - unz_global_info gi; /* public global information */ - unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/ - unsigned long num_file; /* number of the current file in the zipfile*/ - unsigned long pos_in_central_dir; /* pos of the current file in the central dir*/ - unsigned long current_file_ok; /* flag about the usability of the current file*/ - unsigned long central_pos; /* position of the beginning of the central dir*/ - - unsigned long size_central_dir; /* size of the central directory */ - unsigned long offset_central_dir; /* offset of start of central directory with - respect to the starting disk number */ - - unz_file_info cur_file_info; /* public info about the current file in zip*/ - unz_file_info_internal cur_file_info_internal; /* private info about it*/ - file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current - file if we are decompressing it */ -} unz_s; - -#define UNZ_OK (0) -#define UNZ_END_OF_LIST_OF_FILE (-100) -#define UNZ_ERRNO (Z_ERRNO) -#define UNZ_EOF (0) -#define UNZ_PARAMERROR (-102) -#define UNZ_BADZIPFILE (-103) -#define UNZ_INTERNALERROR (-104) -#define UNZ_CRCERROR (-105) - -#define UNZ_CASESENSITIVE 1 -#define UNZ_NOTCASESENSITIVE 2 -#define UNZ_OSDEFAULTCASE 0 - -extern int unzStringFileNameCompare (const char* fileName1, const char* fileName2, int iCaseSensitivity); - -/* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi - or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system - (like 1 on Unix, 2 on Windows) -*/ - -extern unzFile unzOpen (const char *path); -extern unzFile unzReOpen (const char* path, unzFile file); - -/* - Open a Zip file. path contain the full pathname (by example, - on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer - "zlib/zlib111.zip". - If the zipfile cannot be opened (file don't exist or in not valid), the - return value is NULL. - Else, the return value is a unzFile Handle, usable with other function - of this unzip package. -*/ - -extern int unzClose (unzFile file); - -/* - Close a ZipFile opened with unzipOpen. - If there is files inside the .Zip opened with unzOpenCurrentFile (see later), - these files MUST be closed with unzipCloseCurrentFile before call unzipClose. - return UNZ_OK if there is no problem. */ - -extern int unzGetGlobalInfo (unzFile file, unz_global_info *pglobal_info); - -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. */ - - -extern int unzGetGlobalComment (unzFile file, char *szComment, unsigned long uSizeBuf); - -/* - Get the global comment string of the ZipFile, in the szComment buffer. - uSizeBuf is the size of the szComment buffer. - return the number of unsigned char copied or an error code <0 -*/ - - -/***************************************************************************/ -/* Unzip package allow you browse the directory of the zipfile */ - -extern int unzGoToFirstFile (unzFile file); - -/* - Set the current file of the zipfile to the first file. - return UNZ_OK if there is no problem -*/ - -extern int unzGoToNextFile (unzFile file); - -/* - Set the current file of the zipfile to the next file. - return UNZ_OK if there is no problem - return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -*/ - -extern int unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity); - -/* - Try locate the file szFileName in the zipfile. - For the iCaseSensitivity signification, see unzStringFileNameCompare - - return value : - UNZ_OK if the file is found. It becomes the current file. - UNZ_END_OF_LIST_OF_FILE if the file is not found -*/ - - -extern int unzGetCurrentFileInfo (unzFile file, unz_file_info *pfile_info, char *szFileName, unsigned long fileNameBufferSize, void *extraField, unsigned long extraFieldBufferSize, char *szComment, unsigned long commentBufferSize); - -/* - Get Info about the current file - if pfile_info!=NULL, the *pfile_info structure will contain somes info about - the current file - if szFileName!=NULL, the filemane string will be copied in szFileName - (fileNameBufferSize is the size of the buffer) - if extraField!=NULL, the extra field information will be copied in extraField - (extraFieldBufferSize is the size of the buffer). - This is the Central-header version of the extra field - if szComment!=NULL, the comment string of the file will be copied in szComment - (commentBufferSize is the size of the buffer) -*/ - -/***************************************************************************/ -/* for reading the content of the current zipfile, you can open it, read data - from it, and close it (you can close it before reading all the file) - */ - -extern int unzOpenCurrentFile (unzFile file); - -/* - Open for reading data the current file in the zipfile. - If there is no error, the return value is UNZ_OK. -*/ - -extern int unzCloseCurrentFile (unzFile file); - -/* - Close the file in zip opened with unzOpenCurrentFile - Return UNZ_CRCERROR if all the file was read but the CRC is not good -*/ - - -extern int unzReadCurrentFile (unzFile file, void* buf, unsigned len); - -/* - Read unsigned chars from the current file (opened by unzOpenCurrentFile) - buf contain buffer where data must be copied - len the size of buf. - - return the number of unsigned char copied if somes unsigned chars are copied - return 0 if the end of file was reached - return <0 with error code if there is an error - (UNZ_ERRNO for IO error, or zLib error for uncompress error) -*/ - -extern long unztell(unzFile file); - -/* - Give the current position in uncompressed data -*/ - -extern int unzeof (unzFile file); - -/* - return 1 if the end of file was reached, 0 elsewhere -*/ - -extern int unzGetLocalExtrafield (unzFile file, void* buf, unsigned len); - -/* - Read extra field from the current file (opened by unzOpenCurrentFile) - This is the local-header version of the extra field (sometimes, there is - more info in the local-header version than in the central-header) - - if buf==NULL, it return the size of the local extra field - - if buf!=NULL, len is the size of the buffer, the extra header is copied in - buf. - the return value is the number of unsigned chars copied in buf, or (if <0) - the error code -*/ diff --git a/libs/pakstuff.h b/libs/pakstuff.h deleted file mode 100644 index 820b5c6..0000000 --- a/libs/pakstuff.h +++ /dev/null @@ -1,141 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#ifndef _PAKSTUFF_H_ -#define _PAKSTUFF_H_ - -#include <windows.h> -#ifdef __cplusplus -extern "C" -{ -#endif - -typedef char Int8; -typedef short Int16; -typedef long Int32; -typedef unsigned char UInt8; -typedef unsigned short UInt16; -typedef unsigned long UInt32; -typedef float Float32; -typedef double Float64; -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define RANDOM(x) (random() % (x)) -#define RANDOMIZE() srand((int) time(NULL)) - -#define FTYPE_UNKNOWN 0 -#define FTYPE_IWAD 1 /* .wad "IWAD" */ -#define FTYPE_PWAD 2 /* .wad "PWAD" */ -#define FTYPE_PACK 3 /* .pak "PACK" */ -#define FTYPE_WAD2 4 /* .wad "WAD2" */ -#define FTYPE_BSP 10 /* .bsp (0x17 0x00 0x00 0x00) */ -#define FTYPE_MODEL 11 /* .mdl "IDPO" */ -#define FTYPE_SPRITE 12 /* .spr "IDSP" */ -#define FTYPE_WAV 20 /* .wav "RIFF" */ -#define FTYPE_AU 21 /* .au ".snd" */ -#define FTYPE_VOC 22 /* .voc ? */ -#define FTYPE_PBM_ASC 30 /* .pbm "P1" */ -#define FTYPE_PGM_ASC 31 /* .pgm "P2" */ -#define FTYPE_PPM_ASC 32 /* .ppm "P3" */ -#define FTYPE_PBM_RAW 33 /* .pbm "P4" */ -#define FTYPE_PGM_RAW 34 /* .pgm "P5" */ -#define FTYPE_PPM_RAW 35 /* .ppm "P6" */ -#define FTYPE_BMP 36 /* .bmp "BM" */ -#define FTYPE_GIF 37 /* .gif "GIF8" */ -#define FTYPE_PCX 38 /* .pcx (0x0a 0x05 0x01 0x08) */ -#define FTYPE_ERROR -1 - -#ifdef FAT_ENDIAN -Bool ReadInt16 (FILE *file, UInt16 huge *x); -Bool ReadInt32 (FILE *file, UInt32 huge *x); -Bool ReadFloat32 (FILE *file, Float32 huge *x); -Bool WriteInt16 (FILE *file, UInt16 huge *x); -Bool WriteInt32 (FILE *file, UInt32 huge *x); -Bool WriteFloat32 (FILE *file, Float32 huge *x); -UInt16 SwapInt16 (UInt16 x); -UInt32 SwapInt32 (UInt32 x); -Float32 SwapFloat32 (Float32 x); -#else -#define ReadInt16(f, p) ReadBytes((f), (p), 2L) -#define ReadInt32(f, p) ReadBytes((f), (p), 4L) -#define ReadFloat32(f, p) ReadBytes((f), (p), 4L) -#define WriteInt16(f, p) WriteBytes((f), (p), 2L) -#define WriteInt32(f, p) WriteBytes((f), (p), 4L) -#define WriteFloat32(f, p) WriteBytes((f), (p), 4L) -#define SwapInt16(x) (x) -#define SwapInt32(x) (x) -#define SwapFloat32(x) (x) -#endif /* FAT_ENDIAN */ - -#define FROMDISK -1 -struct PACKDirectory -{ - char name[56]; /* name of file */ - UInt32 offset; /* offset to start of data */ - UInt32 size; /* byte size of data */ -}; -typedef struct PACKDirectory *PACKDirPtr; - -typedef struct DirListStruct -{ - char dirname[1024]; - int from; - struct DirListStruct *next; -} DIRLIST; - -typedef struct FileListStruct -{ - char filename[1024]; - UInt32 offset; - UInt32 size; - struct FileListStruct *next; -} FILELIST; - -typedef struct DirStruct -{ - char name[1024]; - FILELIST *files; - struct DirStruct *next; -} DIRECTORY; - - -extern int m_nPAKIndex; -extern FILE* pakfile[16]; -extern boolean pakopen; -extern DIRECTORY *paktextures; - -void ClearFileList (FILELIST **); -void ClearDirList (DIRLIST **); -boolean GetPackFileList (FILELIST **, char *); -boolean GetPackTextureDirs (DIRLIST **); -boolean AddToDirListAlphabetized (DIRLIST **, char *, int); -boolean AddToFileListAlphabetized (FILELIST **t, char *, UInt32, UInt32, boolean); -boolean PakLoadFile (const char *, void **); -void OpenPakFile (const char *); -void ClosePakFile (void); -int PakLoadAnyFile(const char *filename, void **bufferptr); -void WINAPI InitPakFile(const char * pBasePath, const char *pName); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/libs/str.h b/libs/str.h deleted file mode 100644 index fb10f70..0000000 --- a/libs/str.h +++ /dev/null @@ -1,214 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#ifndef __STR__ -#define __STR__ -// -// class Str -// loose replacement for CString from MFC -// -//#include "cmdlib.h" -#include <string.h> - -char* __StrDup(char* pStr); -char* __StrDup(const char* pStr); - - - -static char *g_pStrWork = NULL; - -class Str -{ -protected: - bool m_bIgnoreCase; - char *m_pStr; - -public: - Str() - { - m_bIgnoreCase = true; - m_pStr = NULL; - } - - Str(char *p) - { - m_bIgnoreCase = true; - m_pStr = __StrDup(p); - } - - Str(const char *p) - { - m_bIgnoreCase = true; - m_pStr = __StrDup(p); - } - - void Deallocate() - { - delete []m_pStr; - m_pStr = NULL; - } - - void Allocate(int n) - { - Deallocate(); - m_pStr = new char[n]; - } - - const char* GetBuffer() - { - return m_pStr; - } - - void MakeEmpty() - { - Deallocate(); - m_pStr = __StrDup(""); - } - - ~Str() - { - Deallocate(); - delete []g_pStrWork; - g_pStrWork = NULL; - } - - void MakeLower() - { - if (m_pStr) - { - strlwr(m_pStr); - } - } - - int Find(const char *p) - { - char *pf = strstr(m_pStr, p); - return (pf) ? (pf - m_pStr) : -1; - } - - int GetLength() - { - return (m_pStr) ? strlen(m_pStr) : 0; - } - - const char* Left(int n) - { - delete []g_pStrWork; - if (n > 0) - { - g_pStrWork = new char[n+1]; - strncpy(g_pStrWork, m_pStr, n); - } - else - { - g_pStrWork = ""; - g_pStrWork = new char[1]; - g_pStrWork[0] = '\0'; - } - return g_pStrWork; - } - - const char* Right(int n) - { - delete []g_pStrWork; - if (n > 0) - { - g_pStrWork = new char[n+1]; - int nStart = GetLength() - n; - strncpy(g_pStrWork, &m_pStr[nStart], n); - g_pStrWork[n] = '\0'; - } - else - { - g_pStrWork = new char[1]; - g_pStrWork[0] = '\0'; - } - return g_pStrWork; - } - - - char& operator *() { return *m_pStr; } - char& operator *() const { return *const_cast<Str*>(this)->m_pStr; } - operator void*() { return m_pStr; } - operator char*() { return m_pStr; } - operator const char*(){ return reinterpret_cast<const char*>(m_pStr); } - operator unsigned char*() { return reinterpret_cast<unsigned char*>(m_pStr); } - operator const unsigned char*() { return reinterpret_cast<const unsigned char*>(m_pStr); } - Str& operator =(const Str& rhs) - { - if (&rhs != this) - { - delete[] m_pStr; - m_pStr = __StrDup(rhs.m_pStr); - } - return *this; - } - - Str& operator =(const char* pStr) - { - if (m_pStr != pStr) - { - delete[] m_pStr; - m_pStr = __StrDup(pStr); - } - return *this; - } - - Str& operator +=(const char *pStr) - { - if (pStr) - { - if (m_pStr) - { - char *p = new char[strlen(m_pStr) + strlen(pStr) + 1]; - strcpy(p, m_pStr); - strcat(p, pStr); - delete m_pStr; - m_pStr = p; - } - else - { - m_pStr = __StrDup(pStr); - } - } - return *this; - } - - Str& operator +=(const char c) - { - return operator+=(&c); - } - - - bool operator ==(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) == 0 : strcmp(m_pStr, rhs.m_pStr) == 0; } - bool operator ==(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) == 0 : strcmp(m_pStr, pStr) == 0; } - bool operator ==(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) == 0 : strcmp(m_pStr, pStr) == 0; } - bool operator !=(Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) != 0 : strcmp(m_pStr, rhs.m_pStr) != 0; } - bool operator !=(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) != 0 : strcmp(m_pStr, pStr) != 0; } - bool operator !=(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) != 0 : strcmp(m_pStr, pStr) != 0; } - char& operator [](int nIndex) { return m_pStr[nIndex]; } - char& operator [](int nIndex) const { return m_pStr[nIndex]; } - -}; - - - -#endif
\ No newline at end of file diff --git a/q3map/brush.c b/q3map/brush.c deleted file mode 100644 index 506bd1d..0000000 --- a/q3map/brush.c +++ /dev/null @@ -1,861 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#include "qbsp.h" - - -int c_active_brushes; - -int c_nodes; - -// if a brush just barely pokes onto the other side, -// let it slide by without chopping -#define PLANESIDE_EPSILON 0.001 -//0.1 - - - - -/* -================ -CountBrushList -================ -*/ -int CountBrushList (bspbrush_t *brushes) -{ - int c; - - c = 0; - for ( ; brushes ; brushes = brushes->next) - c++; - return c; -} - - -/* -================ -AllocBrush -================ -*/ -bspbrush_t *AllocBrush (int numsides) -{ - bspbrush_t *bb; - int c; - - c = (int)&(((bspbrush_t *)0)->sides[numsides]); - bb = malloc(c); - memset (bb, 0, c); - if (numthreads == 1) - c_active_brushes++; - return bb; -} - -/* -================ -FreeBrush -================ -*/ -void FreeBrush (bspbrush_t *brushes) -{ - int i; - - for (i=0 ; i<brushes->numsides ; i++) - if (brushes->sides[i].winding) - FreeWinding(brushes->sides[i].winding); - free (brushes); - if (numthreads == 1) - c_active_brushes--; -} - - -/* -================ -FreeBrushList -================ -*/ -void FreeBrushList (bspbrush_t *brushes) -{ - bspbrush_t *next; - - for ( ; brushes ; brushes = next) - { - next = brushes->next; - - FreeBrush (brushes); - } -} - -/* -================== -CopyBrush - -Duplicates the brush, the sides, and the windings -================== -*/ -bspbrush_t *CopyBrush (bspbrush_t *brush) -{ - bspbrush_t *newbrush; - int size; - int i; - - size = (int)&(((bspbrush_t *)0)->sides[brush->numsides]); - - newbrush = AllocBrush (brush->numsides); - memcpy (newbrush, brush, size); - - for (i=0 ; i<brush->numsides ; i++) - { - if (brush->sides[i].winding) - newbrush->sides[i].winding = CopyWinding (brush->sides[i].winding); - } - - return newbrush; -} - - -/* -================ -DrawBrushList -================ -*/ -void DrawBrushList (bspbrush_t *brush) -{ - int i; - side_t *s; - - GLS_BeginScene (); - for ( ; brush ; brush=brush->next) - { - for (i=0 ; i<brush->numsides ; i++) - { - s = &brush->sides[i]; - if (!s->winding) - continue; - GLS_Winding (s->winding, 0); - } - } - GLS_EndScene (); -} - - - -/* -================ -WriteBrushList -================ -*/ -void WriteBrushList (char *name, bspbrush_t *brush, qboolean onlyvis) -{ - int i; - side_t *s; - FILE *f; - - qprintf ("writing %s\n", name); - f = SafeOpenWrite (name); - - for ( ; brush ; brush=brush->next) - { - for (i=0 ; i<brush->numsides ; i++) - { - s = &brush->sides[i]; - if (!s->winding) - continue; - if (onlyvis && !s->visible) - continue; - OutputWinding (brush->sides[i].winding, f); - } - } - - fclose (f); -} - - -/* -============= -PrintBrush -============= -*/ -void PrintBrush (bspbrush_t *brush) -{ - int i; - - _printf ("brush: %p\n", brush); - for (i=0;i<brush->numsides ; i++) - { - pw(brush->sides[i].winding); - _printf ("\n"); - } -} - -/* -================== -BoundBrush - -Sets the mins/maxs based on the windings -returns false if the brush doesn't enclose a valid volume -================== -*/ -qboolean BoundBrush (bspbrush_t *brush) -{ - int i, j; - winding_t *w; - - ClearBounds (brush->mins, brush->maxs); - for (i=0 ; i<brush->numsides ; i++) - { - w = brush->sides[i].winding; - if (!w) - continue; - for (j=0 ; j<w->numpoints ; j++) - AddPointToBounds (w->p[j], brush->mins, brush->maxs); - } - - for (i=0 ; i<3 ; i++) { - if (brush->mins[i] < MIN_WORLD_COORD || brush->maxs[i] > MAX_WORLD_COORD - || brush->mins[i] >= brush->maxs[i] ) { - return qfalse; - } - } - - return qtrue; -} - -/* -================== -CreateBrushWindings - -makes basewindigs for sides and mins / maxs for the brush -returns false if the brush doesn't enclose a valid volume -================== -*/ -qboolean CreateBrushWindings (bspbrush_t *brush) -{ - int i, j; - winding_t *w; - side_t *side; - plane_t *plane; - - for ( i = 0; i < brush->numsides; i++ ) - { - side = &brush->sides[i]; - // don't create a winding for a bevel - if ( side->bevel ) { - continue; - } - plane = &mapplanes[side->planenum]; - w = BaseWindingForPlane (plane->normal, plane->dist); - for ( j = 0; j < brush->numsides && w; j++ ) - { - if (i == j) - continue; - if ( brush->sides[j].planenum == ( brush->sides[i].planenum ^ 1 ) ) - continue; // back side clipaway - if (brush->sides[j].bevel) - continue; - if (brush->sides[j].backSide) - continue; - plane = &mapplanes[brush->sides[j].planenum^1]; - ChopWindingInPlace (&w, plane->normal, plane->dist, 0); //CLIP_EPSILON); - } - // free any existing winding - if ( side->winding ) { - FreeWinding( side->winding ); - } - side->winding = w; - } - - return BoundBrush (brush); -} - -/* -================== -BrushFromBounds - -Creates a new axial brush -================== -*/ -bspbrush_t *BrushFromBounds (vec3_t mins, vec3_t maxs) -{ - bspbrush_t *b; - int i; - vec3_t normal; - vec_t dist; - - b = AllocBrush (6); - b->numsides = 6; - for (i=0 ; i<3 ; i++) - { - VectorClear (normal); - normal[i] = 1; - dist = maxs[i]; - b->sides[i].planenum = FindFloatPlane (normal, dist); - - normal[i] = -1; - dist = -mins[i]; - b->sides[3+i].planenum = FindFloatPlane (normal, dist); - } - - CreateBrushWindings (b); - - return b; -} - -/* -================== -BrushVolume - -================== -*/ -vec_t BrushVolume (bspbrush_t *brush) -{ - int i; - winding_t *w; - vec3_t corner; - vec_t d, area, volume; - plane_t *plane; - - if (!brush) - return 0; - - // grab the first valid point as the corner - - w = NULL; - for (i=0 ; i<brush->numsides ; i++) - { - w = brush->sides[i].winding; - if (w) - break; - } - if (!w) - return 0; - VectorCopy (w->p[0], corner); - - // make tetrahedrons to all other faces - - volume = 0; - for ( ; i<brush->numsides ; i++) - { - w = brush->sides[i].winding; - if (!w) - continue; - plane = &mapplanes[brush->sides[i].planenum]; - d = -(DotProduct (corner, plane->normal) - plane->dist); - area = WindingArea (w); - volume += d*area; - } - - volume /= 3; - return volume; -} - - -/* -================== -WriteBspBrushMap -================== -*/ -void WriteBspBrushMap (char *name, bspbrush_t *list) -{ - FILE *f; - side_t *s; - int i; - winding_t *w; - - _printf ("writing %s\n", name); - f = fopen (name, "wb"); - if (!f) - Error ("Can't write %s\b", name); - - fprintf (f, "{\n\"classname\" \"worldspawn\"\n"); - - for ( ; list ; list=list->next ) - { - fprintf (f, "{\n"); - for (i=0,s=list->sides ; i<list->numsides ; i++,s++) - { - w = BaseWindingForPlane (mapplanes[s->planenum].normal, mapplanes[s->planenum].dist); - - fprintf (f,"( %i %i %i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2]); - fprintf (f,"( %i %i %i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2]); - fprintf (f,"( %i %i %i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]); - - fprintf (f, "notexture 0 0 0 1 1\n" ); - FreeWinding (w); - } - fprintf (f, "}\n"); - } - fprintf (f, "}\n"); - - fclose (f); - -} - - -//===================================================================================== - -/* -==================== -FilterBrushIntoTree_r - -==================== -*/ -int FilterBrushIntoTree_r( bspbrush_t *b, node_t *node ) { - bspbrush_t *front, *back; - int c; - - if ( !b ) { - return 0; - } - - // add it to the leaf list - if ( node->planenum == PLANENUM_LEAF ) { - b->next = node->brushlist; - node->brushlist = b; - - // classify the leaf by the structural brush - if ( !b->detail ) { - if ( b->opaque ) { - node->opaque = qtrue; - node->areaportal = qfalse; - } else if ( b->contents & CONTENTS_AREAPORTAL ) { - if ( !node->opaque ) { - node->areaportal = qtrue; - } - } - } - - return 1; - } - - // split it by the node plane - SplitBrush ( b, node->planenum, &front, &back ); - FreeBrush( b ); - - c = 0; - c += FilterBrushIntoTree_r( front, node->children[0] ); - c += FilterBrushIntoTree_r( back, node->children[1] ); - - return c; -} - -/* -===================== -FilterDetailBrushesIntoTree - -Fragment all the detail brushes into the structural leafs -===================== -*/ -void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree ) { - bspbrush_t *b, *newb; - int r; - int c_unique, c_clusters; - int i; - - qprintf( "----- FilterDetailBrushesIntoTree -----\n"); - - c_unique = 0; - c_clusters = 0; - for ( b = e->brushes ; b ; b = b->next ) { - if ( !b->detail ) { - continue; - } - c_unique++; - newb = CopyBrush( b ); - r = FilterBrushIntoTree_r( newb, tree->headnode ); - c_clusters += r; - - // mark all sides as visible so drawsurfs are created - if ( r ) { - for ( i = 0 ; i < b->numsides ; i++ ) { - if ( b->sides[i].winding ) { - b->sides[i].visible = qtrue; - } - } - } - } - - qprintf( "%5i detail brushes\n", c_unique ); - qprintf( "%5i cluster references\n", c_clusters ); -} - -/* -===================== -FilterStructuralBrushesIntoTree - -Mark the leafs as opaque and areaportals -===================== -*/ -void FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree ) { - bspbrush_t *b, *newb; - int r; - int c_unique, c_clusters; - int i; - - qprintf( "----- FilterStructuralBrushesIntoTree -----\n"); - - c_unique = 0; - c_clusters = 0; - for ( b = e->brushes ; b ; b = b->next ) { - if ( b->detail ) { - continue; - } - c_unique++; - newb = CopyBrush( b ); - r = FilterBrushIntoTree_r( newb, tree->headnode ); - c_clusters += r; - - // mark all sides as visible so drawsurfs are created - if ( r ) { - for ( i = 0 ; i < b->numsides ; i++ ) { - if ( b->sides[i].winding ) { - b->sides[i].visible = qtrue; - } - } - } - } - - qprintf( "%5i structural brushes\n", c_unique ); - qprintf( "%5i cluster references\n", c_clusters ); -} - - - -/* -================ -AllocTree -================ -*/ -tree_t *AllocTree (void) -{ - tree_t *tree; - - tree = malloc(sizeof(*tree)); - memset (tree, 0, sizeof(*tree)); - ClearBounds (tree->mins, tree->maxs); - - return tree; -} - -/* -================ -AllocNode -================ -*/ -node_t *AllocNode (void) -{ - node_t *node; - - node = malloc(sizeof(*node)); - memset (node, 0, sizeof(*node)); - - return node; -} - - -/* -================ -WindingIsTiny - -Returns true if the winding would be crunched out of -existance by the vertex snapping. -================ -*/ -#define EDGE_LENGTH 0.2 -qboolean WindingIsTiny (winding_t *w) -{ -/* - if (WindingArea (w) < 1) - return qtrue; - return qfalse; -*/ - int i, j; - vec_t len; - vec3_t delta; - int edges; - - edges = 0; - for (i=0 ; i<w->numpoints ; i++) - { - j = i == w->numpoints - 1 ? 0 : i+1; - VectorSubtract (w->p[j], w->p[i], delta); - len = VectorLength (delta); - if (len > EDGE_LENGTH) - { - if (++edges == 3) - return qfalse; - } - } - return qtrue; -} - -/* -================ -WindingIsHuge - -Returns true if the winding still has one of the points -from basewinding for plane -================ -*/ -qboolean WindingIsHuge (winding_t *w) -{ - int i, j; - - for (i=0 ; i<w->numpoints ; i++) - { - for (j=0 ; j<3 ; j++) - if (w->p[i][j] <= MIN_WORLD_COORD || w->p[i][j] >= MAX_WORLD_COORD) - return qtrue; - } - return qfalse; -} - -//============================================================ - -/* -================== -BrushMostlyOnSide - -================== -*/ -int BrushMostlyOnSide (bspbrush_t *brush, plane_t *plane) -{ - int i, j; - winding_t *w; - vec_t d, max; - int side; - - max = 0; - side = PSIDE_FRONT; - for (i=0 ; i<brush->numsides ; i++) - { - w = brush->sides[i].winding; - if (!w) - continue; - for (j=0 ; j<w->numpoints ; j++) - { - d = DotProduct (w->p[j], plane->normal) - plane->dist; - if (d > max) - { - max = d; - side = PSIDE_FRONT; - } - if (-d > max) - { - max = -d; - side = PSIDE_BACK; - } - } - } - return side; -} - -/* -================ -SplitBrush - -Generates two new brushes, leaving the original -unchanged -================ -*/ -void SplitBrush (bspbrush_t *brush, int planenum, - bspbrush_t **front, bspbrush_t **back) -{ - bspbrush_t *b[2]; - int i, j; - winding_t *w, *cw[2], *midwinding; - plane_t *plane, *plane2; - side_t *s, *cs; - float d, d_front, d_back; - - *front = *back = NULL; - plane = &mapplanes[planenum]; - - // check all points - d_front = d_back = 0; - for (i=0 ; i<brush->numsides ; i++) - { - w = brush->sides[i].winding; - if (!w) - continue; - for (j=0 ; j<w->numpoints ; j++) - { - d = DotProduct (w->p[j], plane->normal) - plane->dist; - if (d > 0 && d > d_front) - d_front = d; - if (d < 0 && d < d_back) - d_back = d; - } - } - if (d_front < 0.1) // PLANESIDE_EPSILON) - { // only on back - *back = CopyBrush (brush); - return; - } - if (d_back > -0.1) // PLANESIDE_EPSILON) - { // only on front - *front = CopyBrush (brush); - return; - } - - // create a new winding from the split plane - - w = BaseWindingForPlane (plane->normal, plane->dist); - for (i=0 ; i<brush->numsides && w ; i++) - { - if ( brush->sides[i].backSide ) { - continue; // fake back-sided polygons never split - } - plane2 = &mapplanes[brush->sides[i].planenum ^ 1]; - ChopWindingInPlace (&w, plane2->normal, plane2->dist, 0); // PLANESIDE_EPSILON); - } - - if (!w || WindingIsTiny (w) ) - { // the brush isn't really split - int side; - - side = BrushMostlyOnSide (brush, plane); - if (side == PSIDE_FRONT) - *front = CopyBrush (brush); - if (side == PSIDE_BACK) - *back = CopyBrush (brush); - return; - } - - if (WindingIsHuge (w)) - { - qprintf ("WARNING: huge winding\n"); - } - - midwinding = w; - - // split it for real - - for (i=0 ; i<2 ; i++) - { - b[i] = AllocBrush (brush->numsides+1); - memcpy( b[i], brush, sizeof( bspbrush_t ) - sizeof( brush->sides ) ); - b[i]->numsides = 0; - b[i]->next = NULL; - b[i]->original = brush->original; - } - - // split all the current windings - - for (i=0 ; i<brush->numsides ; i++) - { - s = &brush->sides[i]; - w = s->winding; - if (!w) - continue; - ClipWindingEpsilon (w, plane->normal, plane->dist, - 0 /*PLANESIDE_EPSILON*/, &cw[0], &cw[1]); - for (j=0 ; j<2 ; j++) - { - if (!cw[j]) - continue; -/* - if (WindingIsTiny (cw[j])) - { - FreeWinding (cw[j]); - continue; - } -*/ - cs = &b[j]->sides[b[j]->numsides]; - b[j]->numsides++; - *cs = *s; - cs->winding = cw[j]; - } - } - - - // see if we have valid polygons on both sides - - for (i=0 ; i<2 ; i++) - { - BoundBrush (b[i]); - for (j=0 ; j<3 ; j++) - { - if (b[i]->mins[j] < MIN_WORLD_COORD || b[i]->maxs[j] > MAX_WORLD_COORD) - { - qprintf ("bogus brush after clip\n"); - break; - } - } - - if (b[i]->numsides < 3 || j < 3) - { - FreeBrush (b[i]); - b[i] = NULL; - } - } - - if ( !(b[0] && b[1]) ) - { - if (!b[0] && !b[1]) - qprintf ("split removed brush\n"); - else - qprintf ("split not on both sides\n"); - if (b[0]) - { - FreeBrush (b[0]); - *front = CopyBrush (brush); - } - if (b[1]) - { - FreeBrush (b[1]); - *back = CopyBrush (brush); - } - return; - } - - // add the midwinding to both sides - for (i=0 ; i<2 ; i++) - { - cs = &b[i]->sides[b[i]->numsides]; - b[i]->numsides++; - - cs->planenum = planenum^i^1; - cs->shaderInfo = NULL; - if (i==0) - cs->winding = CopyWinding (midwinding); - else - cs->winding = midwinding; - } - -{ - vec_t v1; - int i; - - for (i=0 ; i<2 ; i++) - { - v1 = BrushVolume (b[i]); - if (v1 < 1.0) - { - FreeBrush (b[i]); - b[i] = NULL; -// qprintf ("tiny volume after clip\n"); - } - } -} - - *front = b[0]; - *back = b[1]; -} diff --git a/q3map/brush_primit.c b/q3map/brush_primit.c deleted file mode 100644 index 198e90e..0000000 --- a/q3map/brush_primit.c +++ /dev/null @@ -1,52 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#include "qbsp.h" - - -// global flag -int g_bBrushPrimit; - -// NOTE : ComputeAxisBase here and in editor code must always BE THE SAME ! -// WARNING : special case behaviour of atan2(y,x) <-> atan(y/x) might not be the same everywhere when x == 0 -// rotation by (0,RotY,RotZ) assigns X to normal -void ComputeAxisBase(vec3_t normal,vec3_t texX,vec3_t texY) -{ - vec_t RotY,RotZ; - // do some cleaning - if (fabs(normal[0])<1e-6) - normal[0]=0.0f; - if (fabs(normal[1])<1e-6) - normal[1]=0.0f; - if (fabs(normal[2])<1e-6) - normal[2]=0.0f; - // compute the two rotations around Y and Z to rotate X to normal - RotY=-atan2(normal[2],sqrt(normal[1]*normal[1]+normal[0]*normal[0])); - RotZ=atan2(normal[1],normal[0]); - // rotate (0,1,0) and (0,0,1) to compute texX and texY - texX[0]=-sin(RotZ); - texX[1]=cos(RotZ); - texX[2]=0; - // the texY vector is along -Z ( T texture coorinates axis ) - texY[0]=-sin(RotY)*cos(RotZ); - texY[1]=-sin(RotY)*sin(RotZ); - texY[2]=-cos(RotY); -} diff --git a/q3map/bsp.c b/q3map/bsp.c deleted file mode 100644 index 2cf15bd..0000000 --- a/q3map/bsp.c +++ /dev/null @@ -1,605 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#include "qbsp.h" - -#ifdef _WIN32 -#ifdef _TTIMOBUILD -#include "pakstuff.h" -#else -#include "../libs/pakstuff.h" -#endif -extern HWND hwndOut; -#endif - -char source[1024]; -char tempsource[1024]; -char name[1024]; - -vec_t microvolume = 1.0; -qboolean glview; -qboolean nodetail; -qboolean fulldetail; -qboolean onlyents; -qboolean onlytextures; -qboolean nowater; -qboolean nofill; -qboolean noopt; -qboolean leaktest; -qboolean verboseentities; -qboolean noCurveBrushes; -qboolean fakemap; -qboolean notjunc; -qboolean nomerge; -qboolean nofog; -qboolean nosubdivide; -qboolean testExpand; -qboolean showseams; - -char outbase[32]; - -int entity_num; - -/* -============ -ProcessWorldModel - -============ -*/ -void ProcessWorldModel( void ) { - entity_t *e; - tree_t *tree; - bspface_t *faces; - qboolean leaked; - - BeginModel(); - - e = &entities[0]; - e->firstDrawSurf = 0;//numMapDrawSurfs; - - // check for patches with adjacent edges that need to LOD together - PatchMapDrawSurfs( e ); - - // build an initial bsp tree using all of the sides - // of all of the structural brushes - faces = MakeStructuralBspFaceList ( entities[0].brushes ); - tree = FaceBSP( faces ); - MakeTreePortals (tree); - FilterStructuralBrushesIntoTree( e, tree ); - - // see if the bsp is completely enclosed - if ( FloodEntities (tree) ) { - // rebuild a better bsp tree using only the - // sides that are visible from the inside - FillOutside (tree->headnode); - - // chop the sides to the convex hull of - // their visible fragments, giving us the smallest - // polygons - ClipSidesIntoTree( e, tree ); - - faces = MakeVisibleBspFaceList( entities[0].brushes ); - FreeTree (tree); - tree = FaceBSP( faces ); - MakeTreePortals( tree ); - FilterStructuralBrushesIntoTree( e, tree ); - leaked = qfalse; - } else { - _printf ("**********************\n"); - _printf ("******* leaked *******\n"); - _printf ("**********************\n"); - LeakFile (tree); - if ( leaktest ) { - _printf ("--- MAP LEAKED, ABORTING LEAKTEST ---\n"); - exit (0); - } - leaked = qtrue; - - // chop the sides to the convex hull of - // their visible fragments, giving us the smallest - // polygons - ClipSidesIntoTree( e, tree ); - } - - // save out information for visibility processing - NumberClusters( tree ); - if ( !leaked ) { - WritePortalFile( tree ); - } - if ( glview ) { - // dump the portals for debugging - WriteGLView( tree, source ); - } - FloodAreas (tree); - - // add references to the detail brushes - FilterDetailBrushesIntoTree( e, tree ); - - // create drawsurfs for triangle models - AddTriangleModels( tree ); - - // drawsurfs that cross fog boundaries will need to - // be split along the bound - if ( !nofog ) { - FogDrawSurfs(); // may fragment drawsurfs - } - - // subdivide each drawsurf as required by shader tesselation - if ( !nosubdivide ) { - SubdivideDrawSurfs( e, tree ); - } - - // merge together all common shaders on the same plane and remove - // all colinear points, so extra tjunctions won't be generated - if ( !nomerge ) { - MergeSides( e, tree ); // !@# testing - } - - // add in any vertexes required to fix tjunctions - if ( !notjunc ) { - FixTJunctions( e ); - } - - // allocate lightmaps for faces and patches - AllocateLightmaps( e ); - - // add references to the final drawsurfs in the apropriate clusters - FilterDrawsurfsIntoTree( e, tree ); - - EndModel( tree->headnode ); - - FreeTree (tree); -} - -/* -============ -ProcessSubModel - -============ -*/ -void ProcessSubModel( void ) { - entity_t *e; - tree_t *tree; - bspbrush_t *b, *bc; - node_t *node; - - BeginModel (); - - e = &entities[entity_num]; - e->firstDrawSurf = numMapDrawSurfs; - - PatchMapDrawSurfs( e ); - - // just put all the brushes in an empty leaf - // FIXME: patches? - node = AllocNode(); - node->planenum = PLANENUM_LEAF; - for ( b = e->brushes ; b ; b = b->next ) { - bc = CopyBrush( b ); - bc->next = node->brushlist; - node->brushlist = bc; - } - - tree = AllocTree(); - tree->headnode = node; - - ClipSidesIntoTree( e, tree ); - - // subdivide each drawsurf as required by shader tesselation or fog - if ( !nosubdivide ) { - SubdivideDrawSurfs( e, tree ); - } - - // merge together all common shaders on the same plane and remove - // all colinear points, so extra tjunctions won't be generated - if ( !nomerge ) { - MergeSides( e, tree ); // !@# testing - } - - // add in any vertexes required to fix tjunctions - if ( !notjunc ) { - FixTJunctions( e ); - } - - // allocate lightmaps for faces and patches - AllocateLightmaps( e ); - - // add references to the final drawsurfs in the apropriate clusters - FilterDrawsurfsIntoTree( e, tree ); - - EndModel ( node ); - - FreeTree( tree ); -} - - -/* -============ -ProcessModels -============ -*/ -void ProcessModels (void) -{ - qboolean oldVerbose; - entity_t *entity; - - oldVerbose = verbose; - - BeginBSPFile (); - - for ( entity_num=0 ; entity_num< num_entities ; entity_num++ ) { - entity = &entities[entity_num]; - - if ( !entity->brushes && !entity->patches ) { - continue; - } - - qprintf ("############### model %i ###############\n", nummodels); - if (entity_num == 0) - ProcessWorldModel (); - else - ProcessSubModel (); - - if (!verboseentities) - verbose = qfalse; // don't bother printing submodels - } - - verbose = oldVerbose; -} - -/* -============ -Bspinfo -============ -*/ -void Bspinfo( int count, char **fileNames ) { - int i; - char source[1024]; - int size; - FILE *f; - - if ( count < 1 ) { - _printf( "No files to dump info for.\n"); - return; - } - - for ( i = 0 ; i < count ; i++ ) { - _printf ("---------------------\n"); - strcpy (source, fileNames[ i ] ); - DefaultExtension (source, ".bsp"); - f = fopen (source, "rb"); - if (f) - { - size = Q_filelength (f); - fclose (f); - } - else - size = 0; - _printf ("%s: %i\n", source, size); - - LoadBSPFile (source); - PrintBSPFileSizes (); - _printf ("---------------------\n"); - } -} - - -/* -============ -OnlyEnts -============ -*/ -void OnlyEnts( void ) { - char out[1024]; - - sprintf (out, "%s.bsp", source); - LoadBSPFile (out); - num_entities = 0; - - LoadMapFile (name); - SetModelNumbers (); - SetLightStyles (); - - UnparseEntities (); - - WriteBSPFile (out); -} - - -/* -============ -OnlyTextures -============ -*/ -void OnlyTextures( void ) { // FIXME!!! - char out[1024]; - int i; - - Error( "-onlytextures isn't working now..." ); - - sprintf (out, "%s.bsp", source); - - LoadMapFile (name); - - LoadBSPFile (out); - - // replace all the drawsurface shader names - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - } - - WriteBSPFile (out); -} - - -/* -============ -main -============ -*/ -int LightMain( int argc, char **argv ); -int VLightMain (int argc, char **argv); -int VSoundMain (int argc, char **argv); -int VisMain( int argc, char **argv ); - -int main (int argc, char **argv) { - int i; - double start, end; - char path[1024]; - - _printf ("Q3Map v1.0s (c) 1999 Id Software Inc.\n"); - - if ( argc < 2 ) { - Error ("usage: q3map [options] mapfile"); - } - - // check for general program options - if (!strcmp(argv[1], "-info")) { - Bspinfo( argc - 2, argv + 2 ); - return 0; - } - if (!strcmp(argv[1], "-light")) { - LightMain( argc - 1, argv + 1 ); - return 0; - } - if (!strcmp(argv[1], "-vlight")) { - VLightMain( argc - 1, argv + 1 ); - return 0; - } - if (!strcmp(argv[1], "-vsound")) { - VSoundMain( argc - 1, argv + 1 ); - return 0; - } - if (!strcmp(argv[1], "-vis")) { - VisMain( argc - 1, argv + 1 ); - return 0; - } - - // do a bsp if nothing else was specified - - _printf ("---- q3map ----\n"); - - tempsource[0] = '\0'; - - for (i=1 ; i<argc ; i++) - { - if (!strcmp(argv[i],"-tempname")) - { - strcpy(tempsource, argv[++i]); - } - else if (!strcmp(argv[i],"-threads")) - { - numthreads = atoi (argv[i+1]); - i++; - } - else if (!strcmp(argv[i],"-glview")) - { - glview = qtrue; - } - else if (!strcmp(argv[i], "-v")) - { - _printf ("verbose = true\n"); - verbose = qtrue; - } - else if (!strcmp(argv[i], "-draw")) - { - _printf ("drawflag = true\n"); - drawflag = qtrue; - } - else if (!strcmp(argv[i], "-nowater")) - { - _printf ("nowater = true\n"); - nowater = qtrue; - } - else if (!strcmp(argv[i], "-noopt")) - { - _printf ("noopt = true\n"); - noopt = qtrue; - } - else if (!strcmp(argv[i], "-nofill")) - { - _printf ("nofill = true\n"); - nofill = qtrue; - } - else if (!strcmp(argv[i], "-nodetail")) - { - _printf ("nodetail = true\n"); - nodetail = qtrue; - } - else if (!strcmp(argv[i], "-fulldetail")) - { - _printf ("fulldetail = true\n"); - fulldetail = qtrue; - } - else if (!strcmp(argv[i], "-onlyents")) - { - _printf ("onlyents = true\n"); - onlyents = qtrue; - } - else if (!strcmp(argv[i], "-onlytextures")) - { - _printf ("onlytextures = true\n"); // FIXME: make work again! - onlytextures = qtrue; - } - else if (!strcmp(argv[i], "-micro")) - { - microvolume = atof(argv[i+1]); - _printf ("microvolume = %f\n", microvolume); - i++; - } - else if (!strcmp(argv[i], "-nofog")) - { - _printf ("nofog = true\n"); - nofog = qtrue; - } - else if (!strcmp(argv[i], "-nosubdivide")) - { - _printf ("nosubdivide = true\n"); - nosubdivide = qtrue; - } - else if (!strcmp(argv[i], "-leaktest")) - { - _printf ("leaktest = true\n"); - leaktest = qtrue; - } - else if (!strcmp(argv[i], "-verboseentities")) - { - _printf ("verboseentities = true\n"); - verboseentities = qtrue; - } - else if (!strcmp(argv[i], "-nocurves")) - { - noCurveBrushes = qtrue; - _printf ("no curve brushes\n"); - } - else if (!strcmp(argv[i], "-notjunc")) - { - notjunc = qtrue; - _printf ("no tjunction fixing\n"); - } - else if (!strcmp(argv[i], "-expand")) - { - testExpand = qtrue; - _printf ("Writing expanded.map.\n"); - } - else if (!strcmp(argv[i], "-showseams")) - { - showseams = qtrue; - _printf ("Showing seams on terrain.\n"); - } - else if (!strcmp (argv[i],"-tmpout")) - { - strcpy (outbase, "/tmp"); - } - else if (!strcmp (argv[i],"-fakemap")) - { - fakemap = qtrue; - _printf( "will generate fakemap.map\n"); - } - else if (!strcmp(argv[i], "-samplesize")) - { - samplesize = atoi(argv[i+1]); - if (samplesize < 1) samplesize = 1; - i++; - _printf("lightmap sample size is %dx%d units\n", samplesize, samplesize); - } - else if (argv[i][0] == '-') - Error ("Unknown option \"%s\"", argv[i]); - else - break; - } - - if (i != argc - 1) - Error ("usage: q3map [options] mapfile"); - - start = I_FloatTime (); - - ThreadSetDefault (); - //numthreads = 1; // multiple threads aren't helping because of heavy malloc use - SetQdirFromPath (argv[i]); - -#ifdef _WIN32 - InitPakFile(gamedir, NULL); -#endif - - strcpy (source, ExpandArg (argv[i])); - StripExtension (source); - - // delete portal and line files - sprintf (path, "%s.prt", source); - remove (path); - sprintf (path, "%s.lin", source); - remove (path); - - strcpy (name, ExpandArg (argv[i])); - if ( strcmp(name + strlen(name) - 4, ".reg" ) ) { - // if we are doing a full map, delete the last saved region map - sprintf (path, "%s.reg", source); - remove (path); - - DefaultExtension (name, ".map"); // might be .reg - } - - // - // if onlyents, just grab the entites and resave - // - if ( onlyents ) { - OnlyEnts(); - return 0; - } - - // - // if onlytextures, just grab the textures and resave - // - if ( onlytextures ) { - OnlyTextures(); - return 0; - } - - // - // start from scratch - // - LoadShaderInfo(); - - // load original file from temp spot in case it was renamed by the editor on the way in - if (strlen(tempsource) > 0) { - LoadMapFile (tempsource); - } else { - LoadMapFile (name); - } - - SetModelNumbers (); - SetLightStyles (); - - ProcessModels (); - - EndBSPFile(); - - end = I_FloatTime (); - _printf ("%5.0f seconds elapsed\n", end-start); - - // remove temp name if appropriate - if (strlen(tempsource) > 0) { - remove(tempsource); - } - - return 0; -} - diff --git a/q3map/facebsp.c b/q3map/facebsp.c deleted file mode 100644 index a146a21..0000000 --- a/q3map/facebsp.c +++ /dev/null @@ -1,379 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "qbsp.h" - - -int c_faceLeafs; - - -/* -================ -AllocBspFace -================ -*/ -bspface_t *AllocBspFace( void ) { - bspface_t *f; - - f = malloc(sizeof(*f)); - memset( f, 0, sizeof(*f) ); - - return f; -} - -/* -================ -FreeBspFace -================ -*/ -void FreeBspFace( bspface_t *f ) { - if ( f->w ) { - FreeWinding( f->w ); - } - free( f ); -} - - -/* -================ -SelectSplitPlaneNum -================ -*/ -int hintsplit; - -#define BLOCK_SIZE 1024 -int SelectSplitPlaneNum( node_t *node, bspface_t *list ) { - bspface_t *split; - bspface_t *check; - bspface_t *bestSplit; - int splits, facing, front, back; - int side; - plane_t *plane; - int value, bestValue; - int i; - vec3_t normal; - float dist; - int planenum; - - hintsplit = qfalse; - // if it is crossing a 1k block boundary, force a split - for ( i = 0 ; i < 2 ; i++ ) { - dist = BLOCK_SIZE * ( floor( node->mins[i] / BLOCK_SIZE ) + 1 ); - if ( node->maxs[i] > dist ) { - VectorClear( normal ); - normal[i] = 1; - planenum = FindFloatPlane( normal, dist ); - return planenum; - } - } - - // pick one of the face planes - bestValue = -99999; - bestSplit = list; - - for ( split = list ; split ; split = split->next ) { - split->checked = qfalse; - } - - for ( split = list ; split ; split = split->next ) { - if ( split->checked ) { - continue; - } - plane = &mapplanes[ split->planenum ]; - splits = 0; - facing = 0; - front = 0; - back = 0; - for ( check = list ; check ; check = check->next ) { - if ( check->planenum == split->planenum ) { - facing++; - check->checked = qtrue; // won't need to test this plane again - continue; - } - side = WindingOnPlaneSide( check->w, plane->normal, plane->dist ); - if ( side == SIDE_CROSS ) { - splits++; - } else if ( side == SIDE_FRONT ) { - front++; - } else if ( side == SIDE_BACK ) { - back++; - } - } - value = 5*facing - 5*splits; // - abs(front-back); - if ( plane->type < 3 ) { - value+=5; // axial is better - } - value += split->priority; // prioritize hints higher - - if ( value > bestValue ) { - bestValue = value; - bestSplit = split; - } - } - - if ( bestValue == -99999 ) { - return -1; - } - - if (bestSplit->hint) - hintsplit = qtrue; - - return bestSplit->planenum; -} - -int CountFaceList( bspface_t *list ) { - int c; - c = 0; - for ( ; list ; list = list->next ) { - c++; - } - return c; -} - -/* -================ -BuildFaceTree_r -================ -*/ -void BuildFaceTree_r( node_t *node, bspface_t *list ) { - bspface_t *split; - bspface_t *next; - int side; - plane_t *plane; - bspface_t *newFace; - bspface_t *childLists[2]; - winding_t *frontWinding, *backWinding; - int i; - int splitPlaneNum; - - i = CountFaceList( list ); - - splitPlaneNum = SelectSplitPlaneNum( node, list ); - // if we don't have any more faces, this is a node - if ( splitPlaneNum == -1 ) { - node->planenum = PLANENUM_LEAF; - c_faceLeafs++; - return; - } - - // partition the list - node->planenum = splitPlaneNum; - node->hint = hintsplit; - plane = &mapplanes[ splitPlaneNum ]; - childLists[0] = NULL; - childLists[1] = NULL; - for ( split = list ; split ; split = next ) { - next = split->next; - - if ( split->planenum == node->planenum ) { - FreeBspFace( split ); - continue; - } - - side = WindingOnPlaneSide( split->w, plane->normal, plane->dist ); - - if ( side == SIDE_CROSS ) { - ClipWindingEpsilon( split->w, plane->normal, plane->dist, CLIP_EPSILON * 2, - &frontWinding, &backWinding ); - if ( frontWinding ) { - newFace = AllocBspFace(); - newFace->w = frontWinding; - newFace->next = childLists[0]; - newFace->planenum = split->planenum; - newFace->priority = split->priority; - newFace->hint = split->hint; - childLists[0] = newFace; - } - if ( backWinding ) { - newFace = AllocBspFace(); - newFace->w = backWinding; - newFace->next = childLists[1]; - newFace->planenum = split->planenum; - newFace->priority = split->priority; - newFace->hint = split->hint; - childLists[1] = newFace; - } - FreeBspFace( split ); - } else if ( side == SIDE_FRONT ) { - split->next = childLists[0]; - childLists[0] = split; - } else if ( side == SIDE_BACK ) { - split->next = childLists[1]; - childLists[1] = split; - } - } - - - // recursively process children - for ( i = 0 ; i < 2 ; i++ ) { - node->children[i] = AllocNode(); - node->children[i]->parent = node; - VectorCopy( node->mins, node->children[i]->mins ); - VectorCopy( node->maxs, node->children[i]->maxs ); - } - - for ( i = 0 ; i < 3 ; i++ ) { - if ( plane->normal[i] == 1 ) { - node->children[0]->mins[i] = plane->dist; - node->children[1]->maxs[i] = plane->dist; - break; - } - } - - for ( i = 0 ; i < 2 ; i++ ) { - BuildFaceTree_r ( node->children[i], childLists[i]); - } -} - - -/* -================ -FaceBSP - -List will be freed before returning -================ -*/ -tree_t *FaceBSP( bspface_t *list ) { - tree_t *tree; - bspface_t *face; - int i; - int count; - - qprintf( "--- FaceBSP ---\n" ); - - tree = AllocTree (); - - count = 0; - for ( face = list ; face ; face = face->next ) { - count++; - for ( i = 0 ; i < face->w->numpoints ; i++ ) { - AddPointToBounds( face->w->p[i], tree->mins, tree->maxs); - } - } - qprintf( "%5i faces\n", count ); - - tree->headnode = AllocNode(); - VectorCopy( tree->mins, tree->headnode->mins ); - VectorCopy( tree->maxs, tree->headnode->maxs ); - c_faceLeafs = 0; - - BuildFaceTree_r ( tree->headnode, list ); - - qprintf( "%5i leafs\n", c_faceLeafs ); - - return tree; -} - - -/* -================= -BspFaceForPortal -================= -*/ -bspface_t *BspFaceForPortal( portal_t *p ) { - bspface_t *f; - - f = AllocBspFace(); - f->w = CopyWinding( p->winding ); - f->planenum = p->onnode->planenum & ~1; - - return f; -} - - - -/* -================= -MakeStructuralBspFaceList -================= -*/ -bspface_t *MakeStructuralBspFaceList( bspbrush_t *list ) { - bspbrush_t *b; - int i; - side_t *s; - winding_t *w; - bspface_t *f, *flist; - - flist = NULL; - for ( b = list ; b ; b = b->next ) { - if ( b->detail ) { - continue; - } - for ( i = 0 ; i < b->numsides ; i++ ) { - s = &b->sides[i]; - w = s->winding; - if ( !w ) { - continue; - } - f = AllocBspFace(); - f->w = CopyWinding( w ); - f->planenum = s->planenum & ~1; - f->next = flist; - if (s->surfaceFlags & SURF_HINT) { - //f->priority = HINT_PRIORITY; - f->hint = qtrue; - } - flist = f; - } - } - - return flist; -} - -/* -================= -MakeVisibleBspFaceList -================= -*/ -bspface_t *MakeVisibleBspFaceList( bspbrush_t *list ) { - bspbrush_t *b; - int i; - side_t *s; - winding_t *w; - bspface_t *f, *flist; - - flist = NULL; - for ( b = list ; b ; b = b->next ) { - if ( b->detail ) { - continue; - } - for ( i = 0 ; i < b->numsides ; i++ ) { - s = &b->sides[i]; - w = s->visibleHull; - if ( !w ) { - continue; - } - f = AllocBspFace(); - f->w = CopyWinding( w ); - f->planenum = s->planenum & ~1; - f->next = flist; - if (s->surfaceFlags & SURF_HINT) { - //f->priority = HINT_PRIORITY; - f->hint = qtrue; - } - flist = f; - } - } - - return flist; -} - diff --git a/q3map/fog.c b/q3map/fog.c deleted file mode 100644 index fa938dd..0000000 --- a/q3map/fog.c +++ /dev/null @@ -1,554 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#include "qbsp.h" - - -int c_fogFragment; -int c_fogPatchFragments; - -/* -==================== -DrawSurfToMesh -==================== -*/ -mesh_t *DrawSurfToMesh( mapDrawSurface_t *ds ) { - mesh_t *m; - - m = malloc( sizeof( *m ) ); - m->width = ds->patchWidth; - m->height = ds->patchHeight; - m->verts = malloc( sizeof(m->verts[0]) * m->width * m->height ); - memcpy( m->verts, ds->verts, sizeof(m->verts[0]) * m->width * m->height ); - - return m; -} - - -/* -==================== -SplitMeshByPlane -==================== -*/ -void SplitMeshByPlane( mesh_t *in, vec3_t normal, float dist, mesh_t **front, mesh_t **back ) { - int w, h, split; - float d[MAX_PATCH_SIZE][MAX_PATCH_SIZE]; - drawVert_t *dv, *v1, *v2; - int c_front, c_back, c_on; - mesh_t *f, *b; - int i; - float frac; - int frontAprox, backAprox; - - for ( i = 0 ; i < 2 ; i++ ) { - dv = in->verts; - c_front = 0; - c_back = 0; - c_on = 0; - for ( h = 0 ; h < in->height ; h++ ) { - for ( w = 0 ; w < in->width ; w++, dv++ ) { - d[h][w] = DotProduct( dv->xyz, normal ) - dist; - if ( d[h][w] > ON_EPSILON ) { - c_front++; - } else if ( d[h][w] < -ON_EPSILON ) { - c_back++; - } else { - c_on++; - } - } - } - - *front = NULL; - *back = NULL; - - if ( !c_front ) { - *back = in; - return; - } - if ( !c_back ) { - *front = in; - return; - } - - // find a split point - split = -1; - for ( w = 0 ; w < in->width -1 ; w++ ) { - if ( ( d[0][w] < 0 ) != ( d[0][w+1] < 0 ) ) { - if ( split == -1 ) { - split = w; - break; - } - } - } - - if ( split == -1 ) { - if ( i == 1 ) { - qprintf( "No crossing points in patch\n"); - *front = in; - return; - } - - in = TransposeMesh( in ); - InvertMesh( in ); - continue; - } - - // make sure the split point stays the same for all other rows - for ( h = 1 ; h < in->height ; h++ ) { - for ( w = 0 ; w < in->width -1 ; w++ ) { - if ( ( d[h][w] < 0 ) != ( d[h][w+1] < 0 ) ) { - if ( w != split ) { - _printf( "multiple crossing points for patch -- can't clip\n"); - *front = in; - return; - } - } - } - if ( ( d[h][split] < 0 ) == ( d[h][split+1] < 0 ) ) { - _printf( "differing crossing points for patch -- can't clip\n"); - *front = in; - return; - } - } - - break; - } - - - // create two new meshes - f = malloc( sizeof( *f ) ); - f->width = split + 2; - if ( ! (f->width & 1) ) { - f->width++; - frontAprox = 1; - } else { - frontAprox = 0; - } - if ( f->width > MAX_PATCH_SIZE ) { - Error( "MAX_PATCH_SIZE after split"); - } - f->height = in->height; - f->verts = malloc( sizeof(f->verts[0]) * f->width * f->height ); - - b = malloc( sizeof( *b ) ); - b->width = in->width - split; - if ( ! (b->width & 1) ) { - b->width++; - backAprox = 1; - } else { - backAprox = 0; - } - if ( b->width > MAX_PATCH_SIZE ) { - Error( "MAX_PATCH_SIZE after split"); - } - b->height = in->height; - b->verts = malloc( sizeof(b->verts[0]) * b->width * b->height ); - - if ( d[0][0] > 0 ) { - *front = f; - *back = b; - } else { - *front = b; - *back = f; - } - - // distribute the points - for ( w = 0 ; w < in->width ; w++ ) { - for ( h = 0 ; h < in->height ; h++ ) { - if ( w <= split ) { - f->verts[ h * f->width + w ] = in->verts[ h * in->width + w ]; - } else { - b->verts[ h * b->width + w - split + backAprox ] = in->verts[ h * in->width + w ]; - } - } - } - - // clip the crossing line - for ( h = 0 ; h < in->height ; h++ ) { - dv = &f->verts[ h * f->width + split + 1 ]; - v1 = &in->verts[ h * in->width + split ]; - v2 = &in->verts[ h * in->width + split + 1 ]; - frac = d[h][split] / ( d[h][split] - d[h][split+1] ); - for ( i = 0 ; i < 10 ; i++ ) { - dv->xyz[i] = v1->xyz[i] + frac * ( v2->xyz[i] - v1->xyz[i] ); - } - dv->xyz[10] = 0;//set all 4 colors to 0 - if ( frontAprox ) { - f->verts[ h * f->width + split + 2 ] = *dv; - } - b->verts[ h * b->width ] = *dv; - if ( backAprox ) { - b->verts[ h * b->width + 1 ] = *dv; - } - } - - /* -PrintMesh( in ); -_printf("\n"); -PrintMesh( f ); -_printf("\n"); -PrintMesh( b ); -_printf("\n"); - */ - - FreeMesh( in ); -} - - -/* -==================== -ChopPatchByBrush -==================== -*/ -qboolean ChopPatchByBrush( mapDrawSurface_t *ds, bspbrush_t *b ) { - int i, j; - side_t *s; - plane_t *plane; - mesh_t *outside[MAX_BRUSH_SIDES]; - int numOutside; - mesh_t *m, *front, *back; - mapDrawSurface_t *newds; - - m = DrawSurfToMesh( ds ); - numOutside = 0; - - // only split by the top and bottom planes to avoid - // some messy patch clipping issues - - for ( i = 4 ; i <= 5 ; i++ ) { - s = &b->sides[ i ]; - plane = &mapplanes[ s->planenum ]; - - SplitMeshByPlane( m, plane->normal, plane->dist, &front, &back ); - - if ( !back ) { - // nothing actually contained inside - for ( j = 0 ; j < numOutside ; j++ ) { - FreeMesh( outside[j] ); - } - return qfalse; - } - m = back; - - if ( front ) { - if ( numOutside == MAX_BRUSH_SIDES ) { - Error( "MAX_BRUSH_SIDES" ); - } - outside[ numOutside ] = front; - numOutside++; - } - } - - // all of outside fragments become seperate drawsurfs - c_fogPatchFragments += numOutside; - for ( i = 0 ; i < numOutside ; i++ ) { - newds = DrawSurfaceForMesh( outside[ i ] ); - newds->shaderInfo = ds->shaderInfo; - FreeMesh( outside[ i ] ); - } - - // replace ds with m - ds->patchWidth = m->width; - ds->patchHeight = m->height; - ds->numVerts = m->width * m->height; - free( ds->verts ); - ds->verts = malloc( ds->numVerts * sizeof( *ds->verts ) ); - memcpy( ds->verts, m->verts, ds->numVerts * sizeof( *ds->verts ) ); - - FreeMesh( m ); - - return qtrue; -} - -//=============================================================================== - -/* -==================== -WindingFromDrawSurf -==================== -*/ -winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds ) { - winding_t *w; - int i; - - w = AllocWinding( ds->numVerts ); - w->numpoints = ds->numVerts; - for ( i = 0 ; i < ds->numVerts ; i++ ) { - VectorCopy( ds->verts[i].xyz, w->p[i] ); - } - return w; -} - -/* -==================== -ChopFaceByBrush - -There may be a fragment contained in the brush -==================== -*/ -qboolean ChopFaceByBrush( mapDrawSurface_t *ds, bspbrush_t *b ) { - int i, j; - side_t *s; - plane_t *plane; - winding_t *w; - winding_t *front, *back; - winding_t *outside[MAX_BRUSH_SIDES]; - int numOutside; - mapDrawSurface_t *newds; - drawVert_t *dv; - shaderInfo_t *si; - float mins[2]; - - // brush primitive : - // axis base - vec3_t texX,texY; - vec_t x,y; - - w = WindingFromDrawSurf( ds ); - numOutside = 0; - - for ( i = 0 ; i < b->numsides ; i++ ) { - s = &b->sides[ i ]; - if ( s->backSide ) { - continue; - } - plane = &mapplanes[ s->planenum ]; - - // handle coplanar outfacing (don't fog) - if ( ds->side->planenum == s->planenum ) { - return qfalse; - } - - // handle coplanar infacing (keep inside) - if ( ( ds->side->planenum ^ 1 ) == s->planenum ) { - continue; - } - - // general case - ClipWindingEpsilon( w, plane->normal, plane->dist, ON_EPSILON, - &front, &back ); - FreeWinding( w ); - if ( !back ) { - // nothing actually contained inside - for ( j = 0 ; j < numOutside ; j++ ) { - FreeWinding( outside[j] ); - } - return qfalse; - } - if ( front ) { - if ( numOutside == MAX_BRUSH_SIDES ) { - Error( "MAX_BRUSH_SIDES" ); - } - outside[ numOutside ] = front; - numOutside++; - } - w = back; - } - - // all of outside fragments become seperate drawsurfs - // linked to the same side - c_fogFragment += numOutside; - s = ds->side; - - for ( i = 0 ; i < numOutside ; i++ ) { - newds = DrawSurfaceForSide( ds->mapBrush, s, outside[i] ); - FreeWinding( outside[i] ); - } - - - // replace ds->verts with the verts for w - ds->numVerts = w->numpoints; - free( ds->verts ); - - ds->verts = malloc( ds->numVerts * sizeof( *ds->verts ) ); - memset( ds->verts, 0, ds->numVerts * sizeof( *ds->verts ) ); - - si = s->shaderInfo; - - mins[0] = 9999; - mins[1] = 9999; - - // compute s/t coordinates from brush primitive texture matrix - // compute axis base - ComputeAxisBase( mapplanes[s->planenum].normal, texX, texY ); - - for ( j = 0 ; j < w->numpoints ; j++ ) { - dv = ds->verts + j; - VectorCopy( w->p[j], dv->xyz ); - - if (g_bBrushPrimit==BPRIMIT_OLDBRUSHES) - { - // calculate texture s/t - dv->st[0] = s->vecs[0][3] + DotProduct( s->vecs[0], dv->xyz ); - dv->st[1] = s->vecs[1][3] + DotProduct( s->vecs[1], dv->xyz ); - dv->st[0] /= si->width; - dv->st[1] /= si->height; - } - else - { - // calculate texture s/t from brush primitive texture matrix - x = DotProduct( dv->xyz, texX ); - y = DotProduct( dv->xyz, texY ); - dv->st[0]=s->texMat[0][0]*x+s->texMat[0][1]*y+s->texMat[0][2]; - dv->st[1]=s->texMat[1][0]*x+s->texMat[1][1]*y+s->texMat[1][2]; - } - - if ( dv->st[0] < mins[0] ) { - mins[0] = dv->st[0]; - } - if ( dv->st[1] < mins[1] ) { - mins[1] = dv->st[1]; - } - - // copy normal - VectorCopy ( mapplanes[s->planenum].normal, dv->normal ); - } - - // adjust the texture coordinates to be as close to 0 as possible - if ( !si->globalTexture ) { - mins[0] = floor( mins[0] ); - mins[1] = floor( mins[1] ); - for ( i = 0 ; i < w->numpoints ; i++ ) { - dv = ds->verts + i; - dv->st[0] -= mins[0]; - dv->st[1] -= mins[1]; - } - } - - return qtrue; -} - -//=============================================================================== - - -/* -===================== -FogDrawSurfs - -Call after the surface list has been pruned, -before tjunction fixing -before lightmap allocation -===================== -*/ -void FogDrawSurfs( void ) { - int i, j, k; - mapDrawSurface_t *ds; - bspbrush_t *b; - vec3_t mins, maxs; - int c_fogged; - int numBaseDrawSurfs; - dfog_t *fog; - - qprintf("----- FogDrawsurfs -----\n"); - - c_fogged = 0; - c_fogFragment = 0; - - // find all fog brushes - for ( b = entities[0].brushes ; b ; b = b->next ) { - if ( !(b->contents & CONTENTS_FOG) ) { - continue; - } - - if ( numFogs == MAX_MAP_FOGS ) { - Error( "MAX_MAP_FOGS" ); - } - fog = &dfogs[numFogs]; - numFogs++; - fog->brushNum = b->outputNumber; - - // find a side with a valid shaderInfo - // non-axial fog columns may have bevel planes that need to be skipped - for ( i = 0 ; i < b->numsides ; i++ ) { - if ( b->sides[i].shaderInfo && (b->sides[i].shaderInfo->contents & CONTENTS_FOG) ) { - strcpy( fog->shader, b->sides[i].shaderInfo->shader ); - break; - } - } - if ( i == b->numsides ) { - continue; // shouldn't happen - } - - fog->visibleSide = -1; - - // clip each surface into this, but don't clip any of - // the resulting fragments to the same brush - numBaseDrawSurfs = numMapDrawSurfs; - for ( i = 0 ; i < numBaseDrawSurfs ; i++ ) { - ds = &mapDrawSurfs[i]; - - // bound the drawsurf - ClearBounds( mins, maxs ); - for ( j = 0 ; j < ds->numVerts ; j++ ) { - AddPointToBounds( ds->verts[j].xyz, mins, maxs ); - } - - // check against the fog brush - for ( k = 0 ; k < 3 ; k++ ) { - if ( mins[k] > b->maxs[k] ) { - break; - } - if ( maxs[k] < b->mins[k] ) { - break; - } - } - if ( k < 3 ) { - continue; // bboxes don't intersect - } - - if ( ds->mapBrush == b ) { - int s; - - s = ds->side - b->sides; - if ( s <= 6 ) { // not one of the reversed inside faces - // this is a visible fog plane - if ( fog->visibleSide != -1 ) { - _printf( "WARNING: fog brush %i has multiple visible sides\n", b->brushnum ); - } - fog->visibleSide = s; - } - } - - if ( ds->miscModel ) { - // we could write splitting code for trimodels if we wanted to... - c_fogged++; - ds->fogNum = numFogs - 1; - } else if ( ds->patch ) { - if ( ChopPatchByBrush( ds, b ) ) { - c_fogged++; - ds->fogNum = numFogs - 1; - } - } else { - if ( ChopFaceByBrush( ds, b ) ) { - c_fogged++; - ds->fogNum = numFogs - 1; - } - } - } - } - - // split the drawsurfs by the fog brushes - - qprintf( "%5i fogs\n", numFogs ); - qprintf( "%5i fog polygon fragments\n", c_fogFragment ); - qprintf( "%5i fog patch fragments\n", c_fogPatchFragments ); - qprintf( "%5i fogged drawsurfs\n", c_fogged ); -} diff --git a/q3map/gldraw.c b/q3map/gldraw.c deleted file mode 100644 index 80620a4..0000000 --- a/q3map/gldraw.c +++ /dev/null @@ -1,232 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include <windows.h> -#include <GL/gl.h> -#include <GL/glu.h> -#include <GL/glaux.h> - -#include "qbsp.h" - -// can't use the glvertex3fv functions, because the vec3_t fields -// could be either floats or doubles, depending on DOUBLEVEC_T - -qboolean drawflag; -vec3_t draw_mins, draw_maxs; - - -#define WIN_SIZE 512 - -void InitWindow (void) -{ - auxInitDisplayMode (AUX_SINGLE | AUX_RGB); - auxInitPosition (0, 0, WIN_SIZE, WIN_SIZE); - auxInitWindow ("qcsg"); -} - -void Draw_ClearWindow (void) -{ - static int init; - int w, h, g; - vec_t mx, my; - - if (!drawflag) - return; - - if (!init) - { - init = qtrue; - InitWindow (); - } - - glClearColor (1,0.8,0.8,0); - glClear (GL_COLOR_BUFFER_BIT); - - w = (draw_maxs[0] - draw_mins[0]); - h = (draw_maxs[1] - draw_mins[1]); - - mx = draw_mins[0] + w/2; - my = draw_mins[1] + h/2; - - g = w > h ? w : h; - - glLoadIdentity (); - gluPerspective (90, 1, 2, 16384); - gluLookAt (mx, my, draw_maxs[2] + g/2, mx , my, draw_maxs[2], 0, 1, 0); - - glColor3f (0,0,0); -// glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); - glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); - glDisable (GL_DEPTH_TEST); - glEnable (GL_BLEND); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - -#if 0 - glColor4f (1,0,0,0.5); - glBegin (GL_POLYGON); - - glVertex3f (0, 500, 0); - glVertex3f (0, 900, 0); - glVertex3f (0, 900, 100); - glVertex3f (0, 500, 100); - - glEnd (); -#endif - - glFlush (); - -} - -void Draw_SetRed (void) -{ - if (!drawflag) - return; - - glColor3f (1,0,0); -} - -void Draw_SetGrey (void) -{ - if (!drawflag) - return; - - glColor3f (0.5,0.5,0.5); -} - -void Draw_SetBlack (void) -{ - if (!drawflag) - return; - - glColor3f (0,0,0); -} - -void DrawWinding (winding_t *w) -{ - int i; - - if (!drawflag) - return; - - glColor4f (0,0,0,0.5); - glBegin (GL_LINE_LOOP); - for (i=0 ; i<w->numpoints ; i++) - glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] ); - glEnd (); - - glColor4f (0,1,0,0.3); - glBegin (GL_POLYGON); - for (i=0 ; i<w->numpoints ; i++) - glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] ); - glEnd (); - - glFlush (); -} - -void DrawAuxWinding (winding_t *w) -{ - int i; - - if (!drawflag) - return; - - glColor4f (0,0,0,0.5); - glBegin (GL_LINE_LOOP); - for (i=0 ; i<w->numpoints ; i++) - glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] ); - glEnd (); - - glColor4f (1,0,0,0.3); - glBegin (GL_POLYGON); - for (i=0 ; i<w->numpoints ; i++) - glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] ); - glEnd (); - - glFlush (); -} - -//============================================================ - -#define GLSERV_PORT 25001 - -qboolean wins_init; -int draw_socket; - -void GLS_BeginScene (void) -{ - WSADATA winsockdata; - WORD wVersionRequested; - struct sockaddr_in address; - int r; - - if (!wins_init) - { - wins_init = qtrue; - - wVersionRequested = MAKEWORD(1, 1); - - r = WSAStartup (MAKEWORD(1, 1), &winsockdata); - - if (r) - Error ("Winsock initialization failed."); - - } - - // connect a socket to the server - - draw_socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (draw_socket == -1) - Error ("draw_socket failed"); - - address.sin_family = AF_INET; - address.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - address.sin_port = GLSERV_PORT; - r = connect (draw_socket, (struct sockaddr *)&address, sizeof(address)); - if (r == -1) - { - closesocket (draw_socket); - draw_socket = 0; - } -} - -void GLS_Winding (winding_t *w, int code) -{ - byte buf[1024]; - int i, j; - - if (!draw_socket) - return; - - ((int *)buf)[0] = w->numpoints; - ((int *)buf)[1] = code; - for (i=0 ; i<w->numpoints ; i++) - for (j=0 ; j<3 ; j++) - ((float *)buf)[2+i*3+j] = w->p[i][j]; - - send (draw_socket, buf, w->numpoints*12+8, 0); -} - -void GLS_EndScene (void) -{ - closesocket (draw_socket); - draw_socket = 0; -} diff --git a/q3map/glfile.c b/q3map/glfile.c deleted file mode 100644 index b00df75..0000000 --- a/q3map/glfile.c +++ /dev/null @@ -1,148 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "qbsp.h" - -int c_glfaces; - -int PortalVisibleSides (portal_t *p) -{ - int fcon, bcon; - - if (!p->onnode) - return 0; // outside - - fcon = p->nodes[0]->opaque; - bcon = p->nodes[1]->opaque; - - // same contents never create a face - if (fcon == bcon) - return 0; - - if (!fcon) - return 1; - if (!bcon) - return 2; - return 0; -} - -void OutputWinding (winding_t *w, FILE *glview) -{ - static int level = 128; - vec_t light; - int i; - - fprintf (glview, "%i\n", w->numpoints); - level+=28; - light = (level&255)/255.0; - for (i=0 ; i<w->numpoints ; i++) - { - fprintf (glview, "%6.3f %6.3f %6.3f %6.3f %6.3f %6.3f\n", - w->p[i][0], - w->p[i][1], - w->p[i][2], - light, - light, - light); - } - fprintf (glview, "\n"); -} - -/* -============= -OutputPortal -============= -*/ -void OutputPortal (portal_t *p, FILE *glview) -{ - winding_t *w; - int sides; - - sides = PortalVisibleSides (p); - if (!sides) - return; - - c_glfaces++; - - w = p->winding; - - if (sides == 2) // back side - w = ReverseWinding (w); - - OutputWinding (w, glview); - - if (sides == 2) - FreeWinding(w); -} - -/* -============= -WriteGLView_r -============= -*/ -void WriteGLView_r (node_t *node, FILE *glview) -{ - portal_t *p, *nextp; - - if (node->planenum != PLANENUM_LEAF) - { - WriteGLView_r (node->children[0], glview); - WriteGLView_r (node->children[1], glview); - return; - } - - // write all the portals - for (p=node->portals ; p ; p=nextp) - { - if (p->nodes[0] == node) - { - OutputPortal (p, glview); - nextp = p->next[0]; - } - else - nextp = p->next[1]; - } -} - -/* -============= -WriteGLView -============= -*/ -void WriteGLView (tree_t *tree, char *source) -{ - char name[1024]; - FILE *glview; - - c_glfaces = 0; - sprintf (name, "%s%s.gl",outbase, source); - _printf ("Writing %s\n", name); - - glview = fopen (name, "w"); - if (!glview) - Error ("Couldn't open %s", name); - WriteGLView_r (tree->headnode, glview); - fclose (glview); - - _printf ("%5i c_glfaces\n", c_glfaces); -} - diff --git a/q3map/leakfile.c b/q3map/leakfile.c deleted file mode 100644 index 683c22a..0000000 --- a/q3map/leakfile.c +++ /dev/null @@ -1,100 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "qbsp.h" - -/* -============================================================================== - -LEAF FILE GENERATION - -Save out name.line for qe3 to read -============================================================================== -*/ - - -/* -============= -LeakFile - -Finds the shortest possible chain of portals -that leads from the outside leaf to a specifically -occupied leaf -============= -*/ -void LeakFile (tree_t *tree) -{ - vec3_t mid; - FILE *linefile; - char filename[1024]; - node_t *node; - int count; - - if (!tree->outside_node.occupied) - return; - - qprintf ("--- LeakFile ---\n"); - - // - // write the points to the file - // - sprintf (filename, "%s.lin", source); - linefile = fopen (filename, "w"); - if (!linefile) - Error ("Couldn't open %s\n", filename); - - count = 0; - node = &tree->outside_node; - while (node->occupied > 1) - { - int next; - portal_t *p, *nextportal; - node_t *nextnode; - int s; - - // find the best portal exit - next = node->occupied; - for (p=node->portals ; p ; p = p->next[!s]) - { - s = (p->nodes[0] == node); - if (p->nodes[s]->occupied - && p->nodes[s]->occupied < next) - { - nextportal = p; - nextnode = p->nodes[s]; - next = nextnode->occupied; - } - } - node = nextnode; - WindingCenter (nextportal->winding, mid); - fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]); - count++; - } - // add the occupant center - GetVectorForKey (node->occupant, "origin", mid); - - fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]); - qprintf ("%5i point linefile\n", count+1); - - fclose (linefile); -} - diff --git a/q3map/light.c b/q3map/light.c deleted file mode 100644 index 1563d58..0000000 --- a/q3map/light.c +++ /dev/null @@ -1,2149 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// light.c - -#include "light.h" -#ifdef _WIN32 -#ifdef _TTIMOBUILD -#include "pakstuff.h" -#else -#include "../libs/pakstuff.h" -#endif -#endif - - -#define EXTRASCALE 2 - -typedef struct { - float plane[4]; - vec3_t origin; - vec3_t vectors[2]; - shaderInfo_t *si; -} filter_t; - -#define MAX_FILTERS 1024 -filter_t filters[MAX_FILTERS]; -int numFilters; - -extern char source[1024]; - -qboolean notrace; -qboolean patchshadows; -qboolean dump; -qboolean extra; -qboolean extraWide; -qboolean lightmapBorder; - -qboolean noSurfaces; - -int samplesize = 16; //sample size in units -int novertexlighting = 0; -int nogridlighting = 0; - -// for run time tweaking of all area sources in the level -float areaScale = 0.25; - -// for run time tweaking of all point sources in the level -float pointScale = 7500; - -qboolean exactPointToPolygon = qtrue; - -float formFactorValueScale = 3; - -float linearScale = 1.0 / 8000; - -light_t *lights; -int numPointLights; -int numAreaLights; - -FILE *dumpFile; - -int c_visible, c_occluded; - -//int defaultLightSubdivide = 128; // vary by surface size? -int defaultLightSubdivide = 999; // vary by surface size? - -vec3_t ambientColor; - -vec3_t surfaceOrigin[ MAX_MAP_DRAW_SURFS ]; -int entitySurface[ MAX_MAP_DRAW_SURFS ]; - -// 7,9,11 normalized to avoid being nearly coplanar with common faces -//vec3_t sunDirection = { 0.441835, 0.56807, 0.694313 }; -//vec3_t sunDirection = { 0.45, 0, 0.9 }; -//vec3_t sunDirection = { 0, 0, 1 }; - -// these are usually overrided by shader values -vec3_t sunDirection = { 0.45, 0.3, 0.9 }; -vec3_t sunLight = { 100, 100, 50 }; - - - -typedef struct { - dbrush_t *b; - vec3_t bounds[2]; -} skyBrush_t; - -int numSkyBrushes; -skyBrush_t skyBrushes[MAX_MAP_BRUSHES]; - - -/* - -the corners of a patch mesh will always be exactly at lightmap samples. -The dimensions of the lightmap will be equal to the average length of the control -mesh in each dimension divided by 2. -The lightmap sample points should correspond to the chosen subdivision points. - -*/ - -/* -=============================================================== - -SURFACE LOADING - -=============================================================== -*/ - -#define MAX_FACE_POINTS 128 - -/* -=============== -SubdivideAreaLight - -Subdivide area lights that are very large -A light that is subdivided will never backsplash, avoiding weird pools of light near edges -=============== -*/ -void SubdivideAreaLight( shaderInfo_t *ls, winding_t *w, vec3_t normal, - float areaSubdivide, qboolean backsplash ) { - float area, value, intensity; - light_t *dl, *dl2; - vec3_t mins, maxs; - int axis; - winding_t *front, *back; - vec3_t planeNormal; - float planeDist; - - if ( !w ) { - return; - } - - WindingBounds( w, mins, maxs ); - - // check for subdivision - for ( axis = 0 ; axis < 3 ; axis++ ) { - if ( maxs[axis] - mins[axis] > areaSubdivide ) { - VectorClear( planeNormal ); - planeNormal[axis] = 1; - planeDist = ( maxs[axis] + mins[axis] ) * 0.5; - ClipWindingEpsilon ( w, planeNormal, planeDist, ON_EPSILON, &front, &back ); - SubdivideAreaLight( ls, front, normal, areaSubdivide, qfalse ); - SubdivideAreaLight( ls, back, normal, areaSubdivide, qfalse ); - FreeWinding( w ); - return; - } - } - - // create a light from this - area = WindingArea (w); - if ( area <= 0 || area > 20000000 ) { - return; - } - - numAreaLights++; - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - dl->next = lights; - lights = dl; - dl->type = emit_area; - - WindingCenter( w, dl->origin ); - dl->w = w; - VectorCopy ( normal, dl->normal); - dl->dist = DotProduct( dl->origin, normal ); - - value = ls->value; - intensity = value * area * areaScale; - VectorAdd( dl->origin, dl->normal, dl->origin ); - - VectorCopy( ls->color, dl->color ); - - dl->photons = intensity; - - // emitColor is irrespective of the area - VectorScale( ls->color, value*formFactorValueScale*areaScale, dl->emitColor ); - - dl->si = ls; - - if ( ls->contents & CONTENTS_FOG ) { - dl->twosided = qtrue; - } - - // optionally create a point backsplash light - if ( backsplash && ls->backsplashFraction > 0 ) { - dl2 = malloc(sizeof(*dl)); - memset (dl2, 0, sizeof(*dl2)); - dl2->next = lights; - lights = dl2; - dl2->type = emit_point; - - VectorMA( dl->origin, ls->backsplashDistance, normal, dl2->origin ); - - VectorCopy( ls->color, dl2->color ); - - dl2->photons = dl->photons * ls->backsplashFraction; - dl2->si = ls; - } -} - - -/* -=============== -CountLightmaps -=============== -*/ -void CountLightmaps( void ) { - int count; - int i; - dsurface_t *ds; - - qprintf ("--- CountLightmaps ---\n"); - count = 0; - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - // see if this surface is light emiting - ds = &drawSurfaces[i]; - if ( ds->lightmapNum > count ) { - count = ds->lightmapNum; - } - } - - count++; - numLightBytes = count * LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 3; - if ( numLightBytes > MAX_MAP_LIGHTING ) { - Error("MAX_MAP_LIGHTING exceeded"); - } - - qprintf( "%5i drawSurfaces\n", numDrawSurfaces ); - qprintf( "%5i lightmaps\n", count ); -} - -/* -=============== -CreateSurfaceLights - -This creates area lights -=============== -*/ -void CreateSurfaceLights( void ) { - int i, j, side; - dsurface_t *ds; - shaderInfo_t *ls; - winding_t *w; - cFacet_t *f; - light_t *dl; - vec3_t origin; - drawVert_t *dv; - int c_lightSurfaces; - float lightSubdivide; - vec3_t normal; - - qprintf ("--- CreateSurfaceLights ---\n"); - c_lightSurfaces = 0; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - // see if this surface is light emiting - ds = &drawSurfaces[i]; - - ls = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - if ( ls->value == 0 ) { - continue; - } - - // determine how much we need to chop up the surface - if ( ls->lightSubdivide ) { - lightSubdivide = ls->lightSubdivide; - } else { - lightSubdivide = defaultLightSubdivide; - } - - c_lightSurfaces++; - - // an autosprite shader will become - // a point light instead of an area light - if ( ls->autosprite ) { - // autosprite geometry should only have four vertexes - if ( surfaceTest[i] ) { - // curve or misc_model - f = surfaceTest[i]->facets; - if ( surfaceTest[i]->numFacets != 1 || f->numBoundaries != 4 ) { - _printf( "WARNING: surface at (%i %i %i) has autosprite shader but isn't a quad\n", - (int)f->points[0], (int)f->points[1], (int)f->points[2] ); - } - VectorAdd( f->points[0], f->points[1], origin ); - VectorAdd( f->points[2], origin, origin ); - VectorAdd( f->points[3], origin, origin ); - VectorScale( origin, 0.25, origin ); - } else { - // normal polygon - dv = &drawVerts[ ds->firstVert ]; - if ( ds->numVerts != 4 ) { - _printf( "WARNING: surface at (%i %i %i) has autosprite shader but %i verts\n", - (int)dv->xyz[0], (int)dv->xyz[1], (int)dv->xyz[2] ); - continue; - } - - VectorAdd( dv[0].xyz, dv[1].xyz, origin ); - VectorAdd( dv[2].xyz, origin, origin ); - VectorAdd( dv[3].xyz, origin, origin ); - VectorScale( origin, 0.25, origin ); - } - - - numPointLights++; - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - dl->next = lights; - lights = dl; - - VectorCopy( origin, dl->origin ); - VectorCopy( ls->color, dl->color ); - dl->photons = ls->value * pointScale; - dl->type = emit_point; - continue; - } - - // possibly create for both sides of the polygon - for ( side = 0 ; side <= ls->twoSided ; side++ ) { - // create area lights - if ( surfaceTest[i] ) { - // curve or misc_model - for ( j = 0 ; j < surfaceTest[i]->numFacets ; j++ ) { - f = surfaceTest[i]->facets + j; - w = AllocWinding( f->numBoundaries ); - w->numpoints = f->numBoundaries; - memcpy( w->p, f->points, f->numBoundaries * 12 ); - - VectorCopy( f->surface, normal ); - if ( side ) { - winding_t *t; - - t = w; - w = ReverseWinding( t ); - FreeWinding( t ); - VectorSubtract( vec3_origin, normal, normal ); - } - SubdivideAreaLight( ls, w, normal, lightSubdivide, qtrue ); - } - } else { - // normal polygon - - w = AllocWinding( ds->numVerts ); - w->numpoints = ds->numVerts; - for ( j = 0 ; j < ds->numVerts ; j++ ) { - VectorCopy( drawVerts[ds->firstVert+j].xyz, w->p[j] ); - } - VectorCopy( ds->lightmapVecs[2], normal ); - if ( side ) { - winding_t *t; - - t = w; - w = ReverseWinding( t ); - FreeWinding( t ); - VectorSubtract( vec3_origin, normal, normal ); - } - SubdivideAreaLight( ls, w, normal, lightSubdivide, qtrue ); - } - } - } - - _printf( "%5i light emitting surfaces\n", c_lightSurfaces ); -} - - - -/* -================ -FindSkyBrushes -================ -*/ -void FindSkyBrushes( void ) { - int i, j; - dbrush_t *b; - skyBrush_t *sb; - shaderInfo_t *si; - dbrushside_t *s; - - // find the brushes - for ( i = 0 ; i < numbrushes ; i++ ) { - b = &dbrushes[i]; - for ( j = 0 ; j < b->numSides ; j++ ) { - s = &dbrushsides[ b->firstSide + j ]; - if ( dshaders[ s->shaderNum ].surfaceFlags & SURF_SKY ) { - sb = &skyBrushes[ numSkyBrushes ]; - sb->b = b; - sb->bounds[0][0] = -dplanes[ dbrushsides[ b->firstSide + 0 ].planeNum ].dist - 1; - sb->bounds[1][0] = dplanes[ dbrushsides[ b->firstSide + 1 ].planeNum ].dist + 1; - sb->bounds[0][1] = -dplanes[ dbrushsides[ b->firstSide + 2 ].planeNum ].dist - 1; - sb->bounds[1][1] = dplanes[ dbrushsides[ b->firstSide + 3 ].planeNum ].dist + 1; - sb->bounds[0][2] = -dplanes[ dbrushsides[ b->firstSide + 4 ].planeNum ].dist - 1; - sb->bounds[1][2] = dplanes[ dbrushsides[ b->firstSide + 5 ].planeNum ].dist + 1; - numSkyBrushes++; - break; - } - } - } - - // default - VectorNormalize( sunDirection, sunDirection ); - - // find the sky shader - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - si = ShaderInfoForShader( dshaders[ drawSurfaces[i].shaderNum ].shader ); - if ( si->surfaceFlags & SURF_SKY ) { - VectorCopy( si->sunLight, sunLight ); - VectorCopy( si->sunDirection, sunDirection ); - break; - } - } -} - -/* -================================================================= - - LIGHT SETUP - -================================================================= -*/ - -/* -================== -FindTargetEntity -================== -*/ -entity_t *FindTargetEntity( const char *target ) { - int i; - const char *n; - - for ( i = 0 ; i < num_entities ; i++ ) { - n = ValueForKey (&entities[i], "targetname"); - if ( !strcmp (n, target) ) { - return &entities[i]; - } - } - - return NULL; -} - - - -/* -============= -CreateEntityLights -============= -*/ -void CreateEntityLights (void) -{ - int i; - light_t *dl; - entity_t *e, *e2; - const char *name; - const char *target; - vec3_t dest; - const char *_color; - float intensity; - int spawnflags; - - // - // entities - // - for ( i = 0 ; i < num_entities ; i++ ) { - e = &entities[i]; - name = ValueForKey (e, "classname"); - if (strncmp (name, "light", 5)) - continue; - - numPointLights++; - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - dl->next = lights; - lights = dl; - - spawnflags = FloatForKey (e, "spawnflags"); - if ( spawnflags & 1 ) { - dl->linearLight = qtrue; - } - - GetVectorForKey (e, "origin", dl->origin); - dl->style = FloatForKey (e, "_style"); - if (!dl->style) - dl->style = FloatForKey (e, "style"); - if (dl->style < 0) - dl->style = 0; - - intensity = FloatForKey (e, "light"); - if (!intensity) - intensity = FloatForKey (e, "_light"); - if (!intensity) - intensity = 300; - _color = ValueForKey (e, "_color"); - if (_color && _color[0]) - { - sscanf (_color, "%f %f %f", &dl->color[0],&dl->color[1],&dl->color[2]); - ColorNormalize (dl->color, dl->color); - } - else - dl->color[0] = dl->color[1] = dl->color[2] = 1.0; - - intensity = intensity * pointScale; - dl->photons = intensity; - - dl->type = emit_point; - - // lights with a target will be spotlights - target = ValueForKey (e, "target"); - - if ( target[0] ) { - float radius; - float dist; - - e2 = FindTargetEntity (target); - if (!e2) { - _printf ("WARNING: light at (%i %i %i) has missing target\n", - (int)dl->origin[0], (int)dl->origin[1], (int)dl->origin[2]); - } else { - GetVectorForKey (e2, "origin", dest); - VectorSubtract (dest, dl->origin, dl->normal); - dist = VectorNormalize (dl->normal, dl->normal); - radius = FloatForKey (e, "radius"); - if ( !radius ) { - radius = 64; - } - if ( !dist ) { - dist = 64; - } - dl->radiusByDist = (radius + 16) / dist; - dl->type = emit_spotlight; - } - } - } -} - -//================================================================= - -/* -================ -SetEntityOrigins - -Find the offset values for inline models -================ -*/ -void SetEntityOrigins( void ) { - int i, j; - entity_t *e; - vec3_t origin; - const char *key; - int modelnum; - dmodel_t *dm; - - for ( i=0 ; i < num_entities ; i++ ) { - e = &entities[i]; - key = ValueForKey (e, "model"); - if ( key[0] != '*' ) { - continue; - } - modelnum = atoi( key + 1 ); - dm = &dmodels[ modelnum ]; - - // set entity surface to true for all surfaces for this model - for ( j = 0 ; j < dm->numSurfaces ; j++ ) { - entitySurface[ dm->firstSurface + j ] = qtrue; - } - - key = ValueForKey (e, "origin"); - if ( !key[0] ) { - continue; - } - GetVectorForKey ( e, "origin", origin ); - - // set origin for all surfaces for this model - for ( j = 0 ; j < dm->numSurfaces ; j++ ) { - VectorCopy( origin, surfaceOrigin[ dm->firstSurface + j ] ); - } - } -} - - -/* -================================================================= - - -================================================================= -*/ - -#define MAX_POINTS_ON_WINDINGS 64 - -/* -================ -PointToPolygonFormFactor -================ -*/ -float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const winding_t *w ) { - vec3_t triVector, triNormal; - int i, j; - vec3_t dirs[MAX_POINTS_ON_WINDING]; - float total; - float dot, angle, facing; - - for ( i = 0 ; i < w->numpoints ; i++ ) { - VectorSubtract( w->p[i], point, dirs[i] ); - VectorNormalize( dirs[i], dirs[i] ); - } - - // duplicate first vertex to avoid mod operation - VectorCopy( dirs[0], dirs[i] ); - - total = 0; - for ( i = 0 ; i < w->numpoints ; i++ ) { - j = i+1; - dot = DotProduct( dirs[i], dirs[j] ); - - // roundoff can cause slight creep, which gives an IND from acos - if ( dot > 1.0 ) { - dot = 1.0; - } else if ( dot < -1.0 ) { - dot = -1.0; - } - - angle = acos( dot ); - CrossProduct( dirs[i], dirs[j], triVector ); - if ( VectorNormalize( triVector, triNormal ) < 0.0001 ) { - continue; - } - facing = DotProduct( normal, triNormal ); - total += facing * angle; - - if ( total > 6.3 || total < -6.3 ) { - static qboolean printed; - - if ( !printed ) { - printed = qtrue; - _printf( "WARNING: bad PointToPolygonFormFactor: %f at %1.1f %1.1f %1.1f from %1.1f %1.1f %1.1f\n", total, - w->p[i][0], w->p[i][1], w->p[i][2], point[0], point[1], point[2]); - } - return 0; - } - - } - - total /= 2*3.141592657; // now in the range of 0 to 1 over the entire incoming hemisphere - - return total; -} - - -/* -================ -FilterTrace - -Returns 0 to 1.0 filter fractions for the given trace -================ -*/ -void FilterTrace( const vec3_t start, const vec3_t end, vec3_t filter ) { - float d1, d2; - filter_t *f; - int filterNum; - vec3_t point; - float frac; - int i; - float s, t; - int u, v; - int x, y; - byte *pixel; - float radius; - float len; - vec3_t total; - - filter[0] = 1.0; - filter[1] = 1.0; - filter[2] = 1.0; - - for ( filterNum = 0 ; filterNum < numFilters ; filterNum++ ) { - f = &filters[ filterNum ]; - - // see if the plane is crossed - d1 = DotProduct( start, f->plane ) - f->plane[3]; - d2 = DotProduct( end, f->plane ) - f->plane[3]; - - if ( ( d1 < 0 ) == ( d2 < 0 ) ) { - continue; - } - - // calculate the crossing point - frac = d1 / ( d1 - d2 ); - - for ( i = 0 ; i < 3 ; i++ ) { - point[i] = start[i] + frac * ( end[i] - start[i] ); - } - - VectorSubtract( point, f->origin, point ); - - s = DotProduct( point, f->vectors[0] ); - t = 1.0 - DotProduct( point, f->vectors[1] ); - if ( s < 0 || s >= 1.0 || t < 0 || t >= 1.0 ) { - continue; - } - - // decide the filter size - radius = 10 * frac; - len = VectorLength( f->vectors[0] ); - if ( !len ) { - continue; - } - radius = radius * len * f->si->width; - - // look up the filter, taking multiple samples - VectorClear( total ); - for ( u = -1 ; u <= 1 ; u++ ) { - for ( v = -1 ; v <=1 ; v++ ) { - x = s * f->si->width + u * radius; - if ( x < 0 ) { - x = 0; - } - if ( x >= f->si->width ) { - x = f->si->width - 1; - } - y = t * f->si->height + v * radius; - if ( y < 0 ) { - y = 0; - } - if ( y >= f->si->height ) { - y = f->si->height - 1; - } - - pixel = f->si->pixels + ( y * f->si->width + x ) * 4; - total[0] += pixel[0]; - total[1] += pixel[1]; - total[2] += pixel[2]; - } - } - - filter[0] *= total[0]/(255.0*9); - filter[1] *= total[1]/(255.0*9); - filter[2] *= total[2]/(255.0*9); - } - -} - -/* -================ -SunToPoint - -Returns an amount of light to add at the point -================ -*/ -int c_sunHit, c_sunMiss; -void SunToPoint( const vec3_t origin, traceWork_t *tw, vec3_t addLight ) { - int i; - trace_t trace; - skyBrush_t *b; - vec3_t end; - - if ( !numSkyBrushes ) { - VectorClear( addLight ); - return; - } - - VectorMA( origin, MAX_WORLD_COORD * 2, sunDirection, end ); - - TraceLine( origin, end, &trace, qtrue, tw ); - - // see if trace.hit is inside a sky brush - for ( i = 0 ; i < numSkyBrushes ; i++) { - b = &skyBrushes[ i ]; - - // this assumes that sky brushes are axial... - if ( trace.hit[0] < b->bounds[0][0] - || trace.hit[0] > b->bounds[1][0] - || trace.hit[1] < b->bounds[0][1] - || trace.hit[1] > b->bounds[1][1] - || trace.hit[2] < b->bounds[0][2] - || trace.hit[2] > b->bounds[1][2] ) { - continue; - } - - - // trace again to get intermediate filters - TraceLine( origin, trace.hit, &trace, qtrue, tw ); - - // we hit the sky, so add sunlight - if ( numthreads == 1 ) { - c_sunHit++; - } - addLight[0] = trace.filter[0] * sunLight[0]; - addLight[1] = trace.filter[1] * sunLight[1]; - addLight[2] = trace.filter[2] * sunLight[2]; - - return; - } - - if ( numthreads == 1 ) { - c_sunMiss++; - } - - VectorClear( addLight ); -} - -/* -================ -SunToPlane -================ -*/ -void SunToPlane( const vec3_t origin, const vec3_t normal, vec3_t color, traceWork_t *tw ) { - float angle; - vec3_t sunColor; - - if ( !numSkyBrushes ) { - return; - } - - angle = DotProduct( normal, sunDirection ); - if ( angle <= 0 ) { - return; // facing away - } - - SunToPoint( origin, tw, sunColor ); - VectorMA( color, angle, sunColor, color ); -} - -/* -================ -LightingAtSample -================ -*/ -void LightingAtSample( vec3_t origin, vec3_t normal, vec3_t color, - qboolean testOcclusion, qboolean forceSunLight, traceWork_t *tw ) { - light_t *light; - trace_t trace; - float angle; - float add; - float dist; - vec3_t dir; - - VectorCopy( ambientColor, color ); - - // trace to all the lights - for ( light = lights ; light ; light = light->next ) { - - //MrE: if the light is behind the surface - if ( DotProduct(light->origin, normal) - DotProduct(normal, origin) < 0 ) - continue; - // testing exact PTPFF - if ( exactPointToPolygon && light->type == emit_area ) { - float factor; - float d; - vec3_t pushedOrigin; - - // see if the point is behind the light - d = DotProduct( origin, light->normal ) - light->dist; - if ( !light->twosided ) { - if ( d < -1 ) { - continue; // point is behind light - } - } - - // test occlusion and find light filters - // clip the line, tracing from the surface towards the light - if ( !notrace && testOcclusion ) { - TraceLine( origin, light->origin, &trace, qfalse, tw ); - - // other light rays must not hit anything - if ( trace.passSolid ) { - continue; - } - } else { - trace.filter[0] = 1.0; - trace.filter[1] = 1.0; - trace.filter[2] = 1.0; - } - - // nudge the point so that it is clearly forward of the light - // so that surfaces meeting a light emiter don't get black edges - if ( d > -8 && d < 8 ) { - VectorMA( origin, (8-d), light->normal, pushedOrigin ); - } else { - VectorCopy( origin, pushedOrigin ); - } - - // calculate the contribution - factor = PointToPolygonFormFactor( pushedOrigin, normal, light->w ); - if ( factor <= 0 ) { - if ( light->twosided ) { - factor = -factor; - } else { - continue; - } - } - color[0] += factor * light->emitColor[0] * trace.filter[0]; - color[1] += factor * light->emitColor[1] * trace.filter[1]; - color[2] += factor * light->emitColor[2] * trace.filter[2]; - - continue; - } - - // calculate the amount of light at this sample - if ( light->type == emit_point ) { - VectorSubtract( light->origin, origin, dir ); - dist = VectorNormalize( dir, dir ); - // clamp the distance to prevent super hot spots - if ( dist < 16 ) { - dist = 16; - } - angle = DotProduct( normal, dir ); - if ( light->linearLight ) { - add = angle * light->photons * linearScale - dist; - if ( add < 0 ) { - add = 0; - } - } else { - add = light->photons / ( dist * dist ) * angle; - } - } else if ( light->type == emit_spotlight ) { - float distByNormal; - vec3_t pointAtDist; - float radiusAtDist; - float sampleRadius; - vec3_t distToSample; - float coneScale; - - VectorSubtract( light->origin, origin, dir ); - - distByNormal = -DotProduct( dir, light->normal ); - if ( distByNormal < 0 ) { - continue; - } - VectorMA( light->origin, distByNormal, light->normal, pointAtDist ); - radiusAtDist = light->radiusByDist * distByNormal; - - VectorSubtract( origin, pointAtDist, distToSample ); - sampleRadius = VectorLength( distToSample ); - - if ( sampleRadius >= radiusAtDist ) { - continue; // outside the cone - } - if ( sampleRadius <= radiusAtDist - 32 ) { - coneScale = 1.0; // fully inside - } else { - coneScale = ( radiusAtDist - sampleRadius ) / 32.0; - } - - dist = VectorNormalize( dir, dir ); - // clamp the distance to prevent super hot spots - if ( dist < 16 ) { - dist = 16; - } - angle = DotProduct( normal, dir ); - add = light->photons / ( dist * dist ) * angle * coneScale; - - } else if ( light->type == emit_area ) { - VectorSubtract( light->origin, origin, dir ); - dist = VectorNormalize( dir, dir ); - // clamp the distance to prevent super hot spots - if ( dist < 16 ) { - dist = 16; - } - angle = DotProduct( normal, dir ); - if ( angle <= 0 ) { - continue; - } - angle *= -DotProduct( light->normal, dir ); - if ( angle <= 0 ) { - continue; - } - - if ( light->linearLight ) { - add = angle * light->photons * linearScale - dist; - if ( add < 0 ) { - add = 0; - } - } else { - add = light->photons / ( dist * dist ) * angle; - } - } - - if ( add <= 1.0 ) { - continue; - } - - // clip the line, tracing from the surface towards the light - if ( !notrace && testOcclusion ) { - TraceLine( origin, light->origin, &trace, qfalse, tw ); - - // other light rays must not hit anything - if ( trace.passSolid ) { - continue; - } - } else { - trace.filter[0] = 1; - trace.filter[1] = 1; - trace.filter[2] = 1; - } - - // add the result - color[0] += add * light->color[0] * trace.filter[0]; - color[1] += add * light->color[1] * trace.filter[1]; - color[2] += add * light->color[2] * trace.filter[2]; - } - - // - // trace directly to the sun - // - if ( testOcclusion || forceSunLight ) { - SunToPlane( origin, normal, color, tw ); - } -} - -/* -============= -PrintOccluded - -For debugging -============= -*/ -void PrintOccluded( byte occluded[LIGHTMAP_WIDTH*EXTRASCALE][LIGHTMAP_HEIGHT*EXTRASCALE], - int width, int height ) { - int i, j; - - _printf( "\n" ); - - for ( i = 0 ; i < height ; i++ ) { - for ( j = 0 ; j < width ; j++ ) { - _printf("%i", (int)occluded[j][i] ); - } - _printf( "\n" ); - } -} - - -/* -============= -VertexLighting - -Vertex lighting will completely ignore occlusion, because -shadows would not be resolvable anyway. -============= -*/ -void VertexLighting( dsurface_t *ds, qboolean testOcclusion, qboolean forceSunLight, float scale, traceWork_t *tw ) { - int i, j; - drawVert_t *dv; - vec3_t sample, normal; - float max; - - VectorCopy( ds->lightmapVecs[2], normal ); - - // generate vertex lighting - for ( i = 0 ; i < ds->numVerts ; i++ ) { - dv = &drawVerts[ ds->firstVert + i ]; - - if ( ds->patchWidth ) { - LightingAtSample( dv->xyz, dv->normal, sample, testOcclusion, forceSunLight, tw ); - } - else if (ds->surfaceType == MST_TRIANGLE_SOUP) { - LightingAtSample( dv->xyz, dv->normal, sample, testOcclusion, forceSunLight, tw ); - } - else { - LightingAtSample( dv->xyz, normal, sample, testOcclusion, forceSunLight, tw ); - } - - if (scale >= 0) - VectorScale(sample, scale, sample); - // clamp with color normalization - max = sample[0]; - if ( sample[1] > max ) { - max = sample[1]; - } - if ( sample[2] > max ) { - max = sample[2]; - } - if ( max > 255 ) { - VectorScale( sample, 255/max, sample ); - } - - // save the sample - for ( j = 0 ; j < 3 ; j++ ) { - if ( sample[j] > 255 ) { - sample[j] = 255; - } - dv->color[j] = sample[j]; - } - - // Don't bother writing alpha since it will already be set to 255, - // plus we don't want to write over alpha generated by SetTerrainTextures - //dv->color[3] = 255; - } -} - - -/* -================= -LinearSubdivideMesh - -For extra lighting, just midpoint one of the axis. -The edges are clamped at the original edges. -================= -*/ -mesh_t *LinearSubdivideMesh( mesh_t *in ) { - int i, j; - mesh_t *out; - drawVert_t *v1, *v2, *vout; - - out = malloc( sizeof( *out ) ); - - out->width = in->width * 2; - out->height = in->height; - out->verts = malloc( out->width * out->height * sizeof(*out->verts) ); - for ( j = 0 ; j < in->height ; j++ ) { - out->verts[ j * out->width + 0 ] = in->verts[ j * in->width + 0 ]; - out->verts[ j * out->width + out->width - 1 ] = in->verts[ j * in->width + in->width - 1 ]; - for ( i = 1 ; i < out->width - 1 ; i+= 2 ) { - v1 = in->verts + j * in->width + (i >> 1); - v2 = v1 + 1; - vout = out->verts + j * out->width + i; - - vout->xyz[0] = 0.75 * v1->xyz[0] + 0.25 * v2->xyz[0]; - vout->xyz[1] = 0.75 * v1->xyz[1] + 0.25 * v2->xyz[1]; - vout->xyz[2] = 0.75 * v1->xyz[2] + 0.25 * v2->xyz[2]; - - vout->normal[0] = 0.75 * v1->normal[0] + 0.25 * v2->normal[0]; - vout->normal[1] = 0.75 * v1->normal[1] + 0.25 * v2->normal[1]; - vout->normal[2] = 0.75 * v1->normal[2] + 0.25 * v2->normal[2]; - - VectorNormalize( vout->normal, vout->normal ); - - vout++; - - vout->xyz[0] = 0.25 * v1->xyz[0] + 0.75 * v2->xyz[0]; - vout->xyz[1] = 0.25 * v1->xyz[1] + 0.75 * v2->xyz[1]; - vout->xyz[2] = 0.25 * v1->xyz[2] + 0.75 * v2->xyz[2]; - - vout->normal[0] = 0.25 * v1->normal[0] + 0.75 * v2->normal[0]; - vout->normal[1] = 0.25 * v1->normal[1] + 0.75 * v2->normal[1]; - vout->normal[2] = 0.25 * v1->normal[2] + 0.75 * v2->normal[2]; - - VectorNormalize( vout->normal, vout->normal ); - - } - } - - FreeMesh( in ); - - return out; -} - -/* -============== -ColorToBytes -============== -*/ -void ColorToBytes( const float *color, byte *colorBytes ) { - float max; - vec3_t sample; - - VectorCopy( color, sample ); - - // clamp with color normalization - max = sample[0]; - if ( sample[1] > max ) { - max = sample[1]; - } - if ( sample[2] > max ) { - max = sample[2]; - } - if ( max > 255 ) { - VectorScale( sample, 255/max, sample ); - } - colorBytes[ 0 ] = sample[0]; - colorBytes[ 1 ] = sample[1]; - colorBytes[ 2 ] = sample[2]; -} - - - -/* -============= -TraceLtm -============= -*/ -void TraceLtm( int num ) { - dsurface_t *ds; - int i, j, k; - int x, y; - int position, numPositions; - vec3_t base, origin, normal; - byte occluded[LIGHTMAP_WIDTH*EXTRASCALE][LIGHTMAP_HEIGHT*EXTRASCALE]; - vec3_t color[LIGHTMAP_WIDTH*EXTRASCALE][LIGHTMAP_HEIGHT*EXTRASCALE]; - traceWork_t tw; - vec3_t average; - int count; - mesh_t srcMesh, *mesh, *subdivided; - shaderInfo_t *si; - static float nudge[2][9] = { - { 0, -1, 0, 1, -1, 1, -1, 0, 1 }, - { 0, -1, -1, -1, 0, 0, 1, 1, 1 } - }; - int sampleWidth, sampleHeight, ssize; - vec3_t lightmapOrigin, lightmapVecs[2]; - int widthtable[LIGHTMAP_WIDTH], heighttable[LIGHTMAP_WIDTH]; - - ds = &drawSurfaces[num]; - si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - - // vertex-lit triangle model - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) { - VertexLighting( ds, !si->noVertexShadows, si->forceSunLight, 1.0, &tw ); - return; - } - - if ( ds->lightmapNum == -1 ) { - return; // doesn't need lighting at all - } - - if (!novertexlighting) { - // calculate the vertex lighting for gouraud shade mode - VertexLighting( ds, si->vertexShadows, si->forceSunLight, si->vertexScale, &tw ); - } - - if ( ds->lightmapNum < 0 ) { - return; // doesn't need lightmap lighting - } - - si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - ssize = samplesize; - if (si->lightmapSampleSize) - ssize = si->lightmapSampleSize; - - if (si->patchShadows) - tw.patchshadows = qtrue; - else - tw.patchshadows = patchshadows; - - if ( ds->surfaceType == MST_PATCH ) { - srcMesh.width = ds->patchWidth; - srcMesh.height = ds->patchHeight; - srcMesh.verts = drawVerts + ds->firstVert; - mesh = SubdivideMesh( srcMesh, 8, 999 ); - PutMeshOnCurve( *mesh ); - MakeMeshNormals( *mesh ); - - subdivided = RemoveLinearMeshColumnsRows( mesh ); - FreeMesh(mesh); - - mesh = SubdivideMeshQuads( subdivided, ssize, LIGHTMAP_WIDTH, widthtable, heighttable); - if ( mesh->width != ds->lightmapWidth || mesh->height != ds->lightmapHeight ) { - Error( "Mesh lightmap miscount"); - } - - if ( extra ) { - mesh_t *mp; - - // chop it up for more light samples (leaking memory...) - mp = mesh;//CopyMesh( mesh ); - mp = LinearSubdivideMesh( mp ); - mp = TransposeMesh( mp ); - mp = LinearSubdivideMesh( mp ); - mp = TransposeMesh( mp ); - - mesh = mp; - } - } else { - VectorCopy( ds->lightmapVecs[2], normal ); - - if ( !extra ) { - VectorCopy( ds->lightmapOrigin, lightmapOrigin ); - VectorCopy( ds->lightmapVecs[0], lightmapVecs[0] ); - VectorCopy( ds->lightmapVecs[1], lightmapVecs[1] ); - } else { - // sample at a closer spacing for antialiasing - VectorCopy( ds->lightmapOrigin, lightmapOrigin ); - VectorScale( ds->lightmapVecs[0], 0.5, lightmapVecs[0] ); - VectorScale( ds->lightmapVecs[1], 0.5, lightmapVecs[1] ); - VectorMA( lightmapOrigin, -0.5, lightmapVecs[0], lightmapOrigin ); - VectorMA( lightmapOrigin, -0.5, lightmapVecs[1], lightmapOrigin ); - } - } - - if ( extra ) { - sampleWidth = ds->lightmapWidth * 2; - sampleHeight = ds->lightmapHeight * 2; - } else { - sampleWidth = ds->lightmapWidth; - sampleHeight = ds->lightmapHeight; - } - - memset ( color, 0, sizeof( color ) ); - - // determine which samples are occluded - memset ( occluded, 0, sizeof( occluded ) ); - for ( i = 0 ; i < sampleWidth ; i++ ) { - for ( j = 0 ; j < sampleHeight ; j++ ) { - - if ( ds->patchWidth ) { - numPositions = 9; - VectorCopy( mesh->verts[j*mesh->width+i].normal, normal ); - // VectorNormalize( normal, normal ); - // push off of the curve a bit - VectorMA( mesh->verts[j*mesh->width+i].xyz, 1, normal, base ); - - MakeNormalVectors( normal, lightmapVecs[0], lightmapVecs[1] ); - } else { - numPositions = 9; - for ( k = 0 ; k < 3 ; k++ ) { - base[k] = lightmapOrigin[k] + normal[k] - + i * lightmapVecs[0][k] - + j * lightmapVecs[1][k]; - } - } - VectorAdd( base, surfaceOrigin[ num ], base ); - - // we may need to slightly nudge the sample point - // if directly on a wall - for ( position = 0 ; position < numPositions ; position++ ) { - // calculate lightmap sample position - for ( k = 0 ; k < 3 ; k++ ) { - origin[k] = base[k] + - + ( nudge[0][position]/16 ) * lightmapVecs[0][k] - + ( nudge[1][position]/16 ) * lightmapVecs[1][k]; - } - - if ( notrace ) { - break; - } - if ( !PointInSolid( origin ) ) { - break; - } - } - - // if none of the nudges worked, this sample is occluded - if ( position == numPositions ) { - occluded[i][j] = qtrue; - if ( numthreads == 1 ) { - c_occluded++; - } - continue; - } - - if ( numthreads == 1 ) { - c_visible++; - } - occluded[i][j] = qfalse; - LightingAtSample( origin, normal, color[i][j], qtrue, qfalse, &tw ); - } - } - - if ( dump ) { - PrintOccluded( occluded, sampleWidth, sampleHeight ); - } - - // calculate average values for occluded samples - for ( i = 0 ; i < sampleWidth ; i++ ) { - for ( j = 0 ; j < sampleHeight ; j++ ) { - if ( !occluded[i][j] ) { - continue; - } - // scan all surrounding samples - count = 0; - VectorClear( average ); - for ( x = -1 ; x <= 1; x++ ) { - for ( y = -1 ; y <= 1 ; y++ ) { - if ( i + x < 0 || i + x >= sampleWidth ) { - continue; - } - if ( j + y < 0 || j + y >= sampleHeight ) { - continue; - } - if ( occluded[i+x][j+y] ) { - continue; - } - count++; - VectorAdd( color[i+x][j+y], average, average ); - } - } - if ( count ) { - VectorScale( average, 1.0/count, color[i][j] ); - } - } - } - - // average together the values if we are extra sampling - if ( ds->lightmapWidth != sampleWidth ) { - for ( i = 0 ; i < ds->lightmapWidth ; i++ ) { - for ( j = 0 ; j < ds->lightmapHeight ; j++ ) { - for ( k = 0 ; k < 3 ; k++ ) { - float value, coverage; - - value = color[i*2][j*2][k] + color[i*2][j*2+1][k] + - color[i*2+1][j*2][k] + color[i*2+1][j*2+1][k]; - coverage = 4; - if ( extraWide ) { - // wider than box filter - if ( i > 0 ) { - value += color[i*2-1][j*2][k] + color[i*2-1][j*2+1][k]; - value += color[i*2-2][j*2][k] + color[i*2-2][j*2+1][k]; - coverage += 4; - } - if ( i < ds->lightmapWidth - 1 ) { - value += color[i*2+2][j*2][k] + color[i*2+2][j*2+1][k]; - value += color[i*2+3][j*2][k] + color[i*2+3][j*2+1][k]; - coverage += 4; - } - if ( j > 0 ) { - value += color[i*2][j*2-1][k] + color[i*2+1][j*2-1][k]; - value += color[i*2][j*2-2][k] + color[i*2+1][j*2-2][k]; - coverage += 4; - } - if ( j < ds->lightmapHeight - 1 ) { - value += color[i*2][j*2+2][k] + color[i*2+1][j*2+2][k]; - value += color[i*2][j*2+3][k] + color[i*2+1][j*2+3][k]; - coverage += 2; - } - } - - color[i][j][k] = value / coverage; - } - } - } - } - - // optionally create a debugging border around the lightmap - if ( lightmapBorder ) { - for ( i = 0 ; i < ds->lightmapWidth ; i++ ) { - color[i][0][0] = 255; - color[i][0][1] = 0; - color[i][0][2] = 0; - - color[i][ds->lightmapHeight-1][0] = 255; - color[i][ds->lightmapHeight-1][1] = 0; - color[i][ds->lightmapHeight-1][2] = 0; - } - for ( i = 0 ; i < ds->lightmapHeight ; i++ ) { - color[0][i][0] = 255; - color[0][i][1] = 0; - color[0][i][2] = 0; - - color[ds->lightmapWidth-1][i][0] = 255; - color[ds->lightmapWidth-1][i][1] = 0; - color[ds->lightmapWidth-1][i][2] = 0; - } - } - - // clamp the colors to bytes and store off - for ( i = 0 ; i < ds->lightmapWidth ; i++ ) { - for ( j = 0 ; j < ds->lightmapHeight ; j++ ) { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + j) - * LIGHTMAP_WIDTH + ds->lightmapX + i; - - ColorToBytes( color[i][j], lightBytes + k*3 ); - } - } - - if (ds->surfaceType == MST_PATCH) - { - FreeMesh(mesh); - } -} - - -//============================================================================= - -vec3_t gridMins; -vec3_t gridSize = { 64, 64, 128 }; -int gridBounds[3]; - - -/* -======================== -LightContributionToPoint -======================== -*/ -qboolean LightContributionToPoint( const light_t *light, const vec3_t origin, - vec3_t color, traceWork_t *tw ) { - trace_t trace; - float add; - - add = 0; - - VectorClear( color ); - - // testing exact PTPFF - if ( exactPointToPolygon && light->type == emit_area ) { - float factor; - float d; - vec3_t normal; - - // see if the point is behind the light - d = DotProduct( origin, light->normal ) - light->dist; - if ( !light->twosided ) { - if ( d < 1 ) { - return qfalse; // point is behind light - } - } - - // test occlusion - // clip the line, tracing from the surface towards the light - TraceLine( origin, light->origin, &trace, qfalse, tw ); - if ( trace.passSolid ) { - return qfalse; - } - - // calculate the contribution - VectorSubtract( light->origin, origin, normal ); - if ( VectorNormalize( normal, normal ) == 0 ) { - return qfalse; - } - factor = PointToPolygonFormFactor( origin, normal, light->w ); - if ( factor <= 0 ) { - if ( light->twosided ) { - factor = -factor; - } else { - return qfalse; - } - } - VectorScale( light->emitColor, factor, color ); - return qtrue; - } - - // calculate the amount of light at this sample - if ( light->type == emit_point || light->type == emit_spotlight ) { - vec3_t dir; - float dist; - - VectorSubtract( light->origin, origin, dir ); - dist = VectorLength( dir ); - // clamp the distance to prevent super hot spots - if ( dist < 16 ) { - dist = 16; - } - if ( light->linearLight ) { - add = light->photons * linearScale - dist; - if ( add < 0 ) { - add = 0; - } - } else { - add = light->photons / ( dist * dist ); - } - } else { - return qfalse; - } - - if ( add <= 1.0 ) { - return qfalse; - } - - // clip the line, tracing from the surface towards the light - TraceLine( origin, light->origin, &trace, qfalse, tw ); - - // other light rays must not hit anything - if ( trace.passSolid ) { - return qfalse; - } - - // add the result - color[0] = add * light->color[0]; - color[1] = add * light->color[1]; - color[2] = add * light->color[2]; - - return qtrue; -} - -typedef struct { - vec3_t dir; - vec3_t color; -} contribution_t; - -/* -============= -TraceGrid - -Grid samples are foe quickly determining the lighting -of dynamically placed entities in the world -============= -*/ -#define MAX_CONTRIBUTIONS 1024 -void TraceGrid( int num ) { - int x, y, z; - vec3_t origin; - light_t *light; - vec3_t color; - int mod; - vec3_t directedColor; - vec3_t summedDir; - contribution_t contributions[MAX_CONTRIBUTIONS]; - int numCon; - int i; - traceWork_t tw; - float addSize; - - mod = num; - z = mod / ( gridBounds[0] * gridBounds[1] ); - mod -= z * ( gridBounds[0] * gridBounds[1] ); - - y = mod / gridBounds[0]; - mod -= y * gridBounds[0]; - - x = mod; - - origin[0] = gridMins[0] + x * gridSize[0]; - origin[1] = gridMins[1] + y * gridSize[1]; - origin[2] = gridMins[2] + z * gridSize[2]; - - if ( PointInSolid( origin ) ) { - vec3_t baseOrigin; - int step; - - VectorCopy( origin, baseOrigin ); - - // try to nudge the origin around to find a valid point - for ( step = 9 ; step <= 18 ; step += 9 ) { - for ( i = 0 ; i < 8 ; i++ ) { - VectorCopy( baseOrigin, origin ); - if ( i & 1 ) { - origin[0] += step; - } else { - origin[0] -= step; - } - if ( i & 2 ) { - origin[1] += step; - } else { - origin[1] -= step; - } - if ( i & 4 ) { - origin[2] += step; - } else { - origin[2] -= step; - } - - if ( !PointInSolid( origin ) ) { - break; - } - } - if ( i != 8 ) { - break; - } - } - if ( step > 18 ) { - // can't find a valid point at all - for ( i = 0 ; i < 8 ; i++ ) { - gridData[ num*8 + i ] = 0; - } - return; - } - } - - VectorClear( summedDir ); - - // trace to all the lights - - // find the major light direction, and divide the - // total light between that along the direction and - // the remaining in the ambient - numCon = 0; - for ( light = lights ; light ; light = light->next ) { - vec3_t add; - vec3_t dir; - float addSize; - - if ( !LightContributionToPoint( light, origin, add, &tw ) ) { - continue; - } - - VectorSubtract( light->origin, origin, dir ); - VectorNormalize( dir, dir ); - - VectorCopy( add, contributions[numCon].color ); - VectorCopy( dir, contributions[numCon].dir ); - numCon++; - - addSize = VectorLength( add ); - VectorMA( summedDir, addSize, dir, summedDir ); - - if ( numCon == MAX_CONTRIBUTIONS-1 ) { - break; - } - } - - // - // trace directly to the sun - // - SunToPoint( origin, &tw, color ); - addSize = VectorLength( color ); - if ( addSize > 0 ) { - VectorCopy( color, contributions[numCon].color ); - VectorCopy( sunDirection, contributions[numCon].dir ); - VectorMA( summedDir, addSize, sunDirection, summedDir ); - numCon++; - } - - - // now that we have identified the primary light direction, - // go back and seperate all the light into directed and ambient - VectorNormalize( summedDir, summedDir ); - VectorCopy( ambientColor, color ); - VectorClear( directedColor ); - - for ( i = 0 ; i < numCon ; i++ ) { - float d; - - d = DotProduct( contributions[i].dir, summedDir ); - if ( d < 0 ) { - d = 0; - } - - VectorMA( directedColor, d, contributions[i].color, directedColor ); - - // the ambient light will be at 1/4 the value of directed light - d = 0.25 * ( 1.0 - d ); - VectorMA( color, d, contributions[i].color, color ); - } - - // now do some fudging to keep the ambient from being too low - VectorMA( color, 0.25, directedColor, color ); - - // - // save the resulting value out - // - ColorToBytes( color, gridData + num*8 ); - ColorToBytes( directedColor, gridData + num*8 + 3 ); - - VectorNormalize( summedDir, summedDir ); - NormalToLatLong( summedDir, gridData + num*8 + 6); -} - - -/* -============= -SetupGrid -============= -*/ -void SetupGrid( void ) { - int i; - vec3_t maxs; - - for ( i = 0 ; i < 3 ; i++ ) { - gridMins[i] = gridSize[i] * ceil( dmodels[0].mins[i] / gridSize[i] ); - maxs[i] = gridSize[i] * floor( dmodels[0].maxs[i] / gridSize[i] ); - gridBounds[i] = (maxs[i] - gridMins[i])/gridSize[i] + 1; - } - - numGridPoints = gridBounds[0] * gridBounds[1] * gridBounds[2]; - if (numGridPoints * 8 >= MAX_MAP_LIGHTGRID) - Error("MAX_MAP_LIGHTGRID"); - qprintf( "%5i gridPoints\n", numGridPoints ); -} - -//============================================================================= - -/* -============= -RemoveLightsInSolid -============= -*/ -void RemoveLightsInSolid(void) -{ - light_t *light, *prev; - int numsolid = 0; - - prev = NULL; - for ( light = lights ; light ; ) { - if (PointInSolid(light->origin)) - { - if (prev) prev->next = light->next; - else lights = light->next; - if (light->w) - FreeWinding(light->w); - free(light); - numsolid++; - if (prev) - light = prev->next; - else - light = lights; - } - else - { - prev = light; - light = light->next; - } - } - _printf (" %7i lights in solid\n", numsolid); -} - -/* -============= -LightWorld -============= -*/ -void LightWorld (void) { - float f; - - // determine the number of grid points - SetupGrid(); - - // find the optional world ambient - GetVectorForKey( &entities[0], "_color", ambientColor ); - f = FloatForKey( &entities[0], "ambient" ); - VectorScale( ambientColor, f, ambientColor ); - - // create lights out of patches and lights - qprintf ("--- CreateLights ---\n"); - CreateEntityLights (); - qprintf ("%i point lights\n", numPointLights); - qprintf ("%i area lights\n", numAreaLights); - - if (!nogridlighting) { - qprintf ("--- TraceGrid ---\n"); - RunThreadsOnIndividual( numGridPoints, qtrue, TraceGrid ); - qprintf( "%i x %i x %i = %i grid\n", gridBounds[0], gridBounds[1], - gridBounds[2], numGridPoints); - } - - qprintf ("--- TraceLtm ---\n"); - RunThreadsOnIndividual( numDrawSurfaces, qtrue, TraceLtm ); - qprintf( "%5i visible samples\n", c_visible ); - qprintf( "%5i occluded samples\n", c_occluded ); -} - -/* -======== -CreateFilters - -EXPERIMENTAL, UNUSED - -Look for transparent light filter surfaces. - -This will only work for flat 3*3 patches that exactly hold one copy of the texture. -======== -*/ -#define PLANAR_PATCH_EPSILON 0.1 -void CreateFilters( void ) { - int i; - filter_t *f; - dsurface_t *ds; - shaderInfo_t *si; - drawVert_t *v1, *v2, *v3; - vec3_t d1, d2; - int vertNum; - - numFilters = 0; - - return; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - ds = &drawSurfaces[i]; - if ( !ds->patchWidth ) { - continue; - } - si = ShaderInfoForShader( dshaders[ ds->shaderNum ].shader ); -/* - if ( !(si->surfaceFlags & SURF_LIGHTFILTER) ) { - continue; - } -*/ - - // we have a filter patch - v1 = &drawVerts[ ds->firstVert ]; - - if ( ds->patchWidth != 3 || ds->patchHeight != 3 ) { - _printf("WARNING: patch at %i %i %i has SURF_LIGHTFILTER but isn't a 3 by 3\n", - v1->xyz[0], v1->xyz[1], v1->xyz[2] ); - continue; - } - - if ( numFilters == MAX_FILTERS ) { - Error( "MAX_FILTERS" ); - } - f = &filters[ numFilters ]; - numFilters++; - - v2 = &drawVerts[ ds->firstVert + 2 ]; - v3 = &drawVerts[ ds->firstVert + 6 ]; - - VectorSubtract( v2->xyz, v1->xyz, d1 ); - VectorSubtract( v3->xyz, v1->xyz, d2 ); - VectorNormalize( d1, d1 ); - VectorNormalize( d2, d2 ); - CrossProduct( d1, d2, f->plane ); - f->plane[3] = DotProduct( v1->xyz, f->plane ); - - // make sure all the control points are on the plane - for ( vertNum = 0 ; vertNum < ds->numVerts ; vertNum++ ) { - float d; - - d = DotProduct( drawVerts[ ds->firstVert + vertNum ].xyz, f->plane ) - f->plane[3]; - if ( fabs( d ) > PLANAR_PATCH_EPSILON ) { - break; - } - } - if ( vertNum != ds->numVerts ) { - numFilters--; - _printf("WARNING: patch at %i %i %i has SURF_LIGHTFILTER but isn't flat\n", - v1->xyz[0], v1->xyz[1], v1->xyz[2] ); - continue; - } - } - - f = &filters[0]; - numFilters = 1; - - f->plane[0] = 1; - f->plane[1] = 0; - f->plane[2] = 0; - f->plane[3] = 448; - - f->origin[0] = 448; - f->origin[1] = 192; - f->origin[2] = 0; - - f->vectors[0][0] = 0; - f->vectors[0][1] = -1.0 / 128; - f->vectors[0][2] = 0; - - f->vectors[1][0] = 0; - f->vectors[1][1] = 0; - f->vectors[1][2] = 1.0 / 128; - - f->si = ShaderInfoForShader( "textures/hell/blocks11ct" ); -} - -/* -============= -VertexLightingThread -============= -*/ -void VertexLightingThread(int num) { - dsurface_t *ds; - traceWork_t tw; - shaderInfo_t *si; - - ds = &drawSurfaces[num]; - - // vertex-lit triangle model - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) { - return; - } - - if (novertexlighting) - return; - - if ( ds->lightmapNum == -1 ) { - return; // doesn't need lighting at all - } - - si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - - // calculate the vertex lighting for gouraud shade mode - VertexLighting( ds, si->vertexShadows, si->forceSunLight, si->vertexScale, &tw ); -} - -/* -============= -TriSoupLightingThread -============= -*/ -void TriSoupLightingThread(int num) { - dsurface_t *ds; - traceWork_t tw; - shaderInfo_t *si; - - ds = &drawSurfaces[num]; - si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - - // vertex-lit triangle model - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) { - VertexLighting( ds, !si->noVertexShadows, si->forceSunLight, 1.0, &tw ); - } -} - -/* -============= -GridAndVertexLighting -============= -*/ -void GridAndVertexLighting(void) { - SetupGrid(); - - FindSkyBrushes(); - CreateFilters(); - InitTrace(); - CreateEntityLights (); - CreateSurfaceLights(); - - if (!nogridlighting) { - _printf ("--- TraceGrid ---\n"); - RunThreadsOnIndividual( numGridPoints, qtrue, TraceGrid ); - } - - if (!novertexlighting) { - _printf ("--- Vertex Lighting ---\n"); - RunThreadsOnIndividual( numDrawSurfaces, qtrue, VertexLightingThread ); - } - - _printf("--- Model Lighting ---\n"); - RunThreadsOnIndividual( numDrawSurfaces, qtrue, TriSoupLightingThread ); -} - -/* -======== -LightMain - -======== -*/ -int LightMain (int argc, char **argv) { - int i; - double start, end; - const char *value; - - _printf ("----- Lighting ----\n"); - - verbose = qfalse; - - for (i=1 ; i<argc ; i++) { - if (!strcmp(argv[i],"-tempname")) - { - i++; - } else if (!strcmp(argv[i],"-v")) { - verbose = qtrue; - } else if (!strcmp(argv[i],"-threads")) { - numthreads = atoi (argv[i+1]); - i++; - } else if (!strcmp(argv[i],"-area")) { - areaScale *= atof(argv[i+1]); - _printf ("area light scaling at %f\n", areaScale); - i++; - } else if (!strcmp(argv[i],"-point")) { - pointScale *= atof(argv[i+1]); - _printf ("point light scaling at %f\n", pointScale); - i++; - } else if (!strcmp(argv[i],"-notrace")) { - notrace = qtrue; - _printf ("No occlusion tracing\n"); - } else if (!strcmp(argv[i],"-patchshadows")) { - patchshadows = qtrue; - _printf ("Patch shadow casting enabled\n"); - } else if (!strcmp(argv[i],"-extra")) { - extra = qtrue; - _printf ("Extra detail tracing\n"); - } else if (!strcmp(argv[i],"-extrawide")) { - extra = qtrue; - extraWide = qtrue; - _printf ("Extra wide detail tracing\n"); - } else if (!strcmp(argv[i], "-samplesize")) { - samplesize = atoi(argv[i+1]); - if (samplesize < 1) samplesize = 1; - i++; - _printf("lightmap sample size is %dx%d units\n", samplesize, samplesize); - } else if (!strcmp(argv[i], "-novertex")) { - novertexlighting = qtrue; - _printf("no vertex lighting = true\n"); - } else if (!strcmp(argv[i], "-nogrid")) { - nogridlighting = qtrue; - _printf("no grid lighting = true\n"); - } else if (!strcmp(argv[i],"-border")) { - lightmapBorder = qtrue; - _printf ("Adding debug border to lightmaps\n"); - } else if (!strcmp(argv[i],"-nosurf")) { - noSurfaces = qtrue; - _printf ("Not tracing against surfaces\n" ); - } else if (!strcmp(argv[i],"-dump")) { - dump = qtrue; - _printf ("Dumping occlusion maps\n"); - } else { - break; - } - } - - ThreadSetDefault (); - - if (i != argc - 1) { - _printf("usage: q3map -light [-<switch> [-<switch> ...]] <mapname>\n" - "\n" - "Switches:\n" - " v = verbose output\n" - " threads <X> = set number of threads to X\n" - " area <V> = set the area light scale to V\n" - " point <W> = set the point light scale to W\n" - " notrace = don't cast any shadows\n" - " extra = enable super sampling for anti-aliasing\n" - " extrawide = same as extra but smoothen more\n" - " nogrid = don't calculate light grid for dynamic model lighting\n" - " novertex = don't calculate vertex lighting\n" - " samplesize <N> = set the lightmap pixel size to NxN units\n"); - exit(0); - } - - start = I_FloatTime (); - - SetQdirFromPath (argv[i]); - -#ifdef _WIN32 - InitPakFile(gamedir, NULL); -#endif - - strcpy (source, ExpandArg(argv[i])); - StripExtension (source); - DefaultExtension (source, ".bsp"); - - LoadShaderInfo(); - - _printf ("reading %s\n", source); - - LoadBSPFile (source); - - FindSkyBrushes(); - - ParseEntities(); - - value = ValueForKey( &entities[0], "gridsize" ); - if (strlen(value)) { - sscanf( value, "%f %f %f", &gridSize[0], &gridSize[1], &gridSize[2] ); - _printf("grid size = {%1.1f, %1.1f, %1.1f}\n", gridSize[0], gridSize[1], gridSize[2]); - } - - CreateFilters(); - - InitTrace(); - - SetEntityOrigins(); - - CountLightmaps(); - - CreateSurfaceLights(); - - LightWorld(); - - _printf ("writing %s\n", source); - WriteBSPFile (source); - - end = I_FloatTime (); - _printf ("%5.0f seconds elapsed\n", end-start); - - return 0; -} - diff --git a/q3map/light.h b/q3map/light.h deleted file mode 100644 index ada2763..0000000 --- a/q3map/light.h +++ /dev/null @@ -1,151 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "cmdlib.h" -#include "mathlib.h" -#include "bspfile.h" -#include "polylib.h" -#include "imagelib.h" -#include "threads.h" -#include "scriplib.h" - -#include "shaders.h" -#include "mesh.h" - - - -typedef enum -{ - emit_point, - emit_area, - emit_spotlight, - emit_sun -} emittype_t; - -#define MAX_LIGHT_EDGES 8 -typedef struct light_s -{ - struct light_s *next; - emittype_t type; - struct shaderInfo_s *si; - - vec3_t origin; - vec3_t normal; // for surfaces, spotlights, and suns - float dist; // plane location along normal - - qboolean linearLight; - int photons; - int style; - vec3_t color; - float radiusByDist; // for spotlights - - qboolean twosided; // fog lights both sides - - winding_t *w; - vec3_t emitColor; // full out-of-gamut value -} light_t; - - -extern float lightscale; -extern float ambient; -extern float maxlight; -extern float direct_scale; -extern float entity_scale; - -extern qboolean noSurfaces; - -//=============================================================== - -// light_trace.c - -// a facet is a subdivided element of a patch aproximation or model -typedef struct cFacet_s { - float surface[4]; - int numBoundaries; // either 3 or 4, anything less is degenerate - float boundaries[4][4]; // positive is outside the bounds - - vec3_t points[4]; // needed for area light subdivision - - float textureMatrix[2][4]; // compute texture coordinates at point of impact for translucency -} cFacet_t; - -typedef struct { - vec3_t mins, maxs; - vec3_t origin; - float radius; - - qboolean patch; - - int numFacets; - cFacet_t *facets; - - shaderInfo_t *shader; // for translucency -} surfaceTest_t; - - -typedef struct { - vec3_t filter; // starts out 1.0, 1.0, 1.0, may be reduced if - // transparent surfaces are crossed - - vec3_t hit; // the impact point of a completely opaque surface - float hitFraction; // 0 = at start, 1.0 = at end - qboolean passSolid; -} trace_t; - -extern surfaceTest_t *surfaceTest[MAX_MAP_DRAW_SURFS]; - -void InitTrace( void ); - -// traceWork_t is only a parameter to crutch up poor large local allocations on -// winNT and macOS. It should be allocated in the worker function, but never -// looked at. -typedef struct { - vec3_t start, end; - int numOpenLeafs; - int openLeafNumbers[MAX_MAP_LEAFS]; - trace_t *trace; - int patchshadows; -} traceWork_t; - -void TraceLine( const vec3_t start, const vec3_t stop, trace_t *trace, - qboolean testAll, traceWork_t *tw ); -qboolean PointInSolid( vec3_t start ); - -//=============================================================== - -//=============================================================== - - -typedef struct { - int textureNum; - int x, y, width, height; - - // for patches - qboolean patch; - mesh_t mesh; - - // for faces - vec3_t origin; - vec3_t vecs[3]; -} lightmap_t; - - diff --git a/q3map/light_trace.c b/q3map/light_trace.c deleted file mode 100644 index 2c78575..0000000 --- a/q3map/light_trace.c +++ /dev/null @@ -1,944 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#include "light.h" - - - -#define CURVE_FACET_ERROR 8 - -int c_totalTrace; -int c_cullTrace, c_testTrace; -int c_testFacets; - -surfaceTest_t *surfaceTest[MAX_MAP_DRAW_SURFS]; - -/* -===================== -CM_GenerateBoundaryForPoints -===================== -*/ -void CM_GenerateBoundaryForPoints( float boundary[4], float plane[4], vec3_t a, vec3_t b ) { - vec3_t d1; - - // amke a perpendicular vector to the edge and the surface - VectorSubtract( b, a, d1 ); - CrossProduct( plane, d1, boundary ); - VectorNormalize( boundary, boundary ); - boundary[3] = DotProduct( a, boundary ); -} - -/* -===================== -TextureMatrixFromPoints -===================== -*/ -void TextureMatrixFromPoints( cFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) { - int i, j; - float t; - float m[3][4]; - float s; - - // This is an incredibly stupid way of solving a three variable equation - for ( i = 0 ; i < 2 ; i++ ) { - - m[0][0] = a->xyz[0]; - m[0][1] = a->xyz[1]; - m[0][2] = a->xyz[2]; - m[0][3] = a->st[i]; - - m[1][0] = b->xyz[0]; - m[1][1] = b->xyz[1]; - m[1][2] = b->xyz[2]; - m[1][3] = b->st[i]; - - m[2][0] = c->xyz[0]; - m[2][1] = c->xyz[1]; - m[2][2] = c->xyz[2]; - m[2][3] = c->st[i]; - - if ( fabs(m[1][0]) > fabs(m[0][0]) && fabs(m[1][0]) > fabs(m[2][0]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[0][j]; - m[0][j] = m[1][j]; - m[1][j] = t; - } - } else if ( fabs(m[2][0]) > fabs(m[0][0]) && fabs(m[2][0]) > fabs(m[1][0]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[0][j]; - m[0][j] = m[2][j]; - m[2][j] = t; - } - } - - s = 1.0 / m[0][0]; - m[0][0] *= s; - m[0][1] *= s; - m[0][2] *= s; - m[0][3] *= s; - - s = m[1][0]; - m[1][0] -= m[0][0] * s; - m[1][1] -= m[0][1] * s; - m[1][2] -= m[0][2] * s; - m[1][3] -= m[0][3] * s; - - s = m[2][0]; - m[2][0] -= m[0][0] * s; - m[2][1] -= m[0][1] * s; - m[2][2] -= m[0][2] * s; - m[2][3] -= m[0][3] * s; - - if ( fabs(m[2][1]) > fabs(m[1][1]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[1][j]; - m[1][j] = m[2][j]; - m[2][j] = t; - } - } - - s = 1.0 / m[1][1]; - m[1][0] *= s; - m[1][1] *= s; - m[1][2] *= s; - m[1][3] *= s; - - s = m[2][1]; - m[2][0] -= m[1][0] * s; - m[2][1] -= m[1][1] * s; - m[2][2] -= m[1][2] * s; - m[2][3] -= m[1][3] * s; - - s = 1.0 / m[2][2]; - m[2][0] *= s; - m[2][1] *= s; - m[2][2] *= s; - m[2][3] *= s; - - f->textureMatrix[i][2] = m[2][3]; - f->textureMatrix[i][1] = m[1][3] - f->textureMatrix[i][2] * m[1][2]; - f->textureMatrix[i][0] = m[0][3] - f->textureMatrix[i][2] * m[0][2] - f->textureMatrix[i][1] * m[0][1]; - - f->textureMatrix[i][3] = 0; -/* - s = fabs( DotProduct( a->xyz, f->textureMatrix[i] ) - a->st[i] ); - if ( s > 0.01 ) { - Error( "Bad textureMatrix" ); - } - s = fabs( DotProduct( b->xyz, f->textureMatrix[i] ) - b->st[i] ); - if ( s > 0.01 ) { - Error( "Bad textureMatrix" ); - } - s = fabs( DotProduct( c->xyz, f->textureMatrix[i] ) - c->st[i] ); - if ( s > 0.01 ) { - Error( "Bad textureMatrix" ); - } -*/ - } -} - -/* -===================== -CM_GenerateFacetFor3Points -===================== -*/ -qboolean CM_GenerateFacetFor3Points( cFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) { - // if we can't generate a valid plane for the points, ignore the facet - if ( !PlaneFromPoints( f->surface, a->xyz, b->xyz, c->xyz ) ) { - f->numBoundaries = 0; - return qfalse; - } - - // make boundaries - f->numBoundaries = 3; - - CM_GenerateBoundaryForPoints( f->boundaries[0], f->surface, a->xyz, b->xyz ); - CM_GenerateBoundaryForPoints( f->boundaries[1], f->surface, b->xyz, c->xyz ); - CM_GenerateBoundaryForPoints( f->boundaries[2], f->surface, c->xyz, a->xyz ); - - VectorCopy( a->xyz, f->points[0] ); - VectorCopy( b->xyz, f->points[1] ); - VectorCopy( c->xyz, f->points[2] ); - - TextureMatrixFromPoints( f, a, b, c ); - - return qtrue; -} - -/* -===================== -CM_GenerateFacetFor4Points - -Attempts to use four points as a planar quad -===================== -*/ -#define PLANAR_EPSILON 0.1 -qboolean CM_GenerateFacetFor4Points( cFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c, drawVert_t *d ) { - float dist; - int i; - vec4_t plane; - - // if we can't generate a valid plane for the points, ignore the facet - if ( !PlaneFromPoints( f->surface, a->xyz, b->xyz, c->xyz ) ) { - f->numBoundaries = 0; - return qfalse; - } - - // if the fourth point is also on the plane, we can make a quad facet - dist = DotProduct( d->xyz, f->surface ) - f->surface[3]; - if ( fabs( dist ) > PLANAR_EPSILON ) { - f->numBoundaries = 0; - return qfalse; - } - - // make boundaries - f->numBoundaries = 4; - - CM_GenerateBoundaryForPoints( f->boundaries[0], f->surface, a->xyz, b->xyz ); - CM_GenerateBoundaryForPoints( f->boundaries[1], f->surface, b->xyz, c->xyz ); - CM_GenerateBoundaryForPoints( f->boundaries[2], f->surface, c->xyz, d->xyz ); - CM_GenerateBoundaryForPoints( f->boundaries[3], f->surface, d->xyz, a->xyz ); - - VectorCopy( a->xyz, f->points[0] ); - VectorCopy( b->xyz, f->points[1] ); - VectorCopy( c->xyz, f->points[2] ); - VectorCopy( d->xyz, f->points[3] ); - - for (i = 1; i < 4; i++) - { - if ( !PlaneFromPoints( plane, f->points[i], f->points[(i+1) % 4], f->points[(i+2) % 4]) ) { - f->numBoundaries = 0; - return qfalse; - } - - if (DotProduct(f->surface, plane) < 0.9) { - f->numBoundaries = 0; - return qfalse; - } - } - - TextureMatrixFromPoints( f, a, b, c ); - - return qtrue; -} - - - - -/* -=============== -SphereFromBounds -=============== -*/ -void SphereFromBounds( vec3_t mins, vec3_t maxs, vec3_t origin, float *radius ) { - vec3_t temp; - - VectorAdd( mins, maxs, origin ); - VectorScale( origin, 0.5, origin ); - VectorSubtract( maxs, origin, temp ); - *radius = VectorLength( temp ); -} - - -/* -==================== -FacetsForTriangleSurface -==================== -*/ -void FacetsForTriangleSurface( dsurface_t *dsurf, shaderInfo_t *si, surfaceTest_t *test ) { - int i; - drawVert_t *v1, *v2, *v3, *v4; - int count; - int i1, i2, i3, i4, i5, i6; - - test->patch = qfalse; - test->numFacets = dsurf->numIndexes / 3; - test->facets = malloc( sizeof( test->facets[0] ) * test->numFacets ); - test->shader = si; - - count = 0; - for ( i = 0 ; i < test->numFacets ; i++ ) { - i1 = drawIndexes[ dsurf->firstIndex + i*3 ]; - i2 = drawIndexes[ dsurf->firstIndex + i*3 + 1 ]; - i3 = drawIndexes[ dsurf->firstIndex + i*3 + 2 ]; - - v1 = &drawVerts[ dsurf->firstVert + i1 ]; - v2 = &drawVerts[ dsurf->firstVert + i2 ]; - v3 = &drawVerts[ dsurf->firstVert + i3 ]; - - // try and make a quad out of two triangles - if ( i != test->numFacets - 1 ) { - i4 = drawIndexes[ dsurf->firstIndex + i*3 + 3 ]; - i5 = drawIndexes[ dsurf->firstIndex + i*3 + 4 ]; - i6 = drawIndexes[ dsurf->firstIndex + i*3 + 5 ]; - if ( i4 == i3 && i5 == i2 ) { - v4 = &drawVerts[ dsurf->firstVert + i6 ]; - if ( CM_GenerateFacetFor4Points( &test->facets[count], v1, v2, v4, v3 ) ) { - count++; - i++; // skip next tri - continue; - } - } - } - - if (CM_GenerateFacetFor3Points( &test->facets[count], v1, v2, v3 )) - count++; - } - - // we may have turned some pairs into quads - test->numFacets = count; -} - -/* -==================== -FacetsForPatch -==================== -*/ -void FacetsForPatch( dsurface_t *dsurf, shaderInfo_t *si, surfaceTest_t *test ) { - int i, j; - drawVert_t *v1, *v2, *v3, *v4; - int count; - mesh_t srcMesh, *subdivided, *mesh; - - srcMesh.width = dsurf->patchWidth; - srcMesh.height = dsurf->patchHeight; - srcMesh.verts = &drawVerts[ dsurf->firstVert ]; - - //subdivided = SubdivideMesh( mesh, CURVE_FACET_ERROR, 9999 ); - mesh = SubdivideMesh( srcMesh, 8, 999 ); - PutMeshOnCurve( *mesh ); - MakeMeshNormals( *mesh ); - - subdivided = RemoveLinearMeshColumnsRows( mesh ); - FreeMesh(mesh); - - test->patch = qtrue; - test->numFacets = ( subdivided->width - 1 ) * ( subdivided->height - 1 ) * 2; - test->facets = malloc( sizeof( test->facets[0] ) * test->numFacets ); - test->shader = si; - - count = 0; - for ( i = 0 ; i < subdivided->width - 1 ; i++ ) { - for ( j = 0 ; j < subdivided->height - 1 ; j++ ) { - - v1 = subdivided->verts + j * subdivided->width + i; - v2 = v1 + 1; - v3 = v1 + subdivided->width + 1; - v4 = v1 + subdivided->width; - - if ( CM_GenerateFacetFor4Points( &test->facets[count], v1, v4, v3, v2 ) ) { - count++; - } else { - if (CM_GenerateFacetFor3Points( &test->facets[count], v1, v4, v3 )) - count++; - if (CM_GenerateFacetFor3Points( &test->facets[count], v1, v3, v2 )) - count++; - } - } - } - test->numFacets = count; - FreeMesh(subdivided); -} - - -/* -===================== -InitSurfacesForTesting - -Builds structures to speed the ray tracing against surfaces -===================== -*/ -void InitSurfacesForTesting( void ) { - - int i, j; - dsurface_t *dsurf; - surfaceTest_t *test; - drawVert_t *dvert; - shaderInfo_t *si; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - dsurf = &drawSurfaces[ i ]; - if ( !dsurf->numIndexes && !dsurf->patchWidth ) { - continue; - } - - // don't make surfaces for transparent objects - // because we want light to pass through them - si = ShaderInfoForShader( dshaders[ dsurf->shaderNum].shader ); - if ( (si->contents & CONTENTS_TRANSLUCENT) && !(si->surfaceFlags & SURF_ALPHASHADOW) ) { - continue; - } - - test = malloc( sizeof( *test ) ); - surfaceTest[i] = test; - ClearBounds( test->mins, test->maxs ); - - dvert = &drawVerts[ dsurf->firstVert ]; - for ( j = 0 ; j < dsurf->numVerts ; j++, dvert++ ) { - AddPointToBounds( dvert->xyz, test->mins, test->maxs ); - } - - SphereFromBounds( test->mins, test->maxs, test->origin, &test->radius ); - - if ( dsurf->surfaceType == MST_TRIANGLE_SOUP || dsurf->surfaceType == MST_PLANAR ) { - FacetsForTriangleSurface( dsurf, si, test ); - } else if ( dsurf->surfaceType == MST_PATCH ) { - FacetsForPatch( dsurf, si, test ); - } - } -} - - -/* -===================== -GenerateBoundaryForPoints -===================== -*/ -void GenerateBoundaryForPoints( float boundary[4], float plane[4], vec3_t a, vec3_t b ) { - vec3_t d1; - - // amke a perpendicular vector to the edge and the surface - VectorSubtract( b, a, d1 ); - CrossProduct( plane, d1, boundary ); - VectorNormalize( boundary, boundary ); - boundary[3] = DotProduct( a, boundary ); -} - - -/* -================= -SetFacetFilter - -Given a point on a facet, determine the color filter -for light passing through -================= -*/ -void SetFacetFilter( traceWork_t *tr, shaderInfo_t *shader, cFacet_t *facet, vec3_t point ) { - float s, t; - int is, it; - byte *image; - int b; - - // most surfaces are completely opaque - if ( !(shader->surfaceFlags & SURF_ALPHASHADOW) ) { - VectorClear( tr->trace->filter ); - return; - } - - s = DotProduct( point, facet->textureMatrix[0] ) + facet->textureMatrix[0][3]; - t = DotProduct( point, facet->textureMatrix[1] ) + facet->textureMatrix[1][3]; - - if ( !shader->pixels ) { - // assume completely solid - VectorClear( point ); - return; - } - - s = s - floor( s ); - t = t - floor( t ); - - is = s * shader->width; - it = t * shader->height; - - image = shader->pixels + 4 * ( it * shader->width + is ); - - // alpha filter - b = image[3]; - - // alpha test makes this a binary option - b = b < 128 ? 0 : 255; - - tr->trace->filter[0] = tr->trace->filter[0] * (255-b) / 255; - tr->trace->filter[1] = tr->trace->filter[1] * (255-b) / 255; - tr->trace->filter[2] = tr->trace->filter[2] * (255-b) / 255; -} - - -/* -==================== -TraceAgainstFacet - -Shader is needed for translucent surfaces -==================== -*/ -void TraceAgainstFacet( traceWork_t *tr, shaderInfo_t *shader, cFacet_t *facet ) { - int j; - float d1, d2, d, f; - vec3_t point; - float dist; - - // ignore degenerate facets - if ( facet->numBoundaries < 3 ) { - return; - } - - dist = facet->surface[3]; - - // compare the trace endpoints against the facet plane - d1 = DotProduct( tr->start, facet->surface ) - dist; - if ( d1 > -1 && d1 < 1 ) { - return; // don't self intersect - } - d2 = DotProduct( tr->end, facet->surface ) - dist; - if ( d2 > -1 && d2 < 1 ) { - return; // don't self intersect - } - - // calculate the intersection fraction - f = ( d1 - ON_EPSILON ) / ( d1 - d2 ); - if ( f <= 0 ) { - return; - } - if ( f >= tr->trace->hitFraction ) { - return; // we have hit something earlier - } - - // calculate the intersection point - for ( j = 0 ; j < 3 ; j++ ) { - point[j] = tr->start[j] + f * ( tr->end[j] - tr->start[j] ); - } - - // check the point against the facet boundaries - for ( j = 0 ; j < facet->numBoundaries ; j++ ) { - // adjust the plane distance apropriately for mins/maxs - dist = facet->boundaries[j][3]; - - d = DotProduct( point, facet->boundaries[j] ); - if ( d > dist + ON_EPSILON ) { - break; // outside the bounds - } - } - - if ( j != facet->numBoundaries ) { - return; // we are outside the bounds of the facet - } - - // we hit this facet - - // if this is a transparent surface, calculate filter value - if ( shader->surfaceFlags & SURF_ALPHASHADOW ) { - SetFacetFilter( tr, shader, facet, point ); - } else { - // completely opaque - VectorClear( tr->trace->filter ); - tr->trace->hitFraction = f; - } - -// VectorCopy( facet->surface, tr->trace->plane.normal ); -// tr->trace->plane.dist = facet->surface[3]; -} - - -/* -=============================================================== - - LINE TRACING - -=============================================================== -*/ - - -#define TRACE_ON_EPSILON 0.1 - -typedef struct tnode_s -{ - int type; - vec3_t normal; - float dist; - int children[2]; - int planeNum; -} tnode_t; - -#define MAX_TNODES (MAX_MAP_NODES*4) -tnode_t *tnodes, *tnode_p; - -/* -============== -MakeTnode - -Converts the disk node structure into the efficient tracing structure -============== -*/ -void MakeTnode (int nodenum) -{ - tnode_t *t; - dplane_t *plane; - int i; - dnode_t *node; - int leafNum; - - t = tnode_p++; - - node = dnodes + nodenum; - plane = dplanes + node->planeNum; - - t->planeNum = node->planeNum; - t->type = PlaneTypeForNormal( plane->normal ); - VectorCopy (plane->normal, t->normal); - t->dist = plane->dist; - - for (i=0 ; i<2 ; i++) - { - if (node->children[i] < 0) { - leafNum = -node->children[i] - 1; - if ( dleafs[leafNum].cluster == -1 ) { - // solid - t->children[i] = leafNum | ( 1 << 31 ) | ( 1 << 30 ); - } else { - t->children[i] = leafNum | ( 1 << 31 ); - } - } else { - t->children[i] = tnode_p - tnodes; - MakeTnode (node->children[i]); - } - } - -} - -/* -============= -InitTrace - -Loads the node structure out of a .bsp file to be used for light occlusion -============= -*/ -void InitTrace( void ) { - // 32 byte align the structs - tnodes = malloc( (MAX_TNODES+1) * sizeof(tnode_t)); - tnodes = (tnode_t *)(((int)tnodes + 31)&~31); - tnode_p = tnodes; - - MakeTnode (0); - - InitSurfacesForTesting(); -} - - -/* -=================== -PointInSolid -=================== -*/ -qboolean PointInSolid_r( vec3_t start, int node ) { - tnode_t *tnode; - float front; - - while ( !(node & (1<<31) ) ) { - tnode = &tnodes[node]; - switch (tnode->type) { - case PLANE_X: - front = start[0] - tnode->dist; - break; - case PLANE_Y: - front = start[1] - tnode->dist; - break; - case PLANE_Z: - front = start[2] - tnode->dist; - break; - default: - front = (start[0]*tnode->normal[0] + start[1]*tnode->normal[1] + start[2]*tnode->normal[2]) - tnode->dist; - break; - } - - if ( front == 0 ) { - // exactly on node, must check both sides - return (qboolean) ( PointInSolid_r( start, tnode->children[0] ) - | PointInSolid_r( start, tnode->children[1] ) ); - } - - if ( front > 0 ) { - node = tnode->children[0]; - } else { - node = tnode->children[1]; - } - } - - if ( node & ( 1 << 30 ) ) { - return qtrue; - } - return qfalse; -} - -/* -============= -PointInSolid - -============= -*/ -qboolean PointInSolid( vec3_t start ) { - return PointInSolid_r( start, 0 ); -} - - -/* -============= -TraceLine_r - -Returns qtrue if something is hit and tracing can stop -============= -*/ -int TraceLine_r( int node, const vec3_t start, const vec3_t stop, traceWork_t *tw ) { - tnode_t *tnode; - float front, back; - vec3_t mid; - float frac; - int side; - int r; - - if (node & (1<<31)) { - if (node & ( 1 << 30 ) ) { - VectorCopy (start, tw->trace->hit); - tw->trace->passSolid = qtrue; - return qtrue; - } else { - // save the node off for more exact testing - if ( tw->numOpenLeafs == MAX_MAP_LEAFS ) { - return qfalse; - } - tw->openLeafNumbers[ tw->numOpenLeafs ] = node & ~(3 << 30); - tw->numOpenLeafs++; - return qfalse; - } - } - - tnode = &tnodes[node]; - switch (tnode->type) { - case PLANE_X: - front = start[0] - tnode->dist; - back = stop[0] - tnode->dist; - break; - case PLANE_Y: - front = start[1] - tnode->dist; - back = stop[1] - tnode->dist; - break; - case PLANE_Z: - front = start[2] - tnode->dist; - back = stop[2] - tnode->dist; - break; - default: - front = (start[0]*tnode->normal[0] + start[1]*tnode->normal[1] + start[2]*tnode->normal[2]) - tnode->dist; - back = (stop[0]*tnode->normal[0] + stop[1]*tnode->normal[1] + stop[2]*tnode->normal[2]) - tnode->dist; - break; - } - - if (front >= -TRACE_ON_EPSILON && back >= -TRACE_ON_EPSILON) { - return TraceLine_r (tnode->children[0], start, stop, tw); - } - - if (front < TRACE_ON_EPSILON && back < TRACE_ON_EPSILON) { - return TraceLine_r (tnode->children[1], start, stop, tw); - } - - side = front < 0; - - frac = front / (front-back); - - mid[0] = start[0] + (stop[0] - start[0])*frac; - mid[1] = start[1] + (stop[1] - start[1])*frac; - mid[2] = start[2] + (stop[2] - start[2])*frac; - - r = TraceLine_r (tnode->children[side], start, mid, tw); - - if (r) { - return r; - } - -// trace->planeNum = tnode->planeNum; - return TraceLine_r (tnode->children[!side], mid, stop, tw); -} - -//========================================================================================== - - -/* -================ -SphereCull -================ -*/ -qboolean SphereCull( vec3_t start, vec3_t stop, vec3_t origin, float radius ) { - vec3_t v; - float d; - vec3_t dir; - float len; - vec3_t on; - - VectorSubtract( stop, start, dir ); - len = VectorNormalize( dir, dir ); - - VectorSubtract( origin, start, v ); - d = DotProduct( v, dir ); - if ( d > len + radius ) { - return qtrue; // too far ahead - } - if ( d < -radius ) { - return qtrue; // too far behind - } - VectorMA( start, d, dir, on ); - - VectorSubtract( on, origin, v ); - - len = VectorLength( v ); - - if ( len > radius ) { - return qtrue; // too far to the side - } - - return qfalse; // must be traced against -} - -/* -================ -TraceAgainstSurface -================ -*/ -void TraceAgainstSurface( traceWork_t *tw, surfaceTest_t *surf ) { - int i; - - // if surfaces are trans - if ( SphereCull( tw->start, tw->end, surf->origin, surf->radius ) ) { - if ( numthreads == 1 ) { - c_cullTrace++; - } - return; - } - - if ( numthreads == 1 ) { - c_testTrace++; - c_testFacets += surf->numFacets; - } - - /* - // MrE: backface culling - if (!surf->patch && surf->numFacets) { - // if the surface does not cast an alpha shadow - if ( !(surf->shader->surfaceFlags & SURF_ALPHASHADOW) ) { - vec3_t vec; - VectorSubtract(tw->end, tw->start, vec); - if (DotProduct(vec, surf->facets->surface) > 0) - return; - } - } - */ - - // test against each facet - for ( i = 0 ; i < surf->numFacets ; i++ ) { - TraceAgainstFacet( tw, surf->shader, surf->facets + i ); - } -} - -/* -============= -TraceLine - -Follow the trace just through the solid leafs first, and only -if it passes that, trace against the objects inside the empty leafs -Returns qtrue if the trace hit any - -traceWork_t is only a parameter to crutch up poor large local allocations on -winNT and macOS. It should be allocated in the worker function, but never -looked at. - -leave testAll false if all you care about is if it hit anything at all. -if you need to know the exact first point of impact (for a sun trace), set -testAll to true -============= -*/ -extern qboolean patchshadows; - -void TraceLine( const vec3_t start, const vec3_t stop, trace_t *trace, qboolean testAll, traceWork_t *tw ) { - int r; - int i, j; - dleaf_t *leaf; - float oldHitFrac; - surfaceTest_t *test; - int surfaceNum; - byte surfaceTested[MAX_MAP_DRAW_SURFS/8]; - ; - - if ( numthreads == 1 ) { - c_totalTrace++; - } - - // assume all light gets through, unless the ray crosses - // a translucent surface - trace->filter[0] = 1.0; - trace->filter[1] = 1.0; - trace->filter[2] = 1.0; - - VectorCopy( start, tw->start ); - VectorCopy( stop, tw->end ); - tw->trace = trace; - - tw->numOpenLeafs = 0; - - trace->passSolid = qfalse; - trace->hitFraction = 1.0; - - r = TraceLine_r( 0, start, stop, tw ); - - // if we hit a solid leaf, stop without testing the leaf - // surfaces. Note that the plane and endpoint might not - // be the first solid intersection along the ray. - if ( r && !testAll ) { - return; - } - - if ( noSurfaces ) { - return; - } - - memset( surfaceTested, 0, (numDrawSurfaces+7)/8 ); - oldHitFrac = trace->hitFraction; - - for ( i = 0 ; i < tw->numOpenLeafs ; i++ ) { - leaf = &dleafs[ tw->openLeafNumbers[ i ] ]; - for ( j = 0 ; j < leaf->numLeafSurfaces ; j++ ) { - surfaceNum = dleafsurfaces[ leaf->firstLeafSurface + j ]; - - // make sure we don't test the same ray against a surface more than once - if ( surfaceTested[ surfaceNum>>3 ] & ( 1 << ( surfaceNum & 7) ) ) { - continue; - } - surfaceTested[ surfaceNum>>3 ] |= ( 1 << ( surfaceNum & 7 ) ); - - test = surfaceTest[ surfaceNum ]; - if ( !test ) { - continue; - } - // - if ( !tw->patchshadows && test->patch ) { - continue; - } - TraceAgainstSurface( tw, test ); - } - - // if the trace is now solid, we can't possibly hit anything closer - if ( trace->hitFraction < oldHitFrac ) { - trace->passSolid = qtrue; - break; - } - } - - for ( i = 0 ; i < 3 ; i++ ) { - trace->hit[i] = start[i] + ( stop[i] - start[i] ) * trace->hitFraction; - } -} - diff --git a/q3map/lightmaps.c b/q3map/lightmaps.c deleted file mode 100644 index ce1fc12..0000000 --- a/q3map/lightmaps.c +++ /dev/null @@ -1,395 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#include "qbsp.h" - - -/* - - Lightmap allocation has to be done after all flood filling and - visible surface determination. - -*/ - -int numSortShaders; -mapDrawSurface_t *surfsOnShader[MAX_MAP_SHADERS]; - - -int allocated[LIGHTMAP_WIDTH]; - -int numLightmaps = 1; -int c_exactLightmap; - - -void PrepareNewLightmap( void ) { - memset( allocated, 0, sizeof( allocated ) ); - numLightmaps++; -} - -/* -=============== -AllocLMBlock - -returns a texture number and the position inside it -=============== -*/ -qboolean AllocLMBlock (int w, int h, int *x, int *y) -{ - int i, j; - int best, best2; - - best = LIGHTMAP_HEIGHT; - - for ( i=0 ; i <= LIGHTMAP_WIDTH-w ; i++ ) { - best2 = 0; - - for (j=0 ; j<w ; j++) { - if (allocated[i+j] >= best) { - break; - } - if (allocated[i+j] > best2) { - best2 = allocated[i+j]; - } - } - if (j == w) { // this is a valid spot - *x = i; - *y = best = best2; - } - } - - if (best + h > LIGHTMAP_HEIGHT) { - return qfalse; - } - - for (i=0 ; i<w ; i++) { - allocated[*x + i] = best + h; - } - - return qtrue; -} - - -/* -=================== -AllocateLightmapForPatch -=================== -*/ -//#define LIGHTMAP_PATCHSHIFT - -void AllocateLightmapForPatch( mapDrawSurface_t *ds ) { - int i, j, k; - drawVert_t *verts; - int w, h; - int x, y; - float s, t; - mesh_t mesh, *subdividedMesh, *tempMesh, *newmesh; - int widthtable[LIGHTMAP_WIDTH], heighttable[LIGHTMAP_HEIGHT], ssize; - - verts = ds->verts; - - mesh.width = ds->patchWidth; - mesh.height = ds->patchHeight; - mesh.verts = verts; - newmesh = SubdivideMesh( mesh, 8, 999 ); - - PutMeshOnCurve( *newmesh ); - tempMesh = RemoveLinearMeshColumnsRows( newmesh ); - FreeMesh(newmesh); - - ssize = samplesize; - if (ds->shaderInfo->lightmapSampleSize) - ssize = ds->shaderInfo->lightmapSampleSize; - -#ifdef LIGHTMAP_PATCHSHIFT - subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH-1, widthtable, heighttable); -#else - subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH, widthtable, heighttable); -#endif - - w = subdividedMesh->width; - h = subdividedMesh->height; - -#ifdef LIGHTMAP_PATCHSHIFT - w++; - h++; -#endif - - FreeMesh(subdividedMesh); - - // allocate the lightmap - c_exactLightmap += w * h; - - if ( !AllocLMBlock( w, h, &x, &y ) ) { - PrepareNewLightmap(); - if ( !AllocLMBlock( w, h, &x, &y ) ) { - Error("Entity %i, brush %i: Lightmap allocation failed", - ds->mapBrush->entitynum, ds->mapBrush->brushnum ); - } - } - -#ifdef LIGHTMAP_PATCHSHIFT - w--; - h--; -#endif - - // set the lightmap texture coordinates in the drawVerts - ds->lightmapNum = numLightmaps - 1; - ds->lightmapWidth = w; - ds->lightmapHeight = h; - ds->lightmapX = x; - ds->lightmapY = y; - - for ( i = 0 ; i < ds->patchWidth ; i++ ) { - for ( k = 0 ; k < w ; k++ ) { - if ( originalWidths[k] >= i ) { - break; - } - } - if (k >= w) - k = w-1; - s = x + k; - for ( j = 0 ; j < ds->patchHeight ; j++ ) { - for ( k = 0 ; k < h ; k++ ) { - if ( originalHeights[k] >= j ) { - break; - } - } - if (k >= h) - k = h-1; - t = y + k; - verts[i + j * ds->patchWidth].lightmap[0] = ( s + 0.5 ) / LIGHTMAP_WIDTH; - verts[i + j * ds->patchWidth].lightmap[1] = ( t + 0.5 ) / LIGHTMAP_HEIGHT; - } - } -} - - -/* -=================== -AllocateLightmapForSurface -=================== -*/ -//#define LIGHTMAP_BLOCK 16 -void AllocateLightmapForSurface( mapDrawSurface_t *ds ) { - vec3_t mins, maxs, size, exactSize, delta; - int i; - drawVert_t *verts; - int w, h; - int x, y, ssize; - int axis; - vec3_t vecs[2]; - float s, t; - vec3_t origin; - plane_t *plane; - float d; - vec3_t planeNormal; - - if ( ds->patch ) { - AllocateLightmapForPatch( ds ); - return; - } - - ssize = samplesize; - if (ds->shaderInfo->lightmapSampleSize) - ssize = ds->shaderInfo->lightmapSampleSize; - - plane = &mapplanes[ ds->side->planenum ]; - - // bound the surface - ClearBounds( mins, maxs ); - verts = ds->verts; - for ( i = 0 ; i < ds->numVerts ; i++ ) { - AddPointToBounds( verts[i].xyz, mins, maxs ); - } - - // round to the lightmap resolution - for ( i = 0 ; i < 3 ; i++ ) { - exactSize[i] = maxs[i] - mins[i]; - mins[i] = ssize * floor( mins[i] / ssize ); - maxs[i] = ssize * ceil( maxs[i] / ssize ); - size[i] = (maxs[i] - mins[i]) / ssize + 1; - } - - // the two largest axis will be the lightmap size - memset( vecs, 0, sizeof( vecs ) ); - - planeNormal[0] = fabs( plane->normal[0] ); - planeNormal[1] = fabs( plane->normal[1] ); - planeNormal[2] = fabs( plane->normal[2] ); - - if ( planeNormal[0] >= planeNormal[1] && planeNormal[0] >= planeNormal[2] ) { - w = size[1]; - h = size[2]; - axis = 0; - vecs[0][1] = 1.0 / ssize; - vecs[1][2] = 1.0 / ssize; - } else if ( planeNormal[1] >= planeNormal[0] && planeNormal[1] >= planeNormal[2] ) { - w = size[0]; - h = size[2]; - axis = 1; - vecs[0][0] = 1.0 / ssize; - vecs[1][2] = 1.0 / ssize; - } else { - w = size[0]; - h = size[1]; - axis = 2; - vecs[0][0] = 1.0 / ssize; - vecs[1][1] = 1.0 / ssize; - } - - if ( !plane->normal[axis] ) { - Error( "Chose a 0 valued axis" ); - } - - if ( w > LIGHTMAP_WIDTH ) { - VectorScale ( vecs[0], (float)LIGHTMAP_WIDTH/w, vecs[0] ); - w = LIGHTMAP_WIDTH; - } - - if ( h > LIGHTMAP_HEIGHT ) { - VectorScale ( vecs[1], (float)LIGHTMAP_HEIGHT/h, vecs[1] ); - h = LIGHTMAP_HEIGHT; - } - - c_exactLightmap += w * h; - - if ( !AllocLMBlock( w, h, &x, &y ) ) { - PrepareNewLightmap(); - if ( !AllocLMBlock( w, h, &x, &y ) ) { - Error("Entity %i, brush %i: Lightmap allocation failed", - ds->mapBrush->entitynum, ds->mapBrush->brushnum ); - } - } - - // set the lightmap texture coordinates in the drawVerts - ds->lightmapNum = numLightmaps - 1; - ds->lightmapWidth = w; - ds->lightmapHeight = h; - ds->lightmapX = x; - ds->lightmapY = y; - - for ( i = 0 ; i < ds->numVerts ; i++ ) { - VectorSubtract( verts[i].xyz, mins, delta ); - s = DotProduct( delta, vecs[0] ) + x + 0.5; - t = DotProduct( delta, vecs[1] ) + y + 0.5; - verts[i].lightmap[0] = s / LIGHTMAP_WIDTH; - verts[i].lightmap[1] = t / LIGHTMAP_HEIGHT; - } - - // calculate the world coordinates of the lightmap samples - - // project mins onto plane to get origin - d = DotProduct( mins, plane->normal ) - plane->dist; - d /= plane->normal[ axis ]; - VectorCopy( mins, origin ); - origin[axis] -= d; - - // project stepped lightmap blocks and subtract to get planevecs - for ( i = 0 ; i < 2 ; i++ ) { - vec3_t normalized; - float len; - - len = VectorNormalize( vecs[i], normalized ); - VectorScale( normalized, (1.0/len), vecs[i] ); - d = DotProduct( vecs[i], plane->normal ); - d /= plane->normal[ axis ]; - vecs[i][axis] -= d; - } - - VectorCopy( origin, ds->lightmapOrigin ); - VectorCopy( vecs[0], ds->lightmapVecs[0] ); - VectorCopy( vecs[1], ds->lightmapVecs[1] ); - VectorCopy( plane->normal, ds->lightmapVecs[2] ); -} - -/* -=================== -AllocateLightmaps -=================== -*/ -void AllocateLightmaps( entity_t *e ) { - int i, j; - mapDrawSurface_t *ds; - shaderInfo_t *si; - - qprintf ("--- AllocateLightmaps ---\n"); - - - // sort all surfaces by shader so common shaders will usually - // be in the same lightmap - numSortShaders = 0; - - for ( i = e->firstDrawSurf ; i < numMapDrawSurfs ; i++ ) { - ds = &mapDrawSurfs[i]; - if ( !ds->numVerts ) { - continue; // leftover from a surface subdivision - } - if ( ds->miscModel ) { - continue; - } - if ( !ds->patch ) { - VectorCopy( mapplanes[ds->side->planenum].normal, ds->lightmapVecs[2] ); - } - - // search for this shader - for ( j = 0 ; j < numSortShaders ; j++ ) { - if ( ds->shaderInfo == surfsOnShader[j]->shaderInfo ) { - ds->nextOnShader = surfsOnShader[j]; - surfsOnShader[j] = ds; - break; - } - } - if ( j == numSortShaders ) { - if ( numSortShaders >= MAX_MAP_SHADERS ) { - Error( "MAX_MAP_SHADERS" ); - } - surfsOnShader[j] = ds; - numSortShaders++; - } - } - qprintf( "%5i unique shaders\n", numSortShaders ); - - // for each shader, allocate lightmaps for each surface - -// numLightmaps = 0; -// PrepareNewLightmap(); - - for ( i = 0 ; i < numSortShaders ; i++ ) { - si = surfsOnShader[i]->shaderInfo; - - for ( ds = surfsOnShader[i] ; ds ; ds = ds->nextOnShader ) { - // some surfaces don't need lightmaps allocated for them - if ( si->surfaceFlags & SURF_NOLIGHTMAP ) { - ds->lightmapNum = -1; - } else if ( si->surfaceFlags & SURF_POINTLIGHT ) { - ds->lightmapNum = -3; - } else { - AllocateLightmapForSurface( ds ); - } - } - } - - qprintf( "%7i exact lightmap texels\n", c_exactLightmap ); - qprintf( "%7i block lightmap texels\n", numLightmaps * LIGHTMAP_WIDTH*LIGHTMAP_HEIGHT ); -} - - - diff --git a/q3map/lightv.c b/q3map/lightv.c deleted file mode 100644 index 3e9617b..0000000 --- a/q3map/lightv.c +++ /dev/null @@ -1,5748 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - - -#include "cmdlib.h" -#include "mathlib.h" -#include "bspfile.h" -#include "imagelib.h" -#include "threads.h" -#include "mutex.h" -#include "scriplib.h" - -#include "shaders.h" -#include "mesh.h" - -#ifdef _WIN32 -//Improve floating-point consistency. -#pragma optimize( "p", on ) -#endif - -#ifdef _WIN32 -#include "../libs/pakstuff.h" -#endif - -#define MAX_CLUSTERS 16384 -#define MAX_PORTALS 32768 -#define MAX_FACETS 65536 -#define MAX_LIGHTS 16384 - -#define LIGHTMAP_SIZE 128 - -#define LIGHTMAP_PIXELSHIFT 0.5 - -//#define LIGHTMAP_PATCHSHIFT - -#define PORTALFILE "PRT1" - -#define ON_EPSILON 0.1 - -#define VectorSet(v, x, y, z) v[0] = x;v[1] = y;v[2] = z; - -typedef struct -{ - vec3_t normal; - float dist; -} plane_t; - -#define MAX_POINTS_ON_WINDING 64 -//NOTE: whenever this is overflowed parts of lightmaps might end up not being lit -#define MAX_POINTS_ON_FIXED_WINDING 48 - -typedef struct -{ - int numpoints; - vec3_t points[MAX_POINTS_ON_FIXED_WINDING]; // variable sized -} winding_t; - -typedef struct -{ - plane_t plane; // normal pointing into neighbor - int leaf; // neighbor - winding_t *winding; - vec3_t origin; // for fast clip testing - float radius; -} lportal_t; - -#define MAX_PORTALS_ON_LEAF 128 -typedef struct lleaf_s -{ - int numportals; - lportal_t *portals[MAX_PORTALS_ON_LEAF]; - // - int numSurfaces; - int firstSurface; -} lleaf_t; - -typedef struct lFacet_s -{ - int num; - plane_t plane; - vec3_t points[4]; // - int numpoints; - float lightmapCoords[4][2]; - plane_t boundaries[4]; // negative is outside the bounds - float textureMatrix[2][4]; // texture coordinates for translucency - float lightmapMatrix[2][4]; // lightmap texture coordinates - vec3_t mins; - int x, y, width, height; -} lFacet_t; - -typedef struct lsurfaceTest_s -{ - vec3_t mins, maxs; - vec3_t origin; - float radius; - qboolean patch; // true if this is a patch - qboolean trisoup; // true if this is a triangle soup - int numFacets; - lFacet_t *facets; - mesh_t *detailMesh; // detailed mesh with points for each lmp - shaderInfo_t *shader; // for translucency - mutex_t *mutex; - int numvolumes; // number of volumes casted at this surface - // - int always_tracelight; - int always_vlight; -} lsurfaceTest_t; - -//volume types -#define VOLUME_NORMAL 0 -#define VOLUME_DIRECTED 1 - -#define MAX_TRANSLUCENTFACETS 32 - -typedef struct lightvolume_s -{ - int num; - int cluster; //cluster this light volume started in - plane_t endplane; //end plane - plane_t farplane; //original end plane - vec3_t points[MAX_POINTS_ON_WINDING]; //end winding points - plane_t planes[MAX_POINTS_ON_WINDING]; //volume bounding planes - int numplanes; //number of volume bounding planes - int type; //light volume type - //list with translucent surfaces the volume went through - int transFacets[MAX_TRANSLUCENTFACETS]; - int transSurfaces[MAX_TRANSLUCENTFACETS]; - int numtransFacets; - //clusters already tested - byte clusterTested[MAX_CLUSTERS/8]; - //facets already tested - byte facetTested[MAX_FACETS/8]; - int facetNum; //number of the facet blocking the light in this volume - int surfaceNum; //number of the surface blocking the light in this volume -} lightvolume_t; - -//light types -#define LIGHT_POINTRADIAL 1 -#define LIGHT_POINTSPOT 2 -#define LIGHT_POINTFAKESURFACE 3 -#define LIGHT_SURFACEDIRECTED 4 -#define LIGHT_SURFACERADIAL 5 -#define LIGHT_SURFACESPOT 6 - -//light distance attenuation types -#define LDAT_QUADRATIC 0 -#define LDAT_LINEAR 1 -#define LDAT_NOSCALE 2 - -//light angle attenuation types -#define LAAT_NORMAL 0 -#define LAAT_QUADRATIC 1 -#define LAAT_DOUBLEQUADRATIC 2 - -typedef struct vlight_s -{ - vec3_t origin; //light origin, for point lights - winding_t w; //light winding, for area lights - vec4_t plane; //light winding plane - vec3_t normal; //direction of the light - int type; //light type - vec3_t color; //light color - qboolean twosided; //radiates light at both sides of the winding - int style; //light style (not used) - int atten_disttype; //light distance attenuation type - int atten_angletype; //light angle attenuation type - float atten_distscale; //distance attenuation scale - float atten_anglescale; //angle attenuation scale - float radiusByDist; //radius by distance for spot lights - float photons; //emitted photons - float intensity; //intensity - vec3_t emitColor; //full out-of-gamut value (not used) - struct shaderInfo_s *si; //shader info - int insolid; //set when light is in solid -} vlight_t; - -float lightLinearScale = 1.0 / 8000; -float lightPointScale = 7500; -float lightAreaScale = 0.25; -float lightFormFactorValueScale = 3; -int lightDefaultSubdivide = 999; // vary by surface size? -vec3_t lightAmbientColor; - -int portalclusters, numportals, numfaces; -lleaf_t *leafs; -lportal_t *portals; -int numvlights = 0; -vlight_t *vlights[MAX_LIGHTS]; -int nostitching = 0; -int noalphashading = 0; -int nocolorshading = 0; -int nobackfaceculling = 0; -int defaulttracelight = 0; -int radiosity = 0; -int radiosity_scale; - -int clustersurfaces[MAX_MAP_LEAFFACES]; -int numclustersurfaces = 0; -lsurfaceTest_t *lsurfaceTest[MAX_MAP_DRAW_SURFS]; -int numfacets; -float lightmappixelarea[MAX_MAP_LIGHTING/3]; -float *lightFloats;//[MAX_MAP_LIGHTING]; - -// from polylib.c -winding_t *AllocWinding (int points); -void FreeWinding (winding_t *w); -void WindingCenter (winding_t *w, vec3_t center); -void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs); -vec_t WindingArea (winding_t *w); -winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist); -void ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, - vec_t epsilon, winding_t **front, winding_t **back); -winding_t *ReverseWinding (winding_t *w); - -// from light.c -extern char source[1024]; -extern vec3_t surfaceOrigin[ MAX_MAP_DRAW_SURFS ]; -extern int entitySurface[ MAX_MAP_DRAW_SURFS ]; -extern int samplesize; -extern int novertexlighting; -extern int nogridlighting; -extern qboolean patchshadows; -extern vec3_t gridSize; - -float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const winding_t *w ); -void ColorToBytes( const float *color, byte *colorBytes ); -void CountLightmaps( void ); -void GridAndVertexLighting( void ); -void SetEntityOrigins( void ); - - -//#define DEBUGNET - -#ifdef DEBUGNET - -#include "l_net.h" - -socket_t *debug_socket; - -/* -===================== -DebugNet_Setup -===================== -*/ -void DebugNet_Setup(void) -{ - address_t address; - int i; - - Net_Setup(); - Net_StringToAddress("127.0.0.1:28000", &address); - for (i = 0; i < 10; i++) - { - debug_socket = Net_Connect(&address, 28005 + i); - if (debug_socket) - break; - } -} - -/* -===================== -DebugNet_Shutdown -===================== -*/ -void DebugNet_Shutdown(void) -{ - netmessage_t msg; - - if (debug_socket) - { - NMSG_Clear(&msg); - NMSG_WriteByte(&msg, 1); - Net_Send(debug_socket, &msg); - Net_Disconnect(debug_socket); - } - debug_socket = NULL; - Net_Shutdown(); -} - -/* -===================== -DebugNet_RemoveAllPolys -===================== -*/ -void DebugNet_RemoveAllPolys(void) -{ - netmessage_t msg; - - if (!debug_socket) - return; - NMSG_Clear(&msg); - NMSG_WriteByte(&msg, 2); //remove all debug polys - Net_Send(debug_socket, &msg); -} - -/* -==================== -DebugNet_DrawWinding -===================== -*/ -void DebugNet_DrawWinding(winding_t *w, int color) -{ - netmessage_t msg; - int i; - - if (!debug_socket) - return; - NMSG_Clear(&msg); - NMSG_WriteByte(&msg, 0); //draw a winding - NMSG_WriteByte(&msg, w->numpoints); //number of points - NMSG_WriteLong(&msg, color); //color - for (i = 0; i < w->numpoints; i++) - { - NMSG_WriteFloat(&msg, w->points[i][0]); - NMSG_WriteFloat(&msg, w->points[i][1]); - NMSG_WriteFloat(&msg, w->points[i][2]); - } - Net_Send(debug_socket, &msg); -} - -/* -===================== -DebugNet_DrawLine -===================== -*/ -void DebugNet_DrawLine(vec3_t p1, vec3_t p2, int color) -{ - netmessage_t msg; - - if (!debug_socket) - return; - NMSG_Clear(&msg); - NMSG_WriteByte(&msg, 1); //draw a line - NMSG_WriteLong(&msg, color); //color - NMSG_WriteFloat(&msg, p1[0]); - NMSG_WriteFloat(&msg, p1[1]); - NMSG_WriteFloat(&msg, p1[2]); - NMSG_WriteFloat(&msg, p2[0]); - NMSG_WriteFloat(&msg, p2[1]); - NMSG_WriteFloat(&msg, p2[2]); - Net_Send(debug_socket, &msg); -} - -/* -===================== -DebugNet_DrawMesh -===================== -*/ -void DebugNet_DrawMesh(mesh_t *mesh) -{ - int i, j; - float dot; - drawVert_t *v1, *v2, *v3, *v4; - winding_t winding; - plane_t plane; - vec3_t d1, d2; - - for ( i = 0 ; i < mesh->width - 1 ; i++ ) { - for ( j = 0 ; j < mesh->height - 1 ; j++ ) { - - v1 = mesh->verts + j * mesh->width + i; - v2 = v1 + 1; - v3 = v1 + mesh->width + 1; - v4 = v1 + mesh->width; - - VectorSubtract( v4->xyz, v1->xyz, d1 ); - VectorSubtract( v3->xyz, v1->xyz, d2 ); - CrossProduct( d2, d1, plane.normal ); - if ( VectorNormalize( plane.normal, plane.normal ) != 0 ) - { - plane.dist = DotProduct( v1->xyz, plane.normal ); - dot = DotProduct(plane.normal, v2->xyz) - plane.dist; - if (fabs(dot) < 0.1) - { - VectorCopy(v1->xyz, winding.points[0]); - VectorCopy(v4->xyz, winding.points[1]); - VectorCopy(v3->xyz, winding.points[2]); - VectorCopy(v2->xyz, winding.points[3]); - winding.numpoints = 4; - DebugNet_DrawWinding(&winding, 2); - continue; - } - } - - winding.numpoints = 3; - VectorCopy(v1->xyz, winding.points[0]); - VectorCopy(v4->xyz, winding.points[1]); - VectorCopy(v3->xyz, winding.points[2]); - DebugNet_DrawWinding(&winding, 2); - - VectorCopy(v1->xyz, winding.points[0]); - VectorCopy(v3->xyz, winding.points[1]); - VectorCopy(v2->xyz, winding.points[2]); - DebugNet_DrawWinding(&winding, 2); - } - } -} - -/* -===================== -VL_DrawLightVolume -===================== -*/ -int VL_ChopWinding (winding_t *in, plane_t *split, float epsilon); - -void VL_DrawLightVolume(vlight_t *light, lightvolume_t *volume) -{ - winding_t w; - int i; - vec3_t p2, invlight; - - memcpy(w.points, volume->points, volume->numplanes * sizeof(vec3_t)); - w.numpoints = volume->numplanes; - DebugNet_DrawWinding(&w, 2); - - if (volume->type == VOLUME_DIRECTED) - { - VectorCopy(light->normal, invlight); - VectorInverse(invlight); - for (i = 0; i < volume->numplanes; i++) - { - VectorCopy(volume->points[i], w.points[0]); - VectorCopy(volume->points[(i+1) % volume->numplanes], w.points[1]); - VectorMA(w.points[1], MAX_WORLD_COORD, invlight, w.points[2]); - VectorMA(w.points[0], MAX_WORLD_COORD, invlight, w.points[3]); - w.numpoints = 4; - DebugNet_DrawWinding(&w, 2); - VectorMA(volume->points[i], 8, volume->planes[i].normal, p2); - DebugNet_DrawLine(volume->points[i], p2, 3); - } - } - else - { - // - VectorCopy(light->origin, w.points[0]); - w.numpoints = 3; - for (i = 0; i < volume->numplanes; i++) - { - VectorCopy(volume->points[i], w.points[1]); - VectorCopy(volume->points[(i+1) % volume->numplanes], w.points[2]); - VL_ChopWinding(&w, &volume->endplane, 0); - DebugNet_DrawWinding(&w, 2); - VectorMA(volume->points[i], 8, volume->planes[i].normal, p2); - DebugNet_DrawLine(volume->points[i], p2, 3); - } - } -} - -/* -============= -VL_DrawLightmapPixel -============= -*/ -void VL_DrawLightmapPixel(int surfaceNum, int x, int y, int color) -{ - winding_t w; - dsurface_t *ds; - mesh_t *mesh; - - ds = &drawSurfaces[surfaceNum]; - - if (ds->surfaceType == MST_PATCH) - { - mesh = lsurfaceTest[surfaceNum]->detailMesh; - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[0]); - VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[1]); - VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[2]); - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[3]); - w.numpoints = 4; - } - else - { - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT - ds->lightmapX, ds->lightmapVecs[0], w.points[0]); - VectorMA(w.points[0], (float) y - LIGHTMAP_PIXELSHIFT - ds->lightmapY, ds->lightmapVecs[1], w.points[0]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT - ds->lightmapX, ds->lightmapVecs[0], w.points[1]); - VectorMA(w.points[1], (float) y - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapY, ds->lightmapVecs[1], w.points[1]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapX, ds->lightmapVecs[0], w.points[2]); - VectorMA(w.points[2], (float) y - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapY, ds->lightmapVecs[1], w.points[2]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapX, ds->lightmapVecs[0], w.points[3]); - VectorMA(w.points[3], (float) y - LIGHTMAP_PIXELSHIFT - ds->lightmapY, ds->lightmapVecs[1], w.points[3]); - w.numpoints = 4; - } - DebugNet_DrawWinding(&w, color); -} - -/* -============ -VL_DrawPortals -============ -*/ -void VL_DrawPortals(void) -{ - int j; - lportal_t *p; - - for (j = 0; j < numportals * 2; j++) - { - p = portals + j; - DebugNet_DrawWinding(p->winding, 1); - } -} - -/* -============ -VL_DrawLeaf -============ -*/ -void VL_DrawLeaf(int cluster) -{ - int i; - lleaf_t *leaf; - lportal_t *p; - - leaf = &leafs[cluster]; - for (i = 0; i < leaf->numportals; i++) - { - p = leaf->portals[i]; - DebugNet_DrawWinding(p->winding, 1); - } -} - -#endif //DEBUGNET - -/* -============= -VL_SplitWinding -============= -*/ -int VL_SplitWinding (winding_t *in, winding_t *back, plane_t *split, float epsilon) -{ - vec_t dists[128]; - int sides[128]; - int counts[3]; - vec_t dot; - int i, j; - vec_t *p1, *p2; - vec3_t mid; - winding_t out; - winding_t *neww; - - counts[0] = counts[1] = counts[2] = 0; - - // determine sides for each point - for (i=0 ; i<in->numpoints ; i++) - { - dot = DotProduct (in->points[i], split->normal); - dot -= split->dist; - dists[i] = dot; - if (dot > epsilon) - sides[i] = SIDE_FRONT; - else if (dot < -epsilon) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - - if (!counts[SIDE_BACK]) - { - if (!counts[SIDE_FRONT]) - return SIDE_ON; - else - return SIDE_FRONT; - } - - if (!counts[SIDE_FRONT]) - { - return SIDE_BACK; - } - - sides[i] = sides[0]; - dists[i] = dists[0]; - - neww = &out; - - neww->numpoints = 0; - back->numpoints = 0; - - for (i=0 ; i<in->numpoints ; i++) - { - p1 = in->points[i]; - - if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VL_SplitWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; // can't chop -- fall back to original - } - if (back->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VL_SplitWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; - } - - if (sides[i] == SIDE_ON) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - VectorCopy (p1, back->points[back->numpoints]); - back->numpoints++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - } - if (sides[i] == SIDE_BACK) - { - VectorCopy (p1, back->points[back->numpoints]); - back->numpoints++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VL_SplitWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; // can't chop -- fall back to original - } - - if (back->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VL_SplitWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; // can't chop -- fall back to original - } - - // generate a split point - p2 = in->points[(i+1)%in->numpoints]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (split->normal[j] == 1) - mid[j] = split->dist; - else if (split->normal[j] == -1) - mid[j] = -split->dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, neww->points[neww->numpoints]); - neww->numpoints++; - VectorCopy (mid, back->points[back->numpoints]); - back->numpoints++; - } - memcpy(in, &out, sizeof(winding_t)); - - return SIDE_CROSS; -} - -/* -===================== -VL_LinkSurfaceIntoCluster -===================== -*/ -void VL_LinkSurfaceIntoCluster(int cluster, int surfaceNum) -{ - lleaf_t *leaf; - int i; - - leaf = &leafs[cluster]; - - for (i = 0; i < leaf->numSurfaces; i++) - { - if (clustersurfaces[leaf->firstSurface + i] == surfaceNum) - return; - } - for (i = numclustersurfaces; i > leaf->firstSurface + leaf->numSurfaces; i--) - clustersurfaces[i] = clustersurfaces[i-1]; - for (i = 0; i < portalclusters; i++) - { - if (i == cluster) - continue; - if (leafs[i].firstSurface >= leaf->firstSurface + leaf->numSurfaces) - leafs[i].firstSurface++; - } - clustersurfaces[leaf->firstSurface + leaf->numSurfaces] = surfaceNum; - leaf->numSurfaces++; - numclustersurfaces++; - if (numclustersurfaces >= MAX_MAP_LEAFFACES) - Error("MAX_MAP_LEAFFACES"); -} - -/* -===================== -VL_R_LinkSurface -===================== -*/ -void VL_R_LinkSurface(int nodenum, int surfaceNum, winding_t *w) -{ - int leafnum, cluster, res; - dnode_t *node; - dplane_t *plane; - winding_t back; - plane_t split; - - while(nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - - VectorCopy(plane->normal, split.normal); - split.dist = plane->dist; - res = VL_SplitWinding (w, &back, &split, 0.1); - - if (res == SIDE_FRONT) - { - nodenum = node->children[0]; - } - else if (res == SIDE_BACK) - { - nodenum = node->children[1]; - } - else if (res == SIDE_ON) - { - memcpy(&back, w, sizeof(winding_t)); - VL_R_LinkSurface(node->children[1], surfaceNum, &back); - nodenum = node->children[0]; - } - else - { - VL_R_LinkSurface(node->children[1], surfaceNum, &back); - nodenum = node->children[0]; - } - } - leafnum = -nodenum - 1; - cluster = dleafs[leafnum].cluster; - if (cluster != -1) - { - VL_LinkSurfaceIntoCluster(cluster, surfaceNum); - } -} - -/* -===================== -VL_LinkSurfaces - -maybe link each facet seperately instead of the test surfaces? -===================== -*/ -void VL_LinkSurfaces(void) -{ - int i, j; - lsurfaceTest_t *test; - lFacet_t *facet; - winding_t winding; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - for (j = 0; j < test->numFacets; j++) - { - facet = &test->facets[j]; - memcpy(winding.points, facet->points, facet->numpoints * sizeof(vec3_t)); - winding.numpoints = facet->numpoints; - VL_R_LinkSurface(0, i, &winding); - } - } -} - -/* -===================== -VL_TextureMatrixFromPoints -===================== -*/ -void VL_TextureMatrixFromPoints( lFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) { - int i, j; - float t; - float m[3][4]; - float s; - - // This is an incredibly stupid way of solving a three variable equation - for ( i = 0 ; i < 2 ; i++ ) { - - m[0][0] = a->xyz[0]; - m[0][1] = a->xyz[1]; - m[0][2] = a->xyz[2]; - m[0][3] = a->st[i]; - - m[1][0] = b->xyz[0]; - m[1][1] = b->xyz[1]; - m[1][2] = b->xyz[2]; - m[1][3] = b->st[i]; - - m[2][0] = c->xyz[0]; - m[2][1] = c->xyz[1]; - m[2][2] = c->xyz[2]; - m[2][3] = c->st[i]; - - if ( fabs(m[1][0]) > fabs(m[0][0]) && fabs(m[1][0]) > fabs(m[2][0]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[0][j]; - m[0][j] = m[1][j]; - m[1][j] = t; - } - } else if ( fabs(m[2][0]) > fabs(m[0][0]) && fabs(m[2][0]) > fabs(m[1][0]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[0][j]; - m[0][j] = m[2][j]; - m[2][j] = t; - } - } - - s = 1.0 / m[0][0]; - m[0][0] *= s; - m[0][1] *= s; - m[0][2] *= s; - m[0][3] *= s; - - s = m[1][0]; - m[1][0] -= m[0][0] * s; - m[1][1] -= m[0][1] * s; - m[1][2] -= m[0][2] * s; - m[1][3] -= m[0][3] * s; - - s = m[2][0]; - m[2][0] -= m[0][0] * s; - m[2][1] -= m[0][1] * s; - m[2][2] -= m[0][2] * s; - m[2][3] -= m[0][3] * s; - - if ( fabs(m[2][1]) > fabs(m[1][1]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[1][j]; - m[1][j] = m[2][j]; - m[2][j] = t; - } - } - - s = 1.0 / m[1][1]; - m[1][0] *= s; - m[1][1] *= s; - m[1][2] *= s; - m[1][3] *= s; - - s = m[2][1];// / m[1][1]; - m[2][0] -= m[1][0] * s; - m[2][1] -= m[1][1] * s; - m[2][2] -= m[1][2] * s; - m[2][3] -= m[1][3] * s; - - s = 1.0 / m[2][2]; - m[2][0] *= s; - m[2][1] *= s; - m[2][2] *= s; - m[2][3] *= s; - - f->textureMatrix[i][2] = m[2][3]; - f->textureMatrix[i][1] = m[1][3] - f->textureMatrix[i][2] * m[1][2]; - f->textureMatrix[i][0] = m[0][3] - f->textureMatrix[i][2] * m[0][2] - f->textureMatrix[i][1] * m[0][1]; - - f->textureMatrix[i][3] = 0; -/* - s = fabs( DotProduct( a->xyz, f->textureMatrix[i] ) - a->st[i] ); - if ( s > 0.01 ) { - Error( "Bad textureMatrix" ); - } - s = fabs( DotProduct( b->xyz, f->textureMatrix[i] ) - b->st[i] ); - if ( s > 0.01 ) { - Error( "Bad textureMatrix" ); - } - s = fabs( DotProduct( c->xyz, f->textureMatrix[i] ) - c->st[i] ); - if ( s > 0.01 ) { - Error( "Bad textureMatrix" ); - } -*/ - } -} - -/* -===================== -VL_LightmapMatrixFromPoints -===================== -*/ -void VL_LightmapMatrixFromPoints( dsurface_t *dsurf, shaderInfo_t *si, lFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) { - int i, j; - float t; - float m[3][4], al, bl, cl; - float s; - int h, w, ssize; - vec3_t mins, maxs, delta, size, planeNormal; - drawVert_t *verts; - static int message; - - // vertex-lit triangle model - if ( dsurf->surfaceType == MST_TRIANGLE_SOUP ) { - return; - } - - if ( dsurf->lightmapNum < 0 ) { - return; // doesn't need lighting - } - - VectorClear(f->mins); - if (dsurf->surfaceType != MST_PATCH) - { - ssize = samplesize; - if (si->lightmapSampleSize) - ssize = si->lightmapSampleSize; - ClearBounds( mins, maxs ); - verts = &drawVerts[dsurf->firstVert]; - for ( i = 0 ; i < dsurf->numVerts ; i++ ) { - AddPointToBounds( verts[i].xyz, mins, maxs ); - } - // round to the lightmap resolution - for ( i = 0 ; i < 3 ; i++ ) { - mins[i] = ssize * floor( mins[i] / ssize ); - maxs[i] = ssize * ceil( maxs[i] / ssize ); - f->mins[i] = mins[i]; - size[i] = (maxs[i] - mins[i]) / ssize + 1; - } - // the two largest axis will be the lightmap size - VectorClear(f->lightmapMatrix[0]); - f->lightmapMatrix[0][3] = 0; - VectorClear(f->lightmapMatrix[1]); - f->lightmapMatrix[1][3] = 0; - - planeNormal[0] = fabs( dsurf->lightmapVecs[2][0] ); - planeNormal[1] = fabs( dsurf->lightmapVecs[2][1] ); - planeNormal[2] = fabs( dsurf->lightmapVecs[2][2] ); - - if ( planeNormal[0] >= planeNormal[1] && planeNormal[0] >= planeNormal[2] ) { - w = size[1]; - h = size[2]; - f->lightmapMatrix[0][1] = 1.0 / ssize; - f->lightmapMatrix[1][2] = 1.0 / ssize; - } else if ( planeNormal[1] >= planeNormal[0] && planeNormal[1] >= planeNormal[2] ) { - w = size[0]; - h = size[2]; - f->lightmapMatrix[0][0] = 1.0 / ssize; - f->lightmapMatrix[1][2] = 1.0 / ssize; - } else { - w = size[0]; - h = size[1]; - f->lightmapMatrix[0][0] = 1.0 / ssize; - f->lightmapMatrix[1][1] = 1.0 / ssize; - } - if ( w > LIGHTMAP_WIDTH ) { - VectorScale ( f->lightmapMatrix[0], (float)LIGHTMAP_SIZE/w, f->lightmapMatrix[0] ); - } - - if ( h > LIGHTMAP_HEIGHT ) { - VectorScale ( f->lightmapMatrix[1], (float)LIGHTMAP_SIZE/h, f->lightmapMatrix[1] ); - } - VectorSubtract(a->xyz, f->mins, delta); - s = (DotProduct( delta, f->lightmapMatrix[0] ) + dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - if ( fabs(s - a->lightmap[0]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - t = (DotProduct( delta, f->lightmapMatrix[1] ) + dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - if ( fabs(t - a->lightmap[1]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - VectorSubtract(b->xyz, f->mins, delta); - s = (DotProduct( delta, f->lightmapMatrix[0] ) + dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - if ( fabs(s - b->lightmap[0]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - t = (DotProduct( delta, f->lightmapMatrix[1] ) + dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - if ( fabs(t - b->lightmap[1]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - VectorSubtract(c->xyz, f->mins, delta); - s = (DotProduct( delta, f->lightmapMatrix[0] ) + dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - if ( fabs(s - c->lightmap[0]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - t = (DotProduct( delta, f->lightmapMatrix[1] ) + dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - if ( fabs(t - c->lightmap[1]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - VectorAdd(f->mins, surfaceOrigin[dsurf - drawSurfaces], f->mins); - return; - } - // This is an incredibly stupid way of solving a three variable equation - for ( i = 0 ; i < 2 ; i++ ) { - - if (i) - al = a->lightmap[i] - ((float) dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - else - al = a->lightmap[i] - ((float) dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - - m[0][0] = a->xyz[0] - f->mins[0]; - m[0][1] = a->xyz[1] - f->mins[1]; - m[0][2] = a->xyz[2] - f->mins[2]; - m[0][3] = al; - - if (i) - bl = b->lightmap[i] - ((float) dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - else - bl = b->lightmap[i] - ((float) dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - - m[1][0] = b->xyz[0] - f->mins[0]; - m[1][1] = b->xyz[1] - f->mins[1]; - m[1][2] = b->xyz[2] - f->mins[2]; - m[1][3] = bl; - - if (i) - cl = c->lightmap[i] - ((float) dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - else - cl = c->lightmap[i] - ((float) dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - - m[2][0] = c->xyz[0] - f->mins[0]; - m[2][1] = c->xyz[1] - f->mins[1]; - m[2][2] = c->xyz[2] - f->mins[2]; - m[2][3] = cl; - - if ( fabs(m[1][0]) > fabs(m[0][0]) && fabs(m[1][0]) >= fabs(m[2][0]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[0][j]; - m[0][j] = m[1][j]; - m[1][j] = t; - } - } else if ( fabs(m[2][0]) > fabs(m[0][0]) && fabs(m[2][0]) >= fabs(m[1][0]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[0][j]; - m[0][j] = m[2][j]; - m[2][j] = t; - } - } - - if (m[0][0]) - { - s = 1.0 / m[0][0]; - m[0][0] *= s; - m[0][1] *= s; - m[0][2] *= s; - m[0][3] *= s; - - s = m[1][0]; - m[1][0] -= m[0][0] * s; - m[1][1] -= m[0][1] * s; - m[1][2] -= m[0][2] * s; - m[1][3] -= m[0][3] * s; - - s = m[2][0]; - m[2][0] -= m[0][0] * s; - m[2][1] -= m[0][1] * s; - m[2][2] -= m[0][2] * s; - m[2][3] -= m[0][3] * s; - } - - if ( fabs(m[2][1]) > fabs(m[1][1]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[1][j]; - m[1][j] = m[2][j]; - m[2][j] = t; - } - } - - if (m[1][1]) - { - s = 1.0 / m[1][1]; - m[1][0] *= s; - m[1][1] *= s; - m[1][2] *= s; - m[1][3] *= s; - - s = m[2][1]; - m[2][0] -= m[1][0] * s; - m[2][1] -= m[1][1] * s; - m[2][2] -= m[1][2] * s; - m[2][3] -= m[1][3] * s; - } - - if (m[2][2]) - { - s = 1.0 / m[2][2]; - m[2][0] *= s; - m[2][1] *= s; - m[2][2] *= s; - m[2][3] *= s; - } - - f->lightmapMatrix[i][2] = m[2][3]; - f->lightmapMatrix[i][1] = m[1][3] - f->lightmapMatrix[i][2] * m[1][2]; - f->lightmapMatrix[i][0] = m[0][3] - f->lightmapMatrix[i][2] * m[0][2] - f->lightmapMatrix[i][1] * m[0][1]; - - f->lightmapMatrix[i][3] = 0; - - VectorSubtract(a->xyz, f->mins, delta); - s = fabs( DotProduct( delta, f->lightmapMatrix[i] ) - al ); - if ( s > 0.01 ) { - if (!message) - _printf( "Bad lightmapMatrix\n" ); - message = qtrue; - } - VectorSubtract(b->xyz, f->mins, delta); - s = fabs( DotProduct( delta, f->lightmapMatrix[i] ) - bl ); - if ( s > 0.01 ) { - if (!message) - _printf( "Bad lightmapMatrix\n" ); - message = qtrue; - } - VectorSubtract(c->xyz, f->mins, delta); - s = fabs( DotProduct( delta, f->lightmapMatrix[i] ) - cl ); - if ( s > 0.01 ) { - if (!message) - _printf( "Bad lightmapMatrix\n" ); - message = qtrue; - } - VectorAdd(f->mins, surfaceOrigin[dsurf - drawSurfaces], f->mins); - } -} - -/* -============= -Plane_Equal -============= -*/ -#define NORMAL_EPSILON 0.0001 -#define DIST_EPSILON 0.02 - -int Plane_Equal(plane_t *a, plane_t *b, int flip) -{ - vec3_t normal; - float dist; - - if (flip) { - normal[0] = - b->normal[0]; - normal[1] = - b->normal[1]; - normal[2] = - b->normal[2]; - dist = - b->dist; - } - else { - normal[0] = b->normal[0]; - normal[1] = b->normal[1]; - normal[2] = b->normal[2]; - dist = b->dist; - } - if ( - fabs(a->normal[0] - normal[0]) < NORMAL_EPSILON - && fabs(a->normal[1] - normal[1]) < NORMAL_EPSILON - && fabs(a->normal[2] - normal[2]) < NORMAL_EPSILON - && fabs(a->dist - dist) < DIST_EPSILON ) - return qtrue; - return qfalse; -} - -/* -============= -VL_PlaneFromPoints -============= -*/ -qboolean VL_PlaneFromPoints( plane_t *plane, const vec3_t a, const vec3_t b, const vec3_t c ) { - vec3_t d1, d2; - - VectorSubtract( b, a, d1 ); - VectorSubtract( c, a, d2 ); - CrossProduct( d2, d1, plane->normal ); - if ( VectorNormalize( plane->normal, plane->normal ) == 0 ) { - return qfalse; - } - - plane->dist = DotProduct( a, plane->normal ); - return qtrue; -} - -/* -===================== -VL_GenerateBoundaryForPoints -===================== -*/ -void VL_GenerateBoundaryForPoints( plane_t *boundary, plane_t *plane, vec3_t a, vec3_t b ) { - vec3_t d1; - - // make a perpendicular vector to the edge and the surface - VectorSubtract( a, b, d1 ); - CrossProduct( plane->normal, d1, boundary->normal ); - VectorNormalize( boundary->normal, boundary->normal ); - boundary->dist = DotProduct( a, boundary->normal ); -} - -/* -===================== -VL_GenerateFacetFor3Points -===================== -*/ -qboolean VL_GenerateFacetFor3Points( dsurface_t *dsurf, shaderInfo_t *si, lFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) { - // - vec3_t dir; - int i; - - // if we can't generate a valid plane for the points, ignore the facet - if ( !VL_PlaneFromPoints( &f->plane, a->xyz, b->xyz, c->xyz ) ) { - f->numpoints = 0; - return qfalse; - } - - f->num = numfacets++; - - VectorAdd( a->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[0] ); - VectorAdd( b->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[1] ); - VectorAdd( c->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[2] ); - - f->lightmapCoords[0][0] = a->lightmap[0]; - f->lightmapCoords[0][1] = a->lightmap[1]; - f->lightmapCoords[1][0] = b->lightmap[0]; - f->lightmapCoords[1][1] = b->lightmap[1]; - f->lightmapCoords[2][0] = c->lightmap[0]; - f->lightmapCoords[2][1] = c->lightmap[1]; - - VL_GenerateBoundaryForPoints( &f->boundaries[0], &f->plane, f->points[0], f->points[1] ); - VL_GenerateBoundaryForPoints( &f->boundaries[1], &f->plane, f->points[1], f->points[2] ); - VL_GenerateBoundaryForPoints( &f->boundaries[2], &f->plane, f->points[2], f->points[0] ); - - for (i = 0; i < 3; i++) - { - VectorSubtract(f->points[(i+1)%3], f->points[i], dir); - if (VectorLength(dir) < 0.1) - return qfalse; - } - - VL_TextureMatrixFromPoints( f, a, b, c ); - VL_LightmapMatrixFromPoints( dsurf, si, f, a, b, c ); - - f->numpoints = 3; - - return qtrue; -} - -/* -===================== -VL_GenerateFacetFor4Points - -Attempts to use four points as a planar quad -===================== -*/ -#define PLANAR_EPSILON 0.1 -qboolean VL_GenerateFacetFor4Points( dsurface_t *dsurf, shaderInfo_t *si, lFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c, drawVert_t *d ) { - float dist; - vec3_t dir; - int i; - plane_t plane; - - // if we can't generate a valid plane for the points, ignore the facet - if ( !VL_PlaneFromPoints( &f->plane, a->xyz, b->xyz, c->xyz ) ) { - f->numpoints = 0; - return qfalse; - } - - // if the fourth point is also on the plane, we can make a quad facet - dist = DotProduct( d->xyz, f->plane.normal ) - f->plane.dist; - if ( fabs( dist ) > PLANAR_EPSILON ) { - f->numpoints = 0; - return qfalse; - } - - VectorAdd( a->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[0] ); - VectorAdd( b->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[1] ); - VectorAdd( c->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[2] ); - VectorAdd( d->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[3] ); - - for (i = 1; i < 4; i++) - { - if ( !VL_PlaneFromPoints( &plane, f->points[i], f->points[(i+1) % 4], f->points[(i+2) % 4]) ) { - f->numpoints = 0; - return qfalse; - } - - if (!Plane_Equal(&f->plane, &plane, qfalse)) { - f->numpoints = 0; - return qfalse; - } - } - - f->lightmapCoords[0][0] = a->lightmap[0]; - f->lightmapCoords[0][1] = a->lightmap[1]; - f->lightmapCoords[1][0] = b->lightmap[0]; - f->lightmapCoords[1][1] = b->lightmap[1]; - f->lightmapCoords[2][0] = c->lightmap[0]; - f->lightmapCoords[2][1] = c->lightmap[1]; - f->lightmapCoords[3][0] = d->lightmap[0]; - f->lightmapCoords[3][1] = d->lightmap[1]; - - VL_GenerateBoundaryForPoints( &f->boundaries[0], &f->plane, f->points[0], f->points[1] ); - VL_GenerateBoundaryForPoints( &f->boundaries[1], &f->plane, f->points[1], f->points[2] ); - VL_GenerateBoundaryForPoints( &f->boundaries[2], &f->plane, f->points[2], f->points[3] ); - VL_GenerateBoundaryForPoints( &f->boundaries[3], &f->plane, f->points[3], f->points[0] ); - - for (i = 0; i < 4; i++) - { - VectorSubtract(f->points[(i+1)%4], f->points[i], dir); - if (VectorLength(dir) < 0.1) - return qfalse; - } - - VL_TextureMatrixFromPoints( f, a, b, c ); - VL_LightmapMatrixFromPoints( dsurf, si, f, a, b, c ); - - f->num = numfacets++; - f->numpoints = 4; - - return qtrue; -} - -/* -=============== -VL_SphereFromBounds -=============== -*/ -void VL_SphereFromBounds( vec3_t mins, vec3_t maxs, vec3_t origin, float *radius ) { - vec3_t temp; - - VectorAdd( mins, maxs, origin ); - VectorScale( origin, 0.5, origin ); - VectorSubtract( maxs, origin, temp ); - *radius = VectorLength( temp ); -} - -/* -==================== -VL_FacetsForTriangleSurface -==================== -*/ -void VL_FacetsForTriangleSurface( dsurface_t *dsurf, shaderInfo_t *si, lsurfaceTest_t *test ) { - int i; - drawVert_t *v1, *v2, *v3, *v4; - int count; - int i1, i2, i3, i4, i5, i6; - - test->patch = qfalse; - if (dsurf->surfaceType == MST_TRIANGLE_SOUP) - test->trisoup = qtrue; - else - test->trisoup = qfalse; - test->numFacets = dsurf->numIndexes / 3; - test->facets = malloc( sizeof( test->facets[0] ) * test->numFacets ); - test->shader = si; - - count = 0; - for ( i = 0 ; i < test->numFacets ; i++ ) { - i1 = drawIndexes[ dsurf->firstIndex + i*3 ]; - i2 = drawIndexes[ dsurf->firstIndex + i*3 + 1 ]; - i3 = drawIndexes[ dsurf->firstIndex + i*3 + 2 ]; - - v1 = &drawVerts[ dsurf->firstVert + i1 ]; - v2 = &drawVerts[ dsurf->firstVert + i2 ]; - v3 = &drawVerts[ dsurf->firstVert + i3 ]; - - // try and make a quad out of two triangles - if ( i != test->numFacets - 1 ) { - i4 = drawIndexes[ dsurf->firstIndex + i*3 + 3 ]; - i5 = drawIndexes[ dsurf->firstIndex + i*3 + 4 ]; - i6 = drawIndexes[ dsurf->firstIndex + i*3 + 5 ]; - if ( i4 == i3 && i5 == i2 ) { - v4 = &drawVerts[ dsurf->firstVert + i6 ]; - if ( VL_GenerateFacetFor4Points( dsurf, si, &test->facets[count], v1, v2, v4, v3 ) ) { - count++; - i++; // skip next tri - continue; - } - } - } - - if (VL_GenerateFacetFor3Points( dsurf, si, &test->facets[count], v1, v2, v3 )) { - count++; - } - } - - // we may have turned some pairs into quads - test->numFacets = count; -} - -/* -==================== -VL_FacetsForPatch -==================== -*/ -void VL_FacetsForPatch( dsurface_t *dsurf, int surfaceNum, shaderInfo_t *si, lsurfaceTest_t *test ) { - int i, j, x, y; - drawVert_t *v1, *v2, *v3, *v4; - int count, ssize; - mesh_t mesh; - mesh_t *subdivided, *detailmesh, *newmesh; - int widthtable[LIGHTMAP_SIZE], heighttable[LIGHTMAP_SIZE]; - - mesh.width = dsurf->patchWidth; - mesh.height = dsurf->patchHeight; - mesh.verts = &drawVerts[ dsurf->firstVert ]; - - newmesh = SubdivideMesh( mesh, 8, 999 ); - PutMeshOnCurve( *newmesh ); - MakeMeshNormals( *newmesh ); - - subdivided = RemoveLinearMeshColumnsRows( newmesh ); - FreeMesh(newmesh); - - // DebugNet_RemoveAllPolys(); - // DebugNet_DrawMesh(subdivided); - - ssize = samplesize; - if (si->lightmapSampleSize) - ssize = si->lightmapSampleSize; - - if ( dsurf->lightmapNum >= 0 ) { - - detailmesh = SubdivideMeshQuads( subdivided, ssize, LIGHTMAP_SIZE, widthtable, heighttable); - test->detailMesh = detailmesh; - - // DebugNet_RemoveAllPolys(); - // DebugNet_DrawMesh(detailmesh); - - if ( detailmesh->width != dsurf->lightmapWidth || detailmesh->height != dsurf->lightmapHeight ) { - Error( "Mesh lightmap miscount"); - } - } - else { - test->detailMesh = NULL; - memset(widthtable, 0, sizeof(widthtable)); - memset(heighttable, 0, sizeof(heighttable)); - } - - test->patch = qtrue; - test->trisoup = qfalse; - test->numFacets = ( subdivided->width - 1 ) * ( subdivided->height - 1 ) * 2; - test->facets = malloc( sizeof( test->facets[0] ) * test->numFacets ); - test->shader = si; - - count = 0; - x = 0; - for ( i = 0 ; i < subdivided->width - 1 ; i++ ) { - y = 0; - for ( j = 0 ; j < subdivided->height - 1 ; j++ ) { - - v1 = subdivided->verts + j * subdivided->width + i; - v2 = v1 + 1; - v3 = v1 + subdivided->width + 1; - v4 = v1 + subdivided->width; - - if ( VL_GenerateFacetFor4Points( dsurf, si, &test->facets[count], v1, v4, v3, v2 ) ) { - test->facets[count].x = x; - test->facets[count].y = y; - test->facets[count].width = widthtable[i]; - test->facets[count].height = heighttable[j]; - count++; - } else { - if (VL_GenerateFacetFor3Points( dsurf, si, &test->facets[count], v1, v4, v3 )) { - test->facets[count].x = x; - test->facets[count].y = y; - test->facets[count].width = widthtable[i]; - test->facets[count].height = heighttable[j]; - count++; - } - if (VL_GenerateFacetFor3Points( dsurf, si, &test->facets[count], v1, v3, v2 )) { - test->facets[count].x = x; - test->facets[count].y = y; - test->facets[count].width = widthtable[i]; - test->facets[count].height = heighttable[j]; - count++; - } - } - y += heighttable[j]; - } - x += widthtable[i]; - } - test->numFacets = count; - - FreeMesh(subdivided); -} - -/* -===================== -VL_InitSurfacesForTesting -===================== -*/ -void VL_InitSurfacesForTesting( void ) { - - int i, j, k; - dsurface_t *dsurf; - lsurfaceTest_t *test; - shaderInfo_t *si; - lFacet_t *facet; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - // don't light the entity surfaces with vlight - if ( entitySurface[i] ) - continue; - // - dsurf = &drawSurfaces[ i ]; - if ( !dsurf->numIndexes && !dsurf->patchWidth ) { - continue; - } - - si = ShaderInfoForShader( dshaders[ dsurf->shaderNum].shader ); - // if the surface is translucent and does not cast an alpha shadow - if ( (si->contents & CONTENTS_TRANSLUCENT) && !(si->surfaceFlags & SURF_ALPHASHADOW) ) { - // if the surface has no lightmap - if ( dsurf->lightmapNum < 0 ) - continue; - } - - test = malloc( sizeof( *test ) ); - memset(test, 0, sizeof( *test )); - test->mutex = MutexAlloc(); - test->numvolumes = 0; - if (si->forceTraceLight) - test->always_tracelight = qtrue; - else if (si->forceVLight) - test->always_vlight = qtrue; - lsurfaceTest[i] = test; - - if ( dsurf->surfaceType == MST_TRIANGLE_SOUP || dsurf->surfaceType == MST_PLANAR ) { - VL_FacetsForTriangleSurface( dsurf, si, test ); - } else if ( dsurf->surfaceType == MST_PATCH ) { - VL_FacetsForPatch( dsurf, i, si, test ); - } - if (numfacets >= MAX_FACETS) - Error("numfacets >= MAX_FACETS (%d)", MAX_FACETS); - - ClearBounds( test->mins, test->maxs ); - for (j = 0; j < test->numFacets; j++) - { - facet = &test->facets[j]; - for ( k = 0 ; k < facet->numpoints; k++) { - AddPointToBounds( facet->points[k], test->mins, test->maxs ); - } - } - VL_SphereFromBounds( test->mins, test->maxs, test->origin, &test->radius ); - } - _printf("%6d facets\n", numfacets); - _printf("linking surfaces...\n"); - VL_LinkSurfaces(); -} - -/* -============= -VL_ChopWinding -============= -*/ -int VL_ChopWinding (winding_t *in, plane_t *split, float epsilon) -{ - vec_t dists[128]; - int sides[128]; - int counts[3]; - vec_t dot; - int i, j; - vec_t *p1, *p2; - vec3_t mid; - winding_t out; - winding_t *neww; - - counts[0] = counts[1] = counts[2] = 0; - - // determine sides for each point - for (i=0 ; i<in->numpoints ; i++) - { - dot = DotProduct (in->points[i], split->normal); - dot -= split->dist; - dists[i] = dot; - if (dot > epsilon) - sides[i] = SIDE_FRONT; - else if (dot < -epsilon) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - - if (!counts[SIDE_BACK]) - { - if (!counts[SIDE_FRONT]) - return SIDE_ON; - else - return SIDE_FRONT; - } - - if (!counts[SIDE_FRONT]) - { - return SIDE_BACK; - } - - sides[i] = sides[0]; - dists[i] = dists[0]; - - neww = &out; - - neww->numpoints = 0; - - for (i=0 ; i<in->numpoints ; i++) - { - p1 = in->points[i]; - - if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VL_ChopWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; // can't chop -- fall back to original - } - - if (sides[i] == SIDE_ON) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VL_ChopWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; // can't chop -- fall back to original - } - - // generate a split point - p2 = in->points[(i+1)%in->numpoints]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (split->normal[j] == 1) - mid[j] = split->dist; - else if (split->normal[j] == -1) - mid[j] = -split->dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, neww->points[neww->numpoints]); - neww->numpoints++; - } - memcpy(in, &out, sizeof(winding_t)); - - return SIDE_CROSS; -} - -/* -============= -VL_ChopWindingWithBrush - - returns all winding fragments outside the brush -============= -*/ -int VL_ChopWindingWithBrush(winding_t *w, dbrush_t *brush, winding_t *outwindings, int maxout) -{ - int i, res, numout; - winding_t front, back; - plane_t plane; - - numout = 0; - memcpy(front.points, w->points, w->numpoints * sizeof(vec3_t)); - front.numpoints = w->numpoints; - for (i = 0; i < brush->numSides; i++) - { - VectorCopy(dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].normal, plane.normal); - VectorInverse(plane.normal); - plane.dist = -dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].dist; - res = VL_SplitWinding(&front, &back, &plane, 0.1); - if (res == SIDE_BACK || res == SIDE_ON) - { - memcpy(outwindings[0].points, w->points, w->numpoints * sizeof(vec3_t)); - outwindings[0].numpoints = w->numpoints; - return 1; //did not intersect - } - if (res != SIDE_FRONT) - { - if (numout >= maxout) - { - _printf("WARNING: VL_ChopWindingWithBrush: more than %d windings\n", maxout); - return 0; - } - memcpy(outwindings[numout].points, back.points, back.numpoints * sizeof(vec3_t)); - outwindings[numout].numpoints = back.numpoints; - numout++; - } - } - return numout; -} - -/* -============= -VL_WindingAreaOutsideBrushes -============= -*/ -float VL_WindingAreaOutsideBrushes(winding_t *w, int *brushnums, int numbrushes) -{ - int i, j, numwindings[2], n; - winding_t windingsbuf[2][64]; - dbrush_t *brush; - float area; - - memcpy(windingsbuf[0][0].points, w->points, w->numpoints * sizeof(vec3_t)); - windingsbuf[0][0].numpoints = w->numpoints; - numwindings[0] = 1; - for (i = 0; i < numbrushes; i++) - { - brush = &dbrushes[brushnums[i]]; - if (!(dshaders[brush->shaderNum].contentFlags & ( - CONTENTS_LAVA - | CONTENTS_SLIME - | CONTENTS_WATER - | CONTENTS_FOG - | CONTENTS_AREAPORTAL - | CONTENTS_PLAYERCLIP - | CONTENTS_MONSTERCLIP - | CONTENTS_CLUSTERPORTAL - | CONTENTS_DONOTENTER - | CONTENTS_BODY - | CONTENTS_CORPSE - | CONTENTS_TRANSLUCENT - | CONTENTS_TRIGGER - | CONTENTS_NODROP) ) && - (dshaders[brush->shaderNum].contentFlags & CONTENTS_SOLID) ) - { - numwindings[!(i & 1)] = 0; - for (j = 0; j < numwindings[i&1]; j++) - { - n = VL_ChopWindingWithBrush(&windingsbuf[i&1][j], brush, - &windingsbuf[!(i&1)][numwindings[!(i&1)]], - 64 - numwindings[!(i&1)]); - numwindings[!(i&1)] += n; - } - if (!numwindings[!(i&1)]) - return 0; - } - else - { - for (j = 0; j < numwindings[i&1]; j++) - { - windingsbuf[!(i&1)][j] = windingsbuf[i&1][j]; - } - numwindings[!(i&1)] = numwindings[i&1]; - } - } - area = 0; - for (j = 0; j < numwindings[i&1]; j++) - { - area += WindingArea(&windingsbuf[i&1][j]); - } - return area; -} - -/* -============= -VL_R_WindingAreaOutsideSolid -============= -*/ -float VL_R_WindingAreaOutsideSolid(winding_t *w, vec3_t normal, int nodenum) -{ - int leafnum, res; - float area; - dnode_t *node; - dleaf_t *leaf; - dplane_t *plane; - winding_t back; - plane_t split; - - area = 0; - while(nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - - VectorCopy(plane->normal, split.normal); - split.dist = plane->dist; - res = VL_SplitWinding (w, &back, &split, 0.1); - - if (res == SIDE_FRONT) - { - nodenum = node->children[0]; - } - else if (res == SIDE_BACK) - { - nodenum = node->children[1]; - } - else if (res == SIDE_ON) - { - if (DotProduct(normal, plane->normal) > 0) - nodenum = node->children[0]; - else - nodenum = node->children[1]; - } - else - { - area += VL_R_WindingAreaOutsideSolid(&back, normal, node->children[1]); - nodenum = node->children[0]; - } - } - leafnum = -nodenum - 1; - leaf = &dleafs[leafnum]; - if (leaf->cluster != -1) - { - area += VL_WindingAreaOutsideBrushes(w, &dleafbrushes[leaf->firstLeafBrush], leaf->numLeafBrushes); - } - return area; -} - -/* -============= -VL_WindingAreaOutsideSolid -============= -*/ -float VL_WindingAreaOutsideSolid(winding_t *w, vec3_t normal) -{ - return VL_R_WindingAreaOutsideSolid(w, normal, 0); -} - -/* -============= -VL_ChopWindingWithFacet -============= -*/ -float VL_ChopWindingWithFacet(winding_t *w, lFacet_t *facet) -{ - int i; - - for (i = 0; i < facet->numpoints; i++) - { - if (VL_ChopWinding(w, &facet->boundaries[i], 0) == SIDE_BACK) - return 0; - } - if (nostitching) - return WindingArea(w); - else - return VL_WindingAreaOutsideSolid(w, facet->plane.normal); -} - -/* -============= -VL_CalcVisibleLightmapPixelArea - -nice brute force ;) -============= -*/ -void VL_CalcVisibleLightmapPixelArea(void) -{ - int i, j, x, y, k; - dsurface_t *ds; - lsurfaceTest_t *test; - mesh_t *mesh; - winding_t w, tmpw; - float area; - - _printf("calculating visible lightmap pixel area...\n"); - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - ds = &drawSurfaces[ i ]; - - if ( ds->lightmapNum < 0 ) - continue; - - for (y = 0; y < ds->lightmapHeight; y++) - { - for (x = 0; x < ds->lightmapWidth; x++) - { - if (ds->surfaceType == MST_PATCH) - { - if (y == ds->lightmapHeight-1) - continue; - if (x == ds->lightmapWidth-1) - continue; - mesh = lsurfaceTest[i]->detailMesh; - VectorCopy( mesh->verts[y*mesh->width+x].xyz, w.points[0]); - VectorCopy( mesh->verts[(y+1)*mesh->width+x].xyz, w.points[1]); - VectorCopy( mesh->verts[(y+1)*mesh->width+x+1].xyz, w.points[2]); - VectorCopy( mesh->verts[y*mesh->width+x+1].xyz, w.points[3]); - w.numpoints = 4; - if (nostitching) - area = WindingArea(&w); - else - area = VL_WindingAreaOutsideSolid(&w, mesh->verts[y*mesh->width+x].normal); - } - else - { - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[0], w.points[0]); - VectorMA(w.points[0], (float) y - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[1], w.points[0]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[0], w.points[3]); - VectorMA(w.points[3], (float) y - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[1], w.points[3]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[0], w.points[2]); - VectorMA(w.points[2], (float) y - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[1], w.points[2]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[0], w.points[1]); - VectorMA(w.points[1], (float) y - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[1], w.points[1]); - w.numpoints = 4; - area = 0; - for (j = 0; j < test->numFacets; j++) - { - memcpy(&tmpw, &w, sizeof(winding_t)); - area += VL_ChopWindingWithFacet(&tmpw, &test->facets[j]); - } - } - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - lightmappixelarea[k] = area; - } - } - } -} - -/* -============= -VL_FindAdjacentSurface -============= -*/ -int VL_FindAdjacentSurface(int surfaceNum, int facetNum, vec3_t p1, vec3_t p2, int *sNum, int *fNum, int *point) -{ - int i, j, k; - lsurfaceTest_t *test; - lFacet_t *facet; - dsurface_t *ds; - float *fp1, *fp2; - vec3_t dir; - plane_t *facetplane; - // winding_t w; - - facetplane = &lsurfaceTest[surfaceNum]->facets[facetNum].plane; - // DebugNet_RemoveAllPolys(); - // memcpy(w.points, lsurfaceTest[surfaceNum]->facets[facetNum].points, - // lsurfaceTest[surfaceNum]->facets[facetNum].numpoints * sizeof(vec3_t)); - // w.numpoints = lsurfaceTest[surfaceNum]->facets[facetNum].numpoints; - // DebugNet_DrawWinding(&w, 2); - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - if (i == surfaceNum) - continue; - test = lsurfaceTest[ i ]; - if (!test) - continue; - if (test->trisoup)// || test->patch) - continue; - ds = &drawSurfaces[i]; - if ( ds->lightmapNum < 0 ) - continue; - //if this surface is not even near the edge - VectorSubtract(p1, test->origin, dir); - if (fabs(dir[0]) > test->radius || - fabs(dir[1]) > test->radius || - fabs(dir[1]) > test->radius) - { - VectorSubtract(p2, test->origin, dir); - if (fabs(dir[0]) > test->radius || - fabs(dir[1]) > test->radius || - fabs(dir[1]) > test->radius) - { - continue; - } - } - // - for (j = 0; j < test->numFacets; j++) - { - facet = &test->facets[j]; - // - //if (!Plane_Equal(&facet->plane, facetplane, qfalse)) - if (DotProduct(facet->plane.normal, facetplane->normal) < 0.9) - { - if (!test->trisoup && !test->patch) - break; - continue; - } - // - for (k = 0; k < facet->numpoints; k++) - { - fp1 = facet->points[k]; - if (fabs(p2[0] - fp1[0]) < 0.1 && - fabs(p2[1] - fp1[1]) < 0.1 && - fabs(p2[2] - fp1[2]) < 0.1) - { - fp2 = facet->points[(k+1) % facet->numpoints]; - if (fabs(p1[0] - fp2[0]) < 0.1 && - fabs(p1[1] - fp2[1]) < 0.1 && - fabs(p1[2] - fp2[2]) < 0.1) - { - // memcpy(w.points, facet->points, facet->numpoints * sizeof(vec3_t)); - // w.numpoints = facet->numpoints; - // DebugNet_DrawWinding(&w, 1); - *sNum = i; - *fNum = j; - *point = k; - return qtrue; - } - } - /* - else if (fabs(p1[0] - fp1[0]) < 0.1 && - fabs(p1[1] - fp1[1]) < 0.1 && - fabs(p1[2] - fp1[2]) < 0.1) - { - fp2 = facet->points[(k+1) % facet->numpoints]; - if (fabs(p2[0] - fp2[0]) < 0.1 && - fabs(p2[1] - fp2[1]) < 0.1 && - fabs(p2[2] - fp2[2]) < 0.1) - { - // memcpy(w.points, facet->points, facet->numpoints * sizeof(vec3_t)); - // w.numpoints = facet->numpoints; - // DebugNet_DrawWinding(&w, 1); - *sNum = i; - *fNum = j; - *point = k; - return qtrue; - } - } - //*/ - } - } - } - return qfalse; -} - -/* -============= -VL_SmoothenLightmapEdges - -this code is used to smoothen lightmaps across surface edges -============= -*/ -void VL_SmoothenLightmapEdges(void) -{ - int i, j, k, coords1[2][2]; - float coords2[2][2]; - int x1, y1, xinc1, yinc1, k1, k2; - float x2, y2, xinc2, yinc2, length; - int surfaceNum, facetNum, point; - lsurfaceTest_t *test; - lFacet_t *facet1, *facet2; - dsurface_t *ds1, *ds2; - float *p[2], s, t, *color1, *color2; - vec3_t dir, cross; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - if (test->trisoup)// || test->patch) - continue; - ds1 = &drawSurfaces[i]; - if ( ds1->lightmapNum < 0 ) - continue; - for (j = 0; j < test->numFacets; j++) - { - facet1 = &test->facets[j]; - // - for (k = 0; k < facet1->numpoints; k++) - { - p[0] = facet1->points[k]; - p[1] = facet1->points[(k+1)%facet1->numpoints]; - // - coords1[0][0] = facet1->lightmapCoords[k][0] * LIGHTMAP_SIZE; - coords1[0][1] = facet1->lightmapCoords[k][1] * LIGHTMAP_SIZE; - coords1[1][0] = facet1->lightmapCoords[(k+1)%facet1->numpoints][0] * LIGHTMAP_SIZE; - coords1[1][1] = facet1->lightmapCoords[(k+1)%facet1->numpoints][1] * LIGHTMAP_SIZE; - if (coords1[0][0] >= LIGHTMAP_SIZE) - coords1[0][0] = LIGHTMAP_SIZE-1; - if (coords1[0][1] >= LIGHTMAP_SIZE) - coords1[0][1] = LIGHTMAP_SIZE-1; - if (coords1[1][0] >= LIGHTMAP_SIZE) - coords1[1][0] = LIGHTMAP_SIZE-1; - if (coords1[1][1] >= LIGHTMAP_SIZE) - coords1[1][1] = LIGHTMAP_SIZE-1; - // try one row or column further because on flat faces the lightmap can - // extend beyond the edge - VectorSubtract(p[1], p[0], dir); - VectorNormalize(dir, dir); - CrossProduct(dir, facet1->plane.normal, cross); - // - if (coords1[0][0] - coords1[1][0] == 0) - { - s = DotProduct( cross, facet1->lightmapMatrix[0] ); - coords1[0][0] += s < 0 ? 1 : -1; - coords1[1][0] += s < 0 ? 1 : -1; - if (coords1[0][0] < ds1->lightmapX || coords1[0][0] >= ds1->lightmapX + ds1->lightmapWidth) - { - coords1[0][0] += s < 0 ? -1 : 1; - coords1[1][0] += s < 0 ? -1 : 1; - } - length = fabs(coords1[1][1] - coords1[0][1]); - } - else if (coords1[0][1] - coords1[1][1] == 0) - { - t = DotProduct( cross, facet1->lightmapMatrix[1] ); - coords1[0][1] += t < 0 ? 1 : -1; - coords1[1][1] += t < 0 ? 1 : -1; - if (coords1[0][1] < ds1->lightmapY || coords1[0][1] >= ds1->lightmapY + ds1->lightmapHeight) - { - coords1[0][1] += t < 0 ? -1 : 1; - coords1[1][1] += t < 0 ? -1 : 1; - } - length = fabs(coords1[1][0] - coords1[0][0]); - } - else - { - //the edge is not parallell to one of the lightmap axis - continue; - } - // - x1 = coords1[0][0]; - y1 = coords1[0][1]; - xinc1 = coords1[1][0] - coords1[0][0]; - if (xinc1 < 0) xinc1 = -1; - if (xinc1 > 0) xinc1 = 1; - yinc1 = coords1[1][1] - coords1[0][1]; - if (yinc1 < 0) yinc1 = -1; - if (yinc1 > 0) yinc1 = 1; - // the edge should be parallell to one of the lightmap axis - if (xinc1 != 0 && yinc1 != 0) - continue; - // - if (!VL_FindAdjacentSurface(i, j, p[0], p[1], &surfaceNum, &facetNum, &point)) - continue; - // - ds2 = &drawSurfaces[surfaceNum]; - facet2 = &lsurfaceTest[surfaceNum]->facets[facetNum]; - coords2[0][0] = facet2->lightmapCoords[(point+1)%facet2->numpoints][0] * LIGHTMAP_SIZE; - coords2[0][1] = facet2->lightmapCoords[(point+1)%facet2->numpoints][1] * LIGHTMAP_SIZE; - coords2[1][0] = facet2->lightmapCoords[point][0] * LIGHTMAP_SIZE; - coords2[1][1] = facet2->lightmapCoords[point][1] * LIGHTMAP_SIZE; - if (coords2[0][0] >= LIGHTMAP_SIZE) - coords2[0][0] = LIGHTMAP_SIZE-1; - if (coords2[0][1] >= LIGHTMAP_SIZE) - coords2[0][1] = LIGHTMAP_SIZE-1; - if (coords2[1][0] >= LIGHTMAP_SIZE) - coords2[1][0] = LIGHTMAP_SIZE-1; - if (coords2[1][1] >= LIGHTMAP_SIZE) - coords2[1][1] = LIGHTMAP_SIZE-1; - // - x2 = coords2[0][0]; - y2 = coords2[0][1]; - xinc2 = coords2[1][0] - coords2[0][0]; - if (length) - xinc2 = xinc2 / length; - yinc2 = coords2[1][1] - coords2[0][1]; - if (length) - yinc2 = yinc2 / length; - // the edge should be parallell to one of the lightmap axis - if ((int) xinc2 != 0 && (int) yinc2 != 0) - continue; - // - while(1) - { - k1 = ( ds1->lightmapNum * LIGHTMAP_HEIGHT + y1) * LIGHTMAP_WIDTH + x1; - k2 = ( ds2->lightmapNum * LIGHTMAP_HEIGHT + ((int) y2)) * LIGHTMAP_WIDTH + ((int) x2); - color1 = lightFloats + k1*3; - color2 = lightFloats + k2*3; - if (lightmappixelarea[k1] < 0.01) - { - color1[0] = color2[0]; - color1[1] = color2[1]; - color1[2] = color2[2]; - } - else - { - color1[0] = (float) color2[0] * 0.7 + (float) color1[0] * 0.3; - color1[1] = (float) color2[1] * 0.7 + (float) color1[1] * 0.3; - color1[2] = (float) color2[2] * 0.7 + (float) color1[2] * 0.3; - } - // - if (x1 == coords1[1][0] && - y1 == coords1[1][1]) - break; - x1 += xinc1; - y1 += yinc1; - x2 += xinc2; - y2 += yinc2; - if (x2 < ds2->lightmapX) - x2 = ds2->lightmapX; - if (x2 >= ds2->lightmapX + ds2->lightmapWidth) - x2 = ds2->lightmapX + ds2->lightmapWidth-1; - if (y2 < ds2->lightmapY) - y2 = ds2->lightmapY; - if (y2 >= ds2->lightmapY + ds2->lightmapHeight) - y2 = ds2->lightmapY + ds2->lightmapHeight-1; - } - } - } - } -} - -/* -============= -VL_FixLightmapEdges -============= -*/ -void VL_FixLightmapEdges(void) -{ - int i, j, x, y, k, foundvalue, height, width, index; - int pos, top, bottom; - dsurface_t *ds; - lsurfaceTest_t *test; - float color[3]; - float *ptr; - byte filled[(LIGHTMAP_SIZE+1) * (LIGHTMAP_SIZE+1) / 8]; - float lightmap_edge_epsilon; - - lightmap_edge_epsilon = 0.1 * samplesize; - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - ds = &drawSurfaces[ i ]; - - if ( ds->lightmapNum < 0 ) - continue; - if (ds->surfaceType == MST_PATCH) - { - height = ds->lightmapHeight - 1; - width = ds->lightmapWidth - 1; - } - else - { - height = ds->lightmapHeight; - width = ds->lightmapWidth; - } - memset(filled, 0, sizeof(filled)); -// printf("\n"); - for (x = 0; x < width; x++) - { - for (y = 0; y < height; y++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (lightmappixelarea[k] > lightmap_edge_epsilon) - { - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - filled[index >> 3] |= 1 << (index & 7); -// printf("*"); - } -// else -// printf("_"); - } -// printf("\n"); - } - for (y = 0; y < height; y++) - { - pos = -2; - for (x = 0; x < width; x++) - { - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (pos == -2) - { - if (filled[index >> 3] & (1 << (index & 7))) - pos = -1; - } - else if (pos == -1) - { - if (!(filled[index >> 3] & (1 << (index & 7)))) - pos = x - 1; - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - bottom = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + pos; - top = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - for (j = 0; j < (x - pos + 1) / 2; j++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + pos + j + 1; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + pos + j + 1; - filled[index >> 3] |= 1 << (index & 7); - (lightFloats + k*3)[0] = (lightFloats + top*3)[0]; - (lightFloats + k*3)[1] = (lightFloats + top*3)[1]; - (lightFloats + k*3)[2] = (lightFloats + top*3)[2]; - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x - j - 1; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x - j - 1; - filled[index >> 3] |= 1 << (index & 7); - (lightFloats + k*3)[0] = (lightFloats + bottom*3)[0]; - (lightFloats + k*3)[1] = (lightFloats + bottom*3)[1]; - (lightFloats + k*3)[2] = (lightFloats + bottom*3)[2]; - } - pos = -1; - } - } - } - } - for (x = 0; x < width; x++) - { - pos = -2; - for (y = 0; y < height; y++) - { - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (pos == -2) - { - if (filled[index >> 3] & (1 << (index & 7))) - pos = -1; - } - else if (pos == -1) - { - if (!(filled[index >> 3] & (1 << (index & 7)))) - pos = y - 1; - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - bottom = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + pos) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - top = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - for (j = 0; j < (y - pos + 1) / 2; j++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + pos + j + 1) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + pos + j + 1) * LIGHTMAP_WIDTH + ds->lightmapX + x; - filled[index >> 3] |= 1 << (index & 7); - (lightFloats + k*3)[0] = (lightFloats + top*3)[0]; - (lightFloats + k*3)[1] = (lightFloats + top*3)[1]; - (lightFloats + k*3)[2] = (lightFloats + top*3)[2]; - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y - j - 1) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + y - j - 1) * LIGHTMAP_WIDTH + ds->lightmapX + x; - filled[index >> 3] |= 1 << (index & 7); - (lightFloats + k*3)[0] = (lightFloats + bottom*3)[0]; - (lightFloats + k*3)[1] = (lightFloats + bottom*3)[1]; - (lightFloats + k*3)[2] = (lightFloats + bottom*3)[2]; - } - pos = -1; - } - } - } - } - for (y = 0; y < height; y++) - { - foundvalue = qfalse; - for (x = 0; x < width; x++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (foundvalue) - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - } - else - { - ptr = lightFloats + k*3; - ptr[0] = color[0]; - ptr[1] = color[1]; - ptr[2] = color[2]; - filled[index >> 3] |= 1 << (index & 7); - } - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - foundvalue = qtrue; - } - } - } - foundvalue = qfalse; - for (x = width-1; x >= 0; x--) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (foundvalue) - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - } - else - { - ptr = lightFloats + k*3; - ptr[0] = color[0]; - ptr[1] = color[1]; - ptr[2] = color[2]; - filled[index >> 3] |= 1 << (index & 7); - } - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - foundvalue = qtrue; - } - } - } - } - for (x = 0; x < width; x++) - { - foundvalue = qfalse; - for (y = 0; y < height; y++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (foundvalue) - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - } - else - { - ptr = lightFloats + k*3; - ptr[0] = color[0]; - ptr[1] = color[1]; - ptr[2] = color[2]; - filled[index >> 3] |= 1 << (index & 7); - } - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - foundvalue = qtrue; - } - } - } - foundvalue = qfalse; - for (y = height-1; y >= 0; y--) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (foundvalue) - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - } - else - { - ptr = lightFloats + k*3; - ptr[0] = color[0]; - ptr[1] = color[1]; - ptr[2] = color[2]; - filled[index >> 3] |= 1 << (index & 7); - } - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - foundvalue = qtrue; - } - } - } - } - if (ds->surfaceType == MST_PATCH) - { - x = ds->lightmapWidth-1; - for (y = 0; y < ds->lightmapHeight; y++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = (lightFloats + (k-1)*3)[0]; - ptr[1] = (lightFloats + (k-1)*3)[1]; - ptr[2] = (lightFloats + (k-1)*3)[2]; - } - y = ds->lightmapHeight-1; - for (x = 0; x < ds->lightmapWidth; x++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[0]; - ptr[1] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[1]; - ptr[2] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[2]; - } - } - /* - //colored debug edges - if (ds->surfaceType == MST_PATCH) - { - x = ds->lightmapWidth-1; - for (y = 0; y < ds->lightmapHeight; y++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = 255; - ptr[1] = 0; - ptr[2] = 0; - } - y = ds->lightmapHeight-1; - for (x = 0; x < ds->lightmapWidth; x++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = 0; - ptr[1] = 255; - ptr[2] = 0; - } - } - //*/ - } - // - VL_SmoothenLightmapEdges(); -} - -/* -============= -VL_ShiftPatchLightmaps -============= -*/ -void VL_ShiftPatchLightmaps(void) -{ - int i, j, x, y, k; - drawVert_t *verts; - dsurface_t *ds; - lsurfaceTest_t *test; - float *ptr; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - ds = &drawSurfaces[ i ]; - - if ( ds->lightmapNum < 0 ) - continue; - if (ds->surfaceType != MST_PATCH) - continue; - for (x = ds->lightmapWidth; x > 0; x--) - { - for (y = 0; y <= ds->lightmapHeight; y++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = (lightFloats + (k-1)*3)[0]; - ptr[1] = (lightFloats + (k-1)*3)[1]; - ptr[2] = (lightFloats + (k-1)*3)[2]; - } - } - for (y = ds->lightmapHeight; y > 0; y--) - { - for (x = 0; x <= ds->lightmapWidth; x++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[0]; - ptr[1] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[1]; - ptr[2] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[2]; - } - } - verts = &drawVerts[ ds->firstVert ]; - for ( j = 0 ; j < ds->patchHeight * ds->patchWidth; j++ ) - { - verts[j].lightmap[0] += 0.5 / LIGHTMAP_WIDTH; - verts[j].lightmap[1] += 0.5 / LIGHTMAP_HEIGHT; - } - ds->lightmapHeight++; - ds->lightmapWidth++; - } -} - -/* -============= -VL_StoreLightmap -============= -*/ -void VL_StoreLightmap(void) -{ - int i, x, y, k; - dsurface_t *ds; - lsurfaceTest_t *test; - float *src; - byte *dst; - - _printf("storing lightmaps...\n"); - //fix lightmap edges before storing them - VL_FixLightmapEdges(); - // -#ifdef LIGHTMAP_PATCHSHIFT - VL_ShiftPatchLightmaps(); -#endif - // - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - ds = &drawSurfaces[ i ]; - - if ( ds->lightmapNum < 0 ) - continue; - - for (y = 0; y < ds->lightmapHeight; y++) - { - for (x = 0; x < ds->lightmapWidth; x++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - VectorAdd((lightFloats + k*3), lightAmbientColor, (lightFloats + k*3)); - src = &lightFloats[k*3]; - dst = lightBytes + k*3; - ColorToBytes(src, dst); - } - } - } -} - -/* -============= -PointInLeafnum -============= -*/ -int PointInLeafnum(vec3_t point) -{ - int nodenum; - vec_t dist; - dnode_t *node; - dplane_t *plane; - - nodenum = 0; - while (nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - dist = DotProduct (point, plane->normal) - plane->dist; - if (dist > 0) - nodenum = node->children[0]; - else - nodenum = node->children[1]; - } - - return -nodenum - 1; -} - -/* -============= -VL_PointInLeafnum_r -============= -*/ -int VL_PointInLeafnum_r(vec3_t point, int nodenum) -{ - int leafnum; - vec_t dist; - dnode_t *node; - dplane_t *plane; - - while (nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - dist = DotProduct (point, plane->normal) - plane->dist; - if (dist > 0.1) - { - nodenum = node->children[0]; - } - else if (dist < -0.1) - { - nodenum = node->children[1]; - } - else - { - leafnum = VL_PointInLeafnum_r(point, node->children[0]); - if (dleafs[leafnum].cluster != -1) - return leafnum; - nodenum = node->children[1]; - } - } - - leafnum = -nodenum - 1; - return leafnum; -} - -/* -============= -VL_PointInLeafnum -============= -*/ -int VL_PointInLeafnum(vec3_t point) -{ - return VL_PointInLeafnum_r(point, 0); -} - -/* -============= -VL_LightLeafnum -============= -*/ -int VL_LightLeafnum(vec3_t point) -{ - /* - int leafnum; - dleaf_t *leaf; - float x, y, z; - vec3_t test; - - leafnum = VL_PointInLeafnum(point); - leaf = &dleafs[leafnum]; - if (leaf->cluster != -1) - return leafnum; - for (z = 1; z >= -1; z -= 1) - { - for (x = 1; x >= -1; x -= 1) - { - for (y = 1; y >= -1; y -= 1) - { - VectorCopy(point, test); - test[0] += x; - test[1] += y; - test[2] += z; - leafnum = VL_PointInLeafnum(test); - leaf = &dleafs[leafnum]; - if (leaf->cluster != -1) - { - VectorCopy(test, point); - return leafnum; - } - } - } - } - return leafnum; - */ - return VL_PointInLeafnum(point); -} - -//#define LIGHTPOLYS - -#ifdef LIGHTPOLYS - -winding_t *lightwindings[MAX_MAP_DRAW_SURFS]; -int numlightwindings; - -/* -============= -VL_DrawLightWindings -============= -*/ -void VL_DrawLightWindings(void) -{ - int i; - for (i = 0; i < numlightwindings; i++) - { -#ifdef DEBUGNET - DebugNet_DrawWinding(lightwindings[i], 1); -#endif - } -} - -/* -============= -VL_LightSurfaceWithVolume -============= -*/ -void VL_LightSurfaceWithVolume(int surfaceNum, int facetNum, vlight_t *light, lightvolume_t *volume) -{ - winding_t *w; - lsurfaceTest_t *test; - lFacet_t *facet; - int i; - - test = lsurfaceTest[ surfaceNum ]; - facet = &test->facets[ facetNum ]; - - // - w = (winding_t *) malloc(sizeof(winding_t)); - memcpy(w->points, facet->points, sizeof(vec3_t) * facet->numpoints); - w->numpoints = facet->numpoints; - - for (i = 0; i < volume->numplanes; i++) - { - //if totally on the back - if (VL_ChopWinding(w, &volume->planes[i], 0.01) == SIDE_BACK) - return; - } - lightwindings[numlightwindings] = w; - numlightwindings++; - if (numlightwindings >= MAX_MAP_DRAW_SURFS) - Error("MAX_LIGHTWINDINGS"); -} - -#else - -/* -============= -VL_LightSurfaceWithVolume -============= -*/ -/* -int VL_PointInsideLightVolume(vec3_t point, lightvolume_t *volume) -{ - int i; - float d; - - for (i = 0; i < volume->numplanes; i++) - { - d = DotProduct(volume->planes[i].normal, point) - volume->planes[i].dist; - if (d < 0) return qfalse; - } - return qtrue; -} - -void VL_LightSurfaceWithVolume( int surfaceNum, int facetNum, vlight_t *light, lightvolume_t *volume ) -{ - dsurface_t *ds; - int i, j, k; - int numPositions; - vec3_t base, normal, color; - int sampleWidth, sampleHeight; - vec3_t lightmapOrigin, lightmapVecs[2], dir; - unsigned char *ptr; - float add, dist, angle; - mesh_t * mesh; - - ds = &drawSurfaces[surfaceNum]; - - // vertex-lit triangle model - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) { - return; - } - - if ( ds->lightmapNum < 0 ) { - return; // doesn't need lighting - } - - if ( ds->surfaceType == MST_PATCH ) { - mesh = lsurfaceTest[surfaceNum]->detailMesh; - } else { - VectorCopy( ds->lightmapVecs[2], normal ); - - VectorCopy( ds->lightmapOrigin, lightmapOrigin ); - VectorCopy( ds->lightmapVecs[0], lightmapVecs[0] ); - VectorCopy( ds->lightmapVecs[1], lightmapVecs[1] ); - } - - sampleWidth = ds->lightmapWidth; - sampleHeight = ds->lightmapHeight; - - //calculate lightmap - for ( i = 0 ; i < sampleWidth; i++ ) { - for ( j = 0 ; j < sampleHeight; j++ ) { - - if ( ds->patchWidth ) { - numPositions = 9; - VectorCopy( mesh->verts[j*mesh->width+i].normal, normal ); - // VectorNormalize( normal, normal ); - // push off of the curve a bit - VectorMA( mesh->verts[j*mesh->width+i].xyz, 1, normal, base ); - -// MakeNormalVectors( normal, lightmapVecs[0], lightmapVecs[1] ); - } else { - numPositions = 9; - for ( k = 0 ; k < 3 ; k++ ) { - base[k] = lightmapOrigin[k] + normal[k] - + ((float) i) * lightmapVecs[0][k] - + ((float) j) * lightmapVecs[1][k]; - } - } - VectorAdd( base, surfaceOrigin[ surfaceNum ], base ); - - VectorSubtract(base, light->origin, dir); - dist = VectorNormalize(dir, dir); - if ( dist < 16 ) { - dist = 16; - } - angle = 1;//DotProduct( normal, dir ); //1; - if (angle > 1) - angle = 1; - if ( light->atten_disttype == LDAT_LINEAR ) { - add = angle * light->photons * lightLinearScale - dist; - if ( add < 0 ) { - add = 0; - } - } else { - add = light->photons / ( dist * dist ) * angle; - } - if (add <= 1.0) - continue; - - if (VL_PointInsideLightVolume(base, volume)) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + j) - * LIGHTMAP_WIDTH + ds->lightmapX + i; - ptr = lightBytes + k*3; - color[0] = (float) ptr[0] + add * light->color[0]; - color[1] = (float) ptr[1] + add * light->color[1]; - color[2] = (float) ptr[2] + add * light->color[2]; - ColorToBytes(color, ptr); - } - } - } -} -*/ - -/* -============= -VL_GetFilter - -FIXME: don't use a lightmap pixel origin but use the four corner points - to map part of a translucent surface onto the lightmap pixel -============= -*/ -void VL_GetFilter(vlight_t *light, lightvolume_t *volume, vec3_t lmp, vec3_t filter) -{ - lFacet_t *facet; - lsurfaceTest_t *test; - float d, d1, d2, frac, s, t, ns; - int i, j, is, it, b; - int x, y, u, v, numsamples, radius, color[4], largest; - byte *image; - vec3_t point, origin, total; - - VectorSet(filter, 1, 1, 1); - - if (noalphashading) - return; - - if (volume->numtransFacets <= 0) - return; - - if (light->type == LIGHT_SURFACEDIRECTED) - { - // project the light map pixel origin onto the area light source plane - d = DotProduct(lmp, light->normal) - DotProduct(light->normal, light->w.points[0]); - VectorMA(lmp, -d, light->normal, origin); - } - else - { - VectorCopy(light->origin, origin); - } - for (i = 0; i < volume->numtransFacets; i++) - { - test = lsurfaceTest[ volume->transSurfaces[i] ]; - facet = &test->facets[ volume->transFacets[i] ]; - // if this surface does not cast an alpha shadow - if ( !(test->shader->surfaceFlags & SURF_ALPHASHADOW) ) - continue; - // if there are no texture pixel available - if ( !test->shader->pixels ) { - continue; - } - // - d1 = DotProduct( origin, facet->plane.normal) - facet->plane.dist; - d2 = DotProduct( lmp, facet->plane.normal ) - facet->plane.dist; - // this should never happen because the light volume went through the facet - if ( ( d1 < 0 ) == ( d2 < 0 ) ) { - continue; - } - // calculate the crossing point - frac = d1 / ( d1 - d2 ); - - for ( j = 0 ; j < 3 ; j++ ) { - point[j] = origin[j] + frac * ( lmp[j] - origin[j] ); - } - - s = DotProduct( point, facet->textureMatrix[0] ) + facet->textureMatrix[0][3]; - t = DotProduct( point, facet->textureMatrix[1] ) + facet->textureMatrix[1][3]; - if (s < 0) - s = 0; - if (t < 0) - t = 0; - - s = s - floor( s ); - t = t - floor( t ); - - is = s * test->shader->width; - it = t * test->shader->height; - - //if old style alpha shading - if (nocolorshading) { - image = test->shader->pixels + 4 * ( it * test->shader->width + is ); - - // alpha filter - b = image[3]; - - // alpha test makes this a binary option - b = b < 128 ? 0 : 255; - - filter[0] = filter[0] * (255-b) / 255; - filter[1] = filter[1] * (255-b) / 255; - filter[2] = filter[2] * (255-b) / 255; - } - else { - VectorClear(total); - numsamples = 0; - radius = 2; - for ( u = -radius; u <= radius; u++ ) - { - x = is + u; - if ( x < 0 || x >= test->shader->width) - continue; - for ( v = -radius; v <= radius; v++ ) - { - y = it + v; - if ( y < 0 || y >= test->shader->height) - continue; - - image = test->shader->pixels + 4 * ( y * test->shader->width + x ); - color[0] = image[0]; - color[1] = image[1]; - color[2] = image[2]; - largest = 0; - for (j = 0; j < 3; j++) - if (image[j] > largest) - largest = image[j]; - if (largest <= 0 || image[3] == 0) { - color[0] = 255; - color[1] = 255; - color[2] = 255; - largest = 255; - } - total[0] += ((float) color[0]/largest) * (255-image[3]) / 255.0; - total[1] += ((float) color[1]/largest) * (255-image[3]) / 255.0; - total[2] += ((float) color[2]/largest) * (255-image[3]) / 255.0; - numsamples++; - } - } - ns = numsamples; - // - filter[0] *= total[0] / ns; - filter[1] *= total[1] / ns; - filter[2] *= total[2] / ns; - } - } -} - -/* -============= -VL_LightSurfaceWithVolume -============= -*/ -void VL_LightSurfaceWithVolume( int surfaceNum, int facetNum, vlight_t *light, lightvolume_t *volume ) -{ - int i; - dsurface_t *ds; - lFacet_t *facet; - lsurfaceTest_t *test; - winding_t w; - vec3_t base, dir, delta, normal, filter, origin; - int min_x[LIGHTMAP_SIZE+2], max_x[LIGHTMAP_SIZE+2]; - int min_y, max_y, k, x, y, n; - float *color, distscale; - float d, add, angle, dist, area, insidearea, coords[MAX_POINTS_ON_WINDING+1][2]; - mesh_t *mesh; - byte polygonedges[(LIGHTMAP_SIZE+1) * (LIGHTMAP_SIZE+1) / 8]; - - - ds = &drawSurfaces[surfaceNum]; - - // vertex-lit triangle model - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) { - return; - } - - if ( ds->lightmapNum < 0 ) { - return; // doesn't need lighting - } - - test = lsurfaceTest[ surfaceNum ]; - facet = &test->facets[ facetNum ]; - - if (defaulttracelight && !test->always_vlight) - return; - if (test->always_tracelight) - return; - - memcpy(w.points, facet->points, sizeof(vec3_t) * facet->numpoints); - w.numpoints = facet->numpoints; - - for (i = 0; i < volume->numplanes; i++) - { - //if totally on the back - if (VL_ChopWinding(&w, &volume->planes[i], 0.01) == SIDE_BACK) - return; - } - - // only one thread at a time may write to the lightmap of this surface - MutexLock(test->mutex); - - test->numvolumes++; - - if (ds->surfaceType == MST_PATCH) - { - // FIXME: reduce size and don't mark all as edge - min_y = ds->lightmapY + facet->y; - max_y = ds->lightmapY + facet->y + facet->height - 1; - for (y = min_y; y <= max_y; y++) - { - min_x[y] = ds->lightmapX + facet->x; - max_x[y] = ds->lightmapX + facet->x + facet->width - 1; - for (x = min_x[y]; x <= max_x[y]; x++) - { - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - } - } - } - else - { - for (i = 0; i < w.numpoints; i++) - { - float s, t; - - if (i >= MAX_POINTS_ON_WINDING) - _printf("coords overflow\n"); - if (ds->surfaceType != MST_PATCH) - { - VectorSubtract(w.points[i], facet->mins, delta); - s = DotProduct( delta, facet->lightmapMatrix[0] ) + ds->lightmapX + 0.5; - t = DotProduct( delta, facet->lightmapMatrix[1] ) + ds->lightmapY + 0.5; - if (s >= LIGHTMAP_SIZE) - s = LIGHTMAP_SIZE - 0.5; - if (s < 0) - s = 0; - if (t >= LIGHTMAP_SIZE) - t = LIGHTMAP_SIZE - 0.5; - if (t < 0) - t = 0; - coords[i][0] = s; - coords[i][1] = t; - } - else - { - s = DotProduct( w.points[i], facet->lightmapMatrix[0] ) + facet->lightmapMatrix[0][3]; - t = DotProduct( w.points[i], facet->lightmapMatrix[1] ) + facet->lightmapMatrix[1][3]; - - s = s - floor( s ); - t = t - floor( t ); - - coords[i][0] = ds->lightmapX + s * LIGHTMAP_SIZE;// + 0.5; - coords[i][1] = ds->lightmapY + t * LIGHTMAP_SIZE;// + 0.5; - - if (coords[i][0] >= LIGHTMAP_SIZE) - coords[i][0] -= LIGHTMAP_SIZE; - if (coords[i][1] >= LIGHTMAP_SIZE) - coords[i][1] -= LIGHTMAP_SIZE; - if (coords[i][0] < ds->lightmapX) - coords[i][0] = ds->lightmapX; - if (coords[i][1] < ds->lightmapY) - coords[i][1] = ds->lightmapY; - } - x = coords[i][0]; - y = coords[i][1]; - if (x < ds->lightmapX || x >= LIGHTMAP_SIZE) - _printf("VL_LightSurfaceWithVolume: x outside lightmap\n"); - if (y < ds->lightmapY || y >= LIGHTMAP_SIZE) - _printf("VL_LightSurfaceWithVolume: y outside lightmap\n"); - } - coords[i][0] = coords[0][0]; - coords[i][1] = coords[0][1]; - - // - min_y = LIGHTMAP_SIZE; - max_y = 0; - for (i = 0; i < LIGHTMAP_SIZE; i++) - { - min_x[i] = LIGHTMAP_SIZE; - max_x[i] = 0; - } - memset(polygonedges, 0, sizeof(polygonedges)); - // scan convert the polygon onto the lightmap - // for each edge it marks *every* lightmap pixel the edge goes through - // so no brasenham and no scan conversion used for texture mapping but - // more something like ray casting - // this is necesary because we need all lightmap pixels totally or partly - // inside the light volume. these lightmap pixels are only lit for the part - // that they are inside the light volume. - for (i = 0; i < w.numpoints; i++) - { - float xf, yf, dx, dy, xstep, ystep, xfrac, yfrac; - int xinc, yinc; - - xf = coords[i][0]; - yf = coords[i][1]; - dx = coords[i+1][0] - xf; - dy = coords[i+1][1] - yf; - // - x = (int) xf; - y = (int) yf; - // - if (y < min_y) - min_y = y; - if (y > max_y) - max_y = y; - // - if (fabs(dx) > fabs(dy)) - { - if (dx > 0) - { - // y fraction at integer x below fractional x - yfrac = yf + (floor(xf) - xf) * dy / dx; - xinc = 1; - } - else if (dx < 0) - { - // y fraction at integer x above fractional x - yfrac = yf + (floor(xf) + 1 - xf) * dy / dx; - xinc = -1; - } - else - { - yfrac = yf; - xinc = 0; - } - // step in y direction per 1 unit in x direction - if (dx) - ystep = dy / fabs(dx); - else - ystep = 0; - while(1) - { - if (x < ds->lightmapX || x >= LIGHTMAP_SIZE) - _printf("VL_LightSurfaceWithVolume: x outside lightmap\n"); - if (y < ds->lightmapY || y >= LIGHTMAP_SIZE) - _printf("VL_LightSurfaceWithVolume: y outside lightmap\n"); - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - if (x == (int) coords[i+1][0]) - break; - yfrac += ystep; - if (dy > 0) - { - if (yfrac > (float) y + 1) - { - y += 1; - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - } - } - else - { - if (yfrac < (float) y) - { - y -= 1; - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - } - } - x += xinc; - } - } - else - { - if (dy > 0) - { - //x fraction at integer y below fractional y - xfrac = xf + (floor(yf) - yf) * dx / dy; - yinc = 1; - } - else if (dy < 0) - { - //x fraction at integer y above fractional y - xfrac = xf + (floor(yf) + 1 - yf) * dx / dy; - yinc = -1; - } - else - { - xfrac = xf; - yinc = 0; - } - // step in x direction per 1 unit in y direction - if (dy) - xstep = dx / fabs(dy); - else - xstep = 0; - while(1) - { - if (x < ds->lightmapX || x >= LIGHTMAP_SIZE) - _printf("VL_LightSurfaceWithVolume: x outside lightmap\n"); - if (y < ds->lightmapY || y >= LIGHTMAP_SIZE) - _printf("VL_LightSurfaceWithVolume: y outside lightmap\n"); - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - if (y == (int) coords[i+1][1]) - break; - xfrac += xstep; - if (dx > 0) - { - if (xfrac > (float) x + 1) - { - x += 1; - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - } - } - else - { - if (xfrac < (float) x) - { - x -= 1; - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - } - } - y += yinc; - } - } - } - } - // map light onto the lightmap - for (y = min_y; y <= max_y; y++) - { - for (x = min_x[y]; x <= max_x[y]; x++) - { - if (ds->surfaceType == MST_PATCH) - { - mesh = test->detailMesh; - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, base); - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].normal, normal); - //VectorCopy(facet->plane.normal, normal); - } - else - { - VectorMA(ds->lightmapOrigin, (float) x - ds->lightmapX, ds->lightmapVecs[0], base); - VectorMA(base, (float) y - ds->lightmapY, ds->lightmapVecs[1], base); - VectorCopy(facet->plane.normal, normal); - } - if (light->type == LIGHT_POINTSPOT) - { - float distByNormal; - vec3_t pointAtDist; - float radiusAtDist; - float sampleRadius; - vec3_t distToSample; - float coneScale; - - VectorSubtract( light->origin, base, dir ); - - distByNormal = -DotProduct( dir, light->normal ); - if ( distByNormal < 0 ) { - continue; - } - VectorMA( light->origin, distByNormal, light->normal, pointAtDist ); - radiusAtDist = light->radiusByDist * distByNormal; - - VectorSubtract( base, pointAtDist, distToSample ); - sampleRadius = VectorLength( distToSample ); - - if ( sampleRadius >= radiusAtDist ) { - continue; // outside the cone - } - if ( sampleRadius <= radiusAtDist - 32 ) { - coneScale = 1.0; // fully inside - } else { - coneScale = ( radiusAtDist - sampleRadius ) / 32.0; - } - - dist = VectorNormalize( dir, dir ); - // clamp the distance to prevent super hot spots - if ( dist < 16 ) { - dist = 16; - } - angle = DotProduct( normal, dir ); - if (angle > 1) - angle = 1; - if (angle > 0) { - if ( light->atten_angletype == LAAT_QUADRATIC ) { - angle = 1 - angle; - angle *= angle; - angle = 1 - angle; - } - else if ( light->atten_angletype == LAAT_DOUBLEQUADRATIC ) { - angle = 1 - angle; - angle *= angle * angle; - angle = 1 - angle; - } - } - if (light->atten_anglescale > 0) { - angle /= light->atten_anglescale; - if (angle > 1) - angle = 1; - } - if (light->atten_distscale > 0) { - distscale = light->atten_distscale; - } - else { - distscale = 1; - } - // - if ( light->atten_disttype == LDAT_NOSCALE ) { - add = angle * coneScale; - } - else if ( light->atten_disttype == LDAT_LINEAR ) { - add = angle * light->photons * lightLinearScale * coneScale - dist * distscale; - if ( add < 0 ) { - add = 0; - } - } - else { - add = light->photons / ( dist * dist * distscale) * angle * coneScale; - } - if (add <= 1.0) - continue; - } - else if (light->type == LIGHT_POINTFAKESURFACE) - { - // calculate the contribution - add = PointToPolygonFormFactor( base, normal, &light->w ); - if ( add <= 0 ) { - if ( light->twosided ) { - add = -add; - } else { - continue; - } - } - } - else if (light->type == LIGHT_SURFACEDIRECTED) - { - //VectorCopy(light->normal, dir); - //VectorInverse(dir); - // project the light map pixel origin onto the area light source plane - d = DotProduct(base, light->normal) - DotProduct(light->normal, light->w.points[0]); - VectorMA(base, -d, light->normal, origin); - VectorSubtract(origin, base, dir); - dist = VectorNormalize(dir, dir); - if ( dist < 16 ) { - dist = 16; - } - // - angle = DotProduct( normal, dir ); - if (angle > 1) - angle = 1; - if (angle > 0) { - if ( light->atten_angletype == LAAT_QUADRATIC ) { - angle = 1 - angle; - angle *= angle; - angle = 1 - angle; - } - else if ( light->atten_angletype == LAAT_DOUBLEQUADRATIC ) { - angle = 1 - angle; - angle *= angle * angle; - angle = 1 - angle; - } - } - if (light->atten_anglescale > 0) { - angle /= light->atten_anglescale; - if (angle > 1) - angle = 1; - } - if (light->atten_distscale > 0) { - distscale = light->atten_distscale; - } - else { - distscale = 1; - } - if ( light->atten_disttype == LDAT_NOSCALE ) { - add = angle; - } - else if ( light->atten_disttype == LDAT_LINEAR ) { - add = angle * light->photons * lightLinearScale - dist * distscale; - if ( add < 0 ) { - add = 0; - } - } else { //default quadratic - add = light->photons / ( dist * dist * distscale) * angle; - } - if (add <= 0) - continue; - } - else //normal radial point light - { - VectorSubtract(light->origin, base, dir); - dist = VectorNormalize(dir, dir); - if ( dist < 16 ) { - dist = 16; - } - angle = DotProduct( normal, dir ); - if (angle > 1) - angle = 1; - if (angle > 0) { - if ( light->atten_angletype == LAAT_QUADRATIC ) { - angle = 1 - angle; - angle *= angle; - angle = 1 - angle; - } - else if ( light->atten_angletype == LAAT_DOUBLEQUADRATIC ) { - angle = 1 - angle; - angle *= angle * angle; - angle = 1 - angle; - } - } - if (light->atten_anglescale > 0) { - angle /= light->atten_anglescale; - if (angle > 1) - angle = 1; - } - if (light->atten_distscale > 0) { - distscale = light->atten_distscale; - } - else { - distscale = 1; - } - if ( light->atten_disttype == LDAT_NOSCALE ) { - add = angle; - } - else if ( light->atten_disttype == LDAT_LINEAR ) { - add = angle * light->photons * lightLinearScale - dist * distscale; - if ( add < 0 ) { - add = 0; - } - } else { - add = light->photons / ( dist * dist * distscale) * angle; - } - if (add <= 1.0) - continue; - } - // - k = (ds->lightmapNum * LIGHTMAP_HEIGHT + y) * LIGHTMAP_WIDTH + x; - //if on one of the edges - n = y * LIGHTMAP_SIZE + x; - if ((polygonedges[n >> 3] & (1 << (n & 7)) )) - { - // multiply 'add' by the relative area being lit of the total visible lightmap pixel area - // - // first create a winding for the lightmap pixel - if (ds->surfaceType == MST_PATCH) - { - mesh = test->detailMesh; - if (y-ds->lightmapY >= mesh->height-1) - _printf("y outside mesh\n"); - if (x-ds->lightmapX >= mesh->width-1) - _printf("x outside mesh\n"); - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[0]); - VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[1]); - VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[2]); - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[3]); - w.numpoints = 4; - } - else - { - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT - ds->lightmapX, ds->lightmapVecs[0], w.points[0]); - VectorMA(w.points[0], (float) y - LIGHTMAP_PIXELSHIFT - ds->lightmapY, ds->lightmapVecs[1], w.points[0]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT - ds->lightmapX, ds->lightmapVecs[0], w.points[1]); - VectorMA(w.points[1], (float) y - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapY, ds->lightmapVecs[1], w.points[1]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapX, ds->lightmapVecs[0], w.points[2]); - VectorMA(w.points[2], (float) y - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapY, ds->lightmapVecs[1], w.points[2]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapX, ds->lightmapVecs[0], w.points[3]); - VectorMA(w.points[3], (float) y - LIGHTMAP_PIXELSHIFT - ds->lightmapY, ds->lightmapVecs[1], w.points[3]); - w.numpoints = 4; - } - // - // take the visible area of the lightmap pixel into account - // - //area = WindingArea(&w); - area = lightmappixelarea[k]; - if (area <= 0) - continue; - // chop the lightmap pixel winding with the light volume - for (i = 0; i < volume->numplanes; i++) - { - //if totally on the back - if (VL_ChopWinding(&w, &volume->planes[i], 0) == SIDE_BACK) - break; - } - // if the lightmap pixel is partly inside the light volume - if (i >= volume->numplanes) - { - insidearea = WindingArea(&w); - if (insidearea <= 0) - i = 0; - add = add * insidearea / area; - } - else - { - //DebugNet_DrawWinding(&w, 2); - continue; // this shouldn't happen - } - } - // get the light filter from all the translucent surfaces the light volume went through - VL_GetFilter(light, volume, base, filter); - // - color = &lightFloats[k*3]; - color[0] += add * light->color[0] * filter[0]; - color[1] += add * light->color[1] * filter[1]; - color[2] += add * light->color[2] * filter[2]; - } - } - - MutexUnlock(test->mutex); -} - -#endif - -/* -============= -VL_SplitLightVolume -============= -*/ -int VL_SplitLightVolume(lightvolume_t *volume, lightvolume_t *back, plane_t *split, float epsilon) -{ - lightvolume_t f, b; - vec_t dists[128]; - int sides[128]; - int counts[3]; - vec_t dot; - int i, j; - vec_t *p1, *p2; - vec3_t mid; - - counts[0] = counts[1] = counts[2] = 0; - - // determine sides for each point - for (i = 0; i < volume->numplanes; i++) - { - dot = DotProduct (volume->points[i], split->normal); - dot -= split->dist; - dists[i] = dot; - if (dot > epsilon) - sides[i] = SIDE_FRONT; - else if (dot < -epsilon) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - - if (!counts[1]) - return 0; // completely on front side - - if (!counts[0]) - return 1; // completely on back side - - sides[i] = sides[0]; - dists[i] = dists[0]; - - f.numplanes = 0; - b.numplanes = 0; - - for (i = 0; i < volume->numplanes; i++) - { - p1 = volume->points[i]; - - if (f.numplanes >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VL_SplitLightVolume -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return 0; // can't chop -- fall back to original - } - if (b.numplanes >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VL_SplitLightVolume -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return 0; // can't chop -- fall back to original - } - - if (sides[i] == SIDE_ON) - { - VectorCopy(p1, f.points[f.numplanes]); - VectorCopy(p1, b.points[b.numplanes]); - if (sides[i+1] == SIDE_BACK) - { - f.planes[f.numplanes] = *split; - b.planes[b.numplanes] = volume->planes[i]; - } - else if (sides[i+1] == SIDE_FRONT) - { - f.planes[f.numplanes] = volume->planes[i]; - b.planes[b.numplanes] = *split; - VectorInverse(b.planes[b.numplanes].normal); - b.planes[b.numplanes].dist = -b.planes[b.numplanes].dist; - } - else //this shouldn't happen - { - f.planes[f.numplanes] = *split; - b.planes[b.numplanes] = *split; - VectorInverse(b.planes[b.numplanes].normal); - b.planes[b.numplanes].dist = -b.planes[b.numplanes].dist; - } - f.numplanes++; - b.numplanes++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, f.points[f.numplanes]); - f.planes[f.numplanes] = volume->planes[i]; - f.numplanes++; - } - if (sides[i] == SIDE_BACK) - { - VectorCopy (p1, b.points[b.numplanes]); - b.planes[b.numplanes] = volume->planes[i]; - b.numplanes++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - if (f.numplanes >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VL_SplitLightVolume -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return 0; // can't chop -- fall back to original - } - if (b.numplanes >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VL_SplitLightVolume -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return 0; // can't chop -- fall back to original - } - - // generate a split point - p2 = volume->points[(i+1)%volume->numplanes]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (split->normal[j] == 1) - mid[j] = split->dist; - else if (split->normal[j] == -1) - mid[j] = -split->dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, f.points[f.numplanes]); - VectorCopy(mid, b.points[b.numplanes]); - if (sides[i+1] == SIDE_BACK) - { - f.planes[f.numplanes] = *split; - b.planes[b.numplanes] = volume->planes[i]; - } - else - { - f.planes[f.numplanes] = volume->planes[i]; - b.planes[b.numplanes] = *split; - VectorInverse(b.planes[b.numplanes].normal); - b.planes[b.numplanes].dist = -b.planes[b.numplanes].dist; - } - f.numplanes++; - b.numplanes++; - } - memcpy(volume->points, f.points, sizeof(vec3_t) * f.numplanes); - memcpy(volume->planes, f.planes, sizeof(plane_t) * f.numplanes); - volume->numplanes = f.numplanes; - memcpy(back->points, b.points, sizeof(vec3_t) * b.numplanes); - memcpy(back->planes, b.planes, sizeof(plane_t) * b.numplanes); - back->numplanes = b.numplanes; - - return 2; -} - -/* -============= -VL_PlaneForEdgeToWinding -============= -*/ -void VL_PlaneForEdgeToWinding(vec3_t p1, vec3_t p2, winding_t *w, int windingonfront, plane_t *plane) -{ - int i, j; - float length, d; - vec3_t v1, v2; - - VectorSubtract(p2, p1, v1); - for (i = 0; i < w->numpoints; i++) - { - VectorSubtract (w->points[i], p1, v2); - - plane->normal[0] = v1[1]*v2[2] - v1[2]*v2[1]; - plane->normal[1] = v1[2]*v2[0] - v1[0]*v2[2]; - plane->normal[2] = v1[0]*v2[1] - v1[1]*v2[0]; - - // if points don't make a valid plane, skip it - length = plane->normal[0] * plane->normal[0] - + plane->normal[1] * plane->normal[1] - + plane->normal[2] * plane->normal[2]; - - if (length < ON_EPSILON) - continue; - - length = 1/sqrt(length); - - plane->normal[0] *= length; - plane->normal[1] *= length; - plane->normal[2] *= length; - - plane->dist = DotProduct (w->points[i], plane->normal); - // - for (j = 0; j < w->numpoints; j++) - { - if (j == i) - continue; - d = DotProduct(w->points[j], plane->normal) - plane->dist; - if (windingonfront) - { - if (d < -ON_EPSILON) - break; - } - else - { - if (d > ON_EPSILON) - break; - } - } - if (j >= w->numpoints) - return; - } -} - -/* -============= -VL_R_CastLightAtSurface -============= -*/ -void VL_R_FloodLight(vlight_t *light, lightvolume_t *volume, int cluster, int firstportal); - -void VL_R_CastLightAtSurface(vlight_t *light, lightvolume_t *volume) -{ - lsurfaceTest_t *test; - int i, n; - - // light the surface with this volume - VL_LightSurfaceWithVolume(volume->surfaceNum, volume->facetNum, light, volume); - // - test = lsurfaceTest[ volume->surfaceNum ]; - // if this is not a translucent surface - if ( !(test->shader->surfaceFlags & SURF_ALPHASHADOW) && !(test->shader->contents & CONTENTS_TRANSLUCENT)) - return; - // - if (volume->numtransFacets >= MAX_TRANSLUCENTFACETS) - Error("a light valume went through more than %d translucent facets", MAX_TRANSLUCENTFACETS); - //add this translucent surface to the list - volume->transSurfaces[volume->numtransFacets] = volume->surfaceNum; - volume->transFacets[volume->numtransFacets] = volume->facetNum; - volume->numtransFacets++; - //clear the tested facets except the translucent ones - memset(volume->facetTested, 0, sizeof(volume->facetTested)); - for (i = 0; i < volume->numtransFacets; i++) - { - test = lsurfaceTest[ volume->transSurfaces[i] ]; - n = test->facets[volume->transFacets[i]].num; - volume->facetTested[n >> 3] |= 1 << (n & 7); - } - memset(volume->clusterTested, 0, sizeof(volume->clusterTested)); - volume->endplane = volume->farplane; - volume->surfaceNum = -1; - volume->facetNum = 0; - VL_R_FloodLight(light, volume, volume->cluster, 0); - if (volume->surfaceNum >= 0) - { - VL_R_CastLightAtSurface(light, volume); - } -} - -/* -============= -VL_R_SplitLightVolume -============= -*/ -int numvolumes = 0; - -int VL_R_SplitLightVolume(vlight_t *light, lightvolume_t *volume, plane_t *split, int cluster, int firstportal) -{ - lightvolume_t back; - int res; - - // - res = VL_SplitLightVolume(volume, &back, split, 0.1); - // if the volume was split - if (res == 2) - { - memcpy(back.clusterTested, volume->clusterTested, sizeof(back.clusterTested)); - memcpy(back.facetTested, volume->facetTested, sizeof(back.facetTested)); - back.num = numvolumes++; - back.endplane = volume->endplane; - back.surfaceNum = volume->surfaceNum; - back.facetNum = volume->facetNum; - back.type = volume->type; - back.cluster = volume->cluster; - back.farplane = volume->farplane; - if (volume->numtransFacets > 0) - { - memcpy(back.transFacets, volume->transFacets, sizeof(back.transFacets)); - memcpy(back.transSurfaces, volume->transSurfaces, sizeof(back.transSurfaces)); - } - back.numtransFacets = volume->numtransFacets; - // - // flood the volume at the back of the split plane - VL_R_FloodLight(light, &back, cluster, firstportal); - // if the back volume hit a surface - if (back.surfaceNum >= 0) - { - VL_R_CastLightAtSurface(light, &back); - } - } - return res; -} - -/* -============= -VL_R_FloodLight -============= -*/ -void VL_R_FloodLight(vlight_t *light, lightvolume_t *volume, int cluster, int firstportal) -{ - int i, j, k, res, surfaceNum, backfaceculled, testculled; - float d; - winding_t winding, tmpwinding; - lleaf_t *leaf; - lportal_t *p; - lsurfaceTest_t *test; - lFacet_t *facet; - vec3_t dir1, dir2; - plane_t plane; - - // DebugNet_RemoveAllPolys(); - // VL_DrawLightVolume(light, volume); - - // if the first portal is not zero then we've checked all occluders in this leaf already - if (firstportal == 0) - { - // check all potential occluders in this leaf - for (i = 0; i < leafs[cluster].numSurfaces; i++) - { - surfaceNum = clustersurfaces[leafs[cluster].firstSurface + i]; - // - test = lsurfaceTest[ surfaceNum ]; - if ( !test ) - continue; - // - testculled = qfalse; - // use surface as an occluder - for (j = 0; j < test->numFacets; j++) - { - // use each facet as an occluder - facet = &test->facets[j]; - // - // memcpy(winding.points, facet->points, sizeof(vec3_t) * facet->numpoints); - // winding.numpoints = facet->numpoints; - // DebugNet_DrawWinding(&winding, 5); - // - // if the facet was tested already - if ( volume->facetTested[facet->num >> 3] & (1 << (facet->num & 7)) ) - continue; - volume->facetTested[facet->num >> 3] |= 1 << (facet->num & 7); - // backface culling for planar surfaces - backfaceculled = qfalse; - if (!test->patch && !test->trisoup) - { - if (volume->type == VOLUME_NORMAL) - { - // facet backface culling - d = DotProduct(light->origin, facet->plane.normal) - facet->plane.dist; - if (d < 0) - { - // NOTE: this doesn't work too great because of sometimes very bad tesselation - // of surfaces that are supposed to be flat - // FIXME: to work around this problem we should make sure that all facets - // created from planar surfaces use the lightmapVecs normal vector - /* - if ( !test->shader->twoSided ) - { - // skip all other facets of this surface as well because they are in the same plane - for (k = 0; k < test->numFacets; k++) - { - facet = &test->facets[k]; - volume->facetTested[facet->num >> 3] |= 1 << (facet->num & 7); - } - }*/ - backfaceculled = qtrue; - } - } - else - { - // FIXME: if all light source winding points are at the back of the facet - // plane then backfaceculled = qtrue - } - } - else // backface culling per facet for patches and triangle soups - { - if (volume->type == VOLUME_NORMAL) - { - // facet backface culling - d = DotProduct(light->origin, facet->plane.normal) - facet->plane.dist; - if (d < 0) - backfaceculled = qtrue; - } - else - { - // FIXME: if all light source winding points are at the back of the facet - // plane then backfaceculled = qtrue - } - } - /* chopping does this already - // check if this facet is totally or partly in front of the volume end plane - for (k = 0; k < facet->numpoints; k++) - { - d = DotProduct(volume->endplane.normal, facet->points[k]) - volume->endplane.dist; - if (d > ON_EPSILON) - break; - } - // if this facet is outside the light volume - if (k >= facet->numpoints) - continue; - */ - // - if (backfaceculled) - { - // if the facet is not two sided - if ( !nobackfaceculling && !test->shader->twoSided ) - continue; - // flip the winding - for (k = 0; k < facet->numpoints; k++) - VectorCopy(facet->points[k], winding.points[facet->numpoints - k - 1]); - winding.numpoints = facet->numpoints; - } - else - { - memcpy(winding.points, facet->points, sizeof(vec3_t) * facet->numpoints); - winding.numpoints = facet->numpoints; - } - // - if (!testculled) - { - testculled = qtrue; - // fast check if the surface sphere is totally behind the volume end plane - d = DotProduct(volume->endplane.normal, test->origin) - volume->endplane.dist; - if (d < -test->radius) - { - for (k = 0; k < test->numFacets; k++) - { - facet = &test->facets[k]; - volume->facetTested[facet->num >> 3] |= 1 << (facet->num & 7); - } - break; - } - for (k = 0; k < volume->numplanes; k++) - { - d = DotProduct(volume->planes[k].normal, test->origin) - volume->planes[k].dist; - if (d < - test->radius) - { - for (k = 0; k < test->numFacets; k++) - { - facet = &test->facets[k]; - volume->facetTested[facet->num >> 3] |= 1 << (facet->num & 7); - } - break; - } - } - if (k < volume->numplanes) - break; - } - //NOTE: we have to chop the facet winding with the volume end plane because - // the faces in Q3 are not stitched together nicely - res = VL_ChopWinding(&winding, &volume->endplane, 0.01); - // if the facet is on or at the back of the volume end plane - if (res == SIDE_BACK || res == SIDE_ON) - continue; - // check if the facet winding is totally or partly inside the light volume - memcpy(&tmpwinding, &winding, sizeof(winding_t)); - for (k = 0; k < volume->numplanes; k++) - { - res = VL_ChopWinding(&tmpwinding, &volume->planes[k], 0.01); - if (res == SIDE_BACK || res == SIDE_ON) - break; - } - // if no part of the light volume is occluded by this facet - if (k < volume->numplanes) - continue; - // - for (k = 0; k < winding.numpoints; k++) - { - if (volume->type == VOLUME_DIRECTED) - { - VectorSubtract(winding.points[(k+1) % winding.numpoints], winding.points[k], dir1); - CrossProduct(light->normal, dir1, plane.normal); - VectorNormalize(plane.normal, plane.normal); - plane.dist = DotProduct(plane.normal, winding.points[k]); - } - else - { - VectorSubtract(winding.points[(k+1) % winding.numpoints], winding.points[k], dir1); - VectorSubtract(light->origin, winding.points[k], dir2); - CrossProduct(dir1, dir2, plane.normal); - VectorNormalize(plane.normal, plane.normal); - plane.dist = DotProduct(plane.normal, winding.points[k]); - } - res = VL_R_SplitLightVolume(light, volume, &plane, cluster, 0); - if (res == 1) - break; //the facet wasn't really inside the volume - } - if (k >= winding.numpoints) - { - volume->endplane = facet->plane; - if (backfaceculled) - { - VectorInverse(volume->endplane.normal); - volume->endplane.dist = -volume->endplane.dist; - } - volume->surfaceNum = surfaceNum; - volume->facetNum = j; - } - } - } - } - // we've tested all occluders in this cluster - volume->clusterTested[cluster >> 3] |= 1 << (cluster & 7); - // flood light through the portals of the current leaf - leaf = &leafs[cluster]; - for (i = firstportal; i < leaf->numportals; i++) - { - p = leaf->portals[i]; - // - // memcpy(&winding, p->winding, sizeof(winding_t)); - // DebugNet_DrawWinding(&winding, 5); - // if already flooded into the cluster this portal leads to - if ( volume->clusterTested[p->leaf >> 3] & (1 << (p->leaf & 7)) ) - continue; - // - if (volume->type == VOLUME_NORMAL) - { - // portal backface culling - d = DotProduct(light->origin, p->plane.normal) - p->plane.dist; - if (d > 0) // portal plane normal points into neighbour cluster - continue; - } - else - { - // FIXME: if all light source winding points are at the back of this portal - // plane then there's no need to flood through - } - // check if this portal is totally or partly in front of the volume end plane - // fast check with portal sphere - d = DotProduct(volume->endplane.normal, p->origin) - volume->endplane.dist; - if (d < -p->radius) - continue; - for (j = 0; j < p->winding->numpoints; j++) - { - d = DotProduct(volume->endplane.normal, p->winding->points[j]) - volume->endplane.dist; - if (d > -0.01) - break; - } - // if this portal is totally behind the light volume end plane - if (j >= p->winding->numpoints) - continue; - //distance from point light to portal - d = DotProduct(p->plane.normal, light->origin) - p->plane.dist; - // only check if a point light is Not *on* the portal - if (volume->type != VOLUME_NORMAL || fabs(d) > 0.1) - { - // check if the portal is partly or totally inside the light volume - memcpy(&winding, p->winding, sizeof(winding_t)); - for (j = 0; j < volume->numplanes; j++) - { - res = VL_ChopWinding(&winding, &volume->planes[j], 0.01); - if (res == SIDE_BACK || res == SIDE_ON) - break; - } - // if the light volume does not go through this portal at all - if (j < volume->numplanes) - continue; - } - // chop the light volume with the portal - for (k = 0; k < p->winding->numpoints; k++) - { - if (volume->type == VOLUME_DIRECTED) - { - VectorSubtract(p->winding->points[(k+1) % p->winding->numpoints], p->winding->points[k], dir1); - CrossProduct(light->normal, dir1, plane.normal); - VectorNormalize(plane.normal, plane.normal); - plane.dist = DotProduct(plane.normal, p->winding->points[k]); - } - else - { - VectorSubtract(p->winding->points[(k+1) % p->winding->numpoints], p->winding->points[k], dir1); - VectorSubtract(light->origin, p->winding->points[k], dir2); - CrossProduct(dir1, dir2, plane.normal); - VectorNormalize(plane.normal, plane.normal); - plane.dist = DotProduct(plane.normal, p->winding->points[k]); - } - res = VL_R_SplitLightVolume(light, volume, &plane, cluster, i+1); - if (res == 1) - break; //volume didn't really go through the portal - } - // if the light volume went through the portal - if (k >= p->winding->numpoints) - { - // flood through the portal - VL_R_FloodLight(light, volume, p->leaf, 0); - } - } -} - -/* -============= -VL_R_FloodAreaSpotLight -============= -*/ -void VL_FloodAreaSpotLight(vlight_t *light, winding_t *w, int leafnum) -{ -} - -/* -============= -VL_R_SubdivideAreaSpotLight -============= -*/ -void VL_R_SubdivideAreaSpotLight(vlight_t *light, int nodenum, winding_t *w) -{ - int leafnum, res; - dnode_t *node; - dplane_t *plane; - winding_t back; - plane_t split; - - while(nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - - VectorCopy(plane->normal, split.normal); - split.dist = plane->dist; - res = VL_SplitWinding (w, &back, &split, 0.1); - - if (res == SIDE_FRONT) - { - nodenum = node->children[0]; - } - else if (res == SIDE_BACK) - { - nodenum = node->children[1]; - } - else if (res == SIDE_ON) - { - memcpy(&back, w, sizeof(winding_t)); - VL_R_SubdivideAreaSpotLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - else - { - VL_R_SubdivideAreaSpotLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - } - leafnum = -nodenum - 1; - if (dleafs[leafnum].cluster != -1) - { - VL_FloodAreaSpotLight(light, w, leafnum); - } -} - -/* -============= -VL_R_FloodRadialAreaLight -============= -*/ -void VL_FloodRadialAreaLight(vlight_t *light, winding_t *w, int leafnum) -{ -} - -/* -============= -VL_R_SubdivideRadialAreaLight -============= -*/ -void VL_R_SubdivideRadialAreaLight(vlight_t *light, int nodenum, winding_t *w) -{ - int leafnum, res; - dnode_t *node; - dplane_t *plane; - winding_t back; - plane_t split; - - while(nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - - VectorCopy(plane->normal, split.normal); - split.dist = plane->dist; - res = VL_SplitWinding (w, &back, &split, 0.1); - - if (res == SIDE_FRONT) - { - nodenum = node->children[0]; - } - else if (res == SIDE_BACK) - { - nodenum = node->children[1]; - } - else if (res == SIDE_ON) - { - memcpy(&back, w, sizeof(winding_t)); - VL_R_SubdivideRadialAreaLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - else - { - VL_R_SubdivideRadialAreaLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - } - leafnum = -nodenum - 1; - if (dleafs[leafnum].cluster != -1) - { - VL_FloodRadialAreaLight(light, w, leafnum); - } -} - -/* -============= -VL_R_FloodDirectedLight -============= -*/ -void VL_FloodDirectedLight(vlight_t *light, winding_t *w, int leafnum) -{ - int i; - float dist; - lightvolume_t volume; - vec3_t dir; - - if (light->atten_disttype == LDAT_NOSCALE) - { - // light travels without decrease in intensity over distance - dist = MAX_WORLD_COORD; - } - else - { - if ( light->atten_disttype == LDAT_LINEAR ) - dist = light->photons * lightLinearScale; - else - dist = sqrt(light->photons); - } - - memset(&volume, 0, sizeof(lightvolume_t)); - for (i = 0; i < w->numpoints; i++) - { - VectorMA(w->points[i], dist, light->normal, volume.points[i]); - VectorSubtract(w->points[(i+1)%w->numpoints], w->points[i], dir); - CrossProduct(light->normal, dir, volume.planes[i].normal); - VectorNormalize(volume.planes[i].normal, volume.planes[i].normal); - volume.planes[i].dist = DotProduct(volume.planes[i].normal, w->points[i]); - } - volume.numplanes = w->numpoints; - VectorCopy(light->normal, volume.endplane.normal); - VectorInverse(volume.endplane.normal); - volume.endplane.dist = DotProduct(volume.endplane.normal, volume.points[0]); - volume.farplane = volume.endplane; - volume.surfaceNum = -1; - volume.type = VOLUME_DIRECTED; - volume.cluster = dleafs[leafnum].cluster; - VL_R_FloodLight(light, &volume, volume.cluster, 0); - if (volume.surfaceNum >= 0) - { - VL_R_CastLightAtSurface(light, &volume); - } -} - -/* -============= -VL_R_SubdivideDirectedAreaLight -============= -*/ -void VL_R_SubdivideDirectedAreaLight(vlight_t *light, int nodenum, winding_t *w) -{ - int leafnum, res; - dnode_t *node; - dplane_t *plane; - winding_t back; - plane_t split; - - while(nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - - VectorCopy(plane->normal, split.normal); - split.dist = plane->dist; - res = VL_SplitWinding (w, &back, &split, 0.1); - - if (res == SIDE_FRONT) - { - nodenum = node->children[0]; - } - else if (res == SIDE_BACK) - { - nodenum = node->children[1]; - } - else if (res == SIDE_ON) - { - memcpy(&back, w, sizeof(winding_t)); - VL_R_SubdivideDirectedAreaLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - else - { - VL_R_SubdivideDirectedAreaLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - } - leafnum = -nodenum - 1; - if (dleafs[leafnum].cluster != -1) - { - VL_FloodDirectedLight(light, w, leafnum); - } -} - -/* -============= -VL_FloodLight -============= -*/ -void VL_FloodLight(vlight_t *light) -{ - lightvolume_t volume; - dleaf_t *leaf; - int leafnum, i, j, k, dir[2][4] = {{1, 1, -1, -1}, {1, -1, -1, 1}}; - float a, step, dist, radius, windingdist; - vec3_t vec, r, p, temp; - winding_t winding; - - switch(light->type) - { - case LIGHT_POINTRADIAL: - { - // source is a point - // light radiates in all directions - // creates sharp shadows - // - // create 6 volumes shining in the axis directions - // what about: 4 tetrahedrons instead? - // - if ( light->atten_disttype == LDAT_LINEAR ) - dist = light->photons * lightLinearScale; - else - dist = sqrt(light->photons); - //always put the winding at a large distance to avoid epsilon issues - windingdist = MAX_WORLD_COORD; - if (dist > windingdist) - windingdist = dist; - // - leafnum = VL_LightLeafnum(light->origin); - leaf = &dleafs[leafnum]; - if (leaf->cluster == -1) - { - light->insolid = qtrue; - break; - } - // for each axis - for (i = 0; i < 3; i++) - { - // for both directions on the axis - for (j = -1; j <= 1; j += 2) - { - memset(&volume, 0, sizeof(lightvolume_t)); - volume.numplanes = 0; - for (k = 0; k < 4; k ++) - { - volume.points[volume.numplanes][i] = light->origin[i] + j * windingdist; - volume.points[volume.numplanes][(i+1)%3] = light->origin[(i+1)%3] + dir[0][k] * windingdist; - volume.points[volume.numplanes][(i+2)%3] = light->origin[(i+2)%3] + dir[1][k] * windingdist; - volume.numplanes++; - } - if (j >= 0) - { - VectorCopy(volume.points[0], temp); - VectorCopy(volume.points[2], volume.points[0]); - VectorCopy(temp, volume.points[2]); - } - for (k = 0; k < volume.numplanes; k++) - { - VL_PlaneFromPoints(&volume.planes[k], light->origin, volume.points[(k+1)%volume.numplanes], volume.points[k]); - } - VectorCopy(light->origin, temp); - temp[i] += (float) j * dist; - VectorClear(volume.endplane.normal); - volume.endplane.normal[i] = -j; - volume.endplane.dist = DotProduct(volume.endplane.normal, temp); //DotProduct(volume.endplane.normal, volume.points[0]); - volume.farplane = volume.endplane; - volume.cluster = leaf->cluster; - volume.surfaceNum = -1; - volume.type = VOLUME_NORMAL; - // - memset(volume.facetTested, 0, sizeof(volume.facetTested)); - memset(volume.clusterTested, 0, sizeof(volume.clusterTested)); - VL_R_FloodLight(light, &volume, leaf->cluster, 0); - if (volume.surfaceNum >= 0) - { - VL_R_CastLightAtSurface(light, &volume); - } - } - } - break; - } - case LIGHT_POINTSPOT: - { - // source is a point - // light is targetted - // creates sharp shadows - // - // what about using brushes to shape spot lights? that'd be pretty cool - // - if ( light->atten_disttype == LDAT_LINEAR ) - dist = light->photons * lightLinearScale; - else - dist = sqrt(light->photons); - dist *= 2; - // - windingdist = 4096; - if (dist > windingdist) - windingdist = dist; - //take 8 times the cone radius because the spotlight also lights outside the cone - radius = 8 * windingdist * light->radiusByDist; - // - memset(&volume, 0, sizeof(lightvolume_t)); - leafnum = VL_LightLeafnum(light->origin); - leaf = &dleafs[leafnum]; - if (leaf->cluster == -1) - { - light->insolid = qtrue; - break; - } - // - VectorClear(vec); - for (i = 0; i < 3; i++) - { - if (light->normal[i] > -0.9 && light->normal[i] < 0.9) - { - vec[i] = 1; - break; - } - } - CrossProduct(light->normal, vec, r); - VectorScale(r, radius, p); - volume.numplanes = 0; - step = 45; - for (a = step / 2; a < 360 + step / 2; a += step) - { - RotatePointAroundVector(volume.points[volume.numplanes], light->normal, p, a); - VectorAdd(light->origin, volume.points[volume.numplanes], volume.points[volume.numplanes]); - VectorMA(volume.points[volume.numplanes], windingdist, light->normal, volume.points[volume.numplanes]); - volume.numplanes++; - } - for (i = 0; i < volume.numplanes; i++) - { - VL_PlaneFromPoints(&volume.planes[i], light->origin, volume.points[(i+1)%volume.numplanes], volume.points[i]); - } - VectorMA(light->origin, dist, light->normal, temp); - VectorCopy(light->normal, volume.endplane.normal); - VectorInverse(volume.endplane.normal); - volume.endplane.dist = DotProduct(volume.endplane.normal, temp);//DotProduct(volume.endplane.normal, volume.points[0]); - volume.farplane = volume.endplane; - volume.cluster = leaf->cluster; - volume.surfaceNum = -1; - volume.type = VOLUME_NORMAL; - // - memset(volume.facetTested, 0, sizeof(volume.facetTested)); - memset(volume.clusterTested, 0, sizeof(volume.clusterTested)); - VL_R_FloodLight(light, &volume, leaf->cluster, 0); - if (volume.surfaceNum >= 0) - { - VL_R_CastLightAtSurface(light, &volume); - } - break; - } - case LIGHT_POINTFAKESURFACE: - { - float value; - int n, axis; - vec3_t v, vecs[2]; - - if ( light->atten_disttype == LDAT_LINEAR ) - dist = light->photons * lightLinearScale; - else - dist = sqrt(light->photons); - //always put the winding at a large distance to avoid epsilon issues - windingdist = 4096; - if (dist > windingdist) - windingdist = dist; - // - VectorMA(light->origin, 0.1, light->normal, light->origin); - // - leafnum = VL_LightLeafnum(light->origin); - leaf = &dleafs[leafnum]; - if (leaf->cluster == -1) - { - light->insolid = qtrue; - break; - } - value = 0; - for (i = 0; i < 3; i++) - { - if (fabs(light->normal[i]) > value) - { - value = fabs(light->normal[i]); - axis = i; - } - } - for (i = 0; i < 2; i++) - { - VectorClear(v); - v[(axis + 1 + i) % 3] = 1; - CrossProduct(light->normal, v, vecs[i]); - } - //cast 4 volumes at the front of the surface - for (i = -1; i <= 1; i += 2) - { - for (j = -1; j <= 1; j += 2) - { - for (n = 0; n < 2; n++) - { - memset(&volume, 0, sizeof(lightvolume_t)); - volume.numplanes = 3; - VectorMA(light->origin, i * windingdist, vecs[0], volume.points[(i == j) == n]); - VectorMA(light->origin, j * windingdist, vecs[1], volume.points[(i != j) == n]); - VectorMA(light->origin, windingdist, light->normal, volume.points[2]); - for (k = 0; k < volume.numplanes; k++) - { - VL_PlaneFromPoints(&volume.planes[k], light->origin, volume.points[(k+1)%volume.numplanes], volume.points[k]); - } - VL_PlaneFromPoints(&volume.endplane, volume.points[0], volume.points[1], volume.points[2]); - VectorMA(light->origin, dist, light->normal, temp); - volume.endplane.dist = DotProduct(volume.endplane.normal, temp); - if (DotProduct(light->origin, volume.endplane.normal) - volume.endplane.dist > 0) - break; - } - volume.farplane = volume.endplane; - volume.cluster = leaf->cluster; - volume.surfaceNum = -1; - volume.type = VOLUME_NORMAL; - // - memset(volume.facetTested, 0, sizeof(volume.facetTested)); - memset(volume.clusterTested, 0, sizeof(volume.clusterTested)); - - VL_R_FloodLight(light, &volume, leaf->cluster, 0); - if (volume.surfaceNum >= 0) - { - VL_R_CastLightAtSurface(light, &volume); - } - } - } - break; - } - case LIGHT_SURFACEDIRECTED: - { - // source is an area defined by a winding - // the light is unidirectional - // creates sharp shadows - // for instance sun light or laser light - // - memcpy(&winding, &light->w, sizeof(winding_t)); - VL_R_SubdivideDirectedAreaLight(light, 0, &winding); - break; - } - case LIGHT_SURFACERADIAL: - { - // source is an area defined by a winding - // the light radiates in all directions at the front of the winding plane - // - memcpy(&winding, &light->w, sizeof(winding_t)); - VL_R_SubdivideRadialAreaLight(light, 0, &winding); - break; - } - case LIGHT_SURFACESPOT: - { - // source is an area defined by a winding - // light is targetted but not unidirectional - // - memcpy(&winding, &light->w, sizeof(winding_t)); - VL_R_SubdivideAreaSpotLight(light, 0, &winding); - break; - } - } -} - -/* -============= -VL_FloodLightThread -============= -*/ -void VL_FloodLightThread(int num) -{ - VL_FloodLight(vlights[num]); -} - -/* -============= -VL_TestLightLeafs -============= -*/ -void VL_TestLightLeafs(void) -{ - int leafnum, i; - vlight_t *light; - dleaf_t *leaf; - - for (i = 0; i < numvlights; i++) - { - light = vlights[i]; - if (light->type != LIGHT_POINTRADIAL && - light->type != LIGHT_POINTSPOT) - continue; - leafnum = VL_LightLeafnum(light->origin); - leaf = &dleafs[leafnum]; - if (leaf->cluster == -1) - if (light->type == LIGHT_POINTRADIAL) - qprintf("light in solid at %1.1f %1.1f %1.1f\n", light->origin[0], light->origin[1], light->origin[2]); - else if (light->type == LIGHT_POINTSPOT) - qprintf("spot light in solid at %1.1f %1.1f %1.1f\n", light->origin[0], light->origin[1], light->origin[2]); - } -} - - -/* -============= -VL_DoForcedTraceLight -============= -*/ -// from light.c -void TraceLtm( int num ); - -void VL_DoForcedTraceLight(int num) -{ - dsurface_t *ds; - shaderInfo_t *si; - - ds = &drawSurfaces[num]; - - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) - return; - - if ( ds->lightmapNum < 0 ) - return; - - // always light entity surfaces with the old light algorithm - if ( !entitySurface[num] ) - { - si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - - if (defaulttracelight) - { - if (si->forceVLight) - return; - } - else - { - if (!si->forceTraceLight) - return; - } - } - - TraceLtm(num); -} - -/* -============= -VL_DoForcedTraceLightSurfaces -============= -*/ -void VL_DoForcedTraceLightSurfaces(void) -{ - _printf( "forced trace light\n" ); - RunThreadsOnIndividual( numDrawSurfaces, qtrue, VL_DoForcedTraceLight ); -} - -float *oldLightFloats; - -/* -============= -VL_SurfaceRadiosity -============= -*/ -void VL_SurfaceRadiosity( int num ) { - dsurface_t *ds; - mesh_t *mesh; - shaderInfo_t *si; - lsurfaceTest_t *test; - int x, y, k; - vec3_t base, normal; - float *color, area; - vlight_t vlight; - - ds = &drawSurfaces[num]; - - if ( ds->lightmapNum < 0 ) { - return; // doesn't have a lightmap - } - - // vertex-lit triangle model - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) { - return; - } - - si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - test = lsurfaceTest[ num ]; - - if (!test) { - return; - } - - for (x = 0; x < ds->lightmapWidth; x++) { - for (y = 0; y < ds->lightmapHeight; y++) { - // - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - area = lightmappixelarea[k]; - if (area <= 0) - continue; - // - if (ds->surfaceType == MST_PATCH) - { - mesh = test->detailMesh; - VectorCopy( mesh->verts[y*mesh->width+x].xyz, base); - VectorCopy( mesh->verts[y*mesh->width+x].normal, normal); - } - else - { - VectorMA(ds->lightmapOrigin, (float) x, ds->lightmapVecs[0], base); - VectorMA(base, (float) y, ds->lightmapVecs[1], base); - VectorCopy(test->facets[0].plane.normal, normal); - } - // create ligth from base - memset(&vlight, 0, sizeof(vlight_t)); - color = &oldLightFloats[k*3]; - // a few units away from the surface - VectorMA(base, 5, normal, vlight.origin); - ColorNormalize(color, vlight.color); - // ok this is crap - vlight.photons = VectorLength(color) * 0.05 * lightPointScale / (area * radiosity_scale); - // what about using a front facing light only ? - vlight.type = LIGHT_POINTRADIAL; - // flood the light from this lightmap pixel - VL_FloodLight(&vlight); - // only one thread at a time may write to the lightmap of this surface - MutexLock(test->mutex); - // don't light the lightmap pixel itself - lightFloats[k*3] = oldLightFloats[k*3]; - lightFloats[k*3+1] = oldLightFloats[k*3+1]; - lightFloats[k*3+2] = oldLightFloats[k*3+2]; - // - MutexUnlock(test->mutex); - } - } -} - -/* -============= -VL_Radiosity - -this aint working real well but it's fun to play with. -============= -*/ -void VL_Radiosity(void) { - - oldLightFloats = lightFloats; - lightFloats = (float *) malloc(numLightBytes * sizeof(float)); - memcpy(lightFloats, oldLightFloats, numLightBytes * sizeof(float)); - _printf("%7i surfaces\n", numDrawSurfaces); - RunThreadsOnIndividual( numDrawSurfaces, qtrue, VL_SurfaceRadiosity ); - free(oldLightFloats); -} - -/* -============= -VL_LightWorld -============= -*/ -void VL_LightWorld(void) -{ - int i, numcastedvolumes, numvlightsinsolid; - float f; - - // find the optional world ambient - GetVectorForKey( &entities[0], "_color", lightAmbientColor ); - f = FloatForKey( &entities[0], "ambient" ); - VectorScale( lightAmbientColor, f, lightAmbientColor ); - /* - _printf("\r%6d lights out of %d", 0, numvlights); - for (i = 0; i < numvlights; i++) - { - _printf("\r%6d", i); - VL_FloodLight(vlights[i]); - } - _printf("\r%6d lights out of %d\n", i, numvlights); - */ - _printf("%7i lights\n", numvlights); - RunThreadsOnIndividual( numvlights, qtrue, VL_FloodLightThread ); - - numcastedvolumes = 0; - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - if (lsurfaceTest[i]) - numcastedvolumes += lsurfaceTest[i]->numvolumes; - } - _printf("%7i light volumes casted\n", numcastedvolumes); - numvlightsinsolid = 0; - for (i = 0; i < numvlights; i++) - { - if (vlights[i]->insolid) - numvlightsinsolid++; - } - _printf("%7i lights in solid\n", numvlightsinsolid); - // - radiosity_scale = 1; - for (i = 0; i < radiosity; i++) { - VL_Radiosity(); - radiosity_scale <<= 1; - } - // - VL_StoreLightmap(); - // redo surfaces with the old light algorithm when needed - VL_DoForcedTraceLightSurfaces(); -} - -/* -============= -VL_CreateEntityLights -============= -*/ -entity_t *FindTargetEntity( const char *target ); - -void VL_CreateEntityLights (void) -{ - int i, c_entityLights; - vlight_t *dl; - entity_t *e, *e2; - const char *name; - const char *target; - vec3_t dest; - const char *_color; - float intensity; - int spawnflags; - - // - c_entityLights = 0; - _printf("Creating entity lights...\n"); - // - for ( i = 0 ; i < num_entities ; i++ ) { - e = &entities[i]; - name = ValueForKey (e, "classname"); - if (strncmp (name, "light", 5)) - continue; - - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - - spawnflags = FloatForKey (e, "spawnflags"); - if ( spawnflags & 1 ) { - dl->atten_disttype = LDAT_LINEAR; - } - if ( spawnflags & 2 ) { - dl->atten_disttype = LDAT_NOSCALE; - } - if ( spawnflags & 4 ) { - dl->atten_angletype = LAAT_QUADRATIC; - } - if ( spawnflags & 8 ) { - dl->atten_angletype = LAAT_DOUBLEQUADRATIC; - } - - dl->atten_distscale = FloatForKey(e, "atten_distscale"); - dl->atten_anglescale = FloatForKey(e, "atten_anglescale"); - - GetVectorForKey (e, "origin", dl->origin); - dl->style = FloatForKey (e, "_style"); - if (!dl->style) - dl->style = FloatForKey (e, "style"); - if (dl->style < 0) - dl->style = 0; - - intensity = FloatForKey (e, "light"); - if (!intensity) - intensity = FloatForKey (e, "_light"); - if (!intensity) - intensity = 300; - _color = ValueForKey (e, "_color"); - if (_color && _color[0]) - { - sscanf (_color, "%f %f %f", &dl->color[0],&dl->color[1],&dl->color[2]); - ColorNormalize (dl->color, dl->color); - } - else - dl->color[0] = dl->color[1] = dl->color[2] = 1.0; - - intensity = intensity * lightPointScale; - dl->photons = intensity; - - dl->type = LIGHT_POINTRADIAL; - - // lights with a target will be spotlights - target = ValueForKey (e, "target"); - - if ( target[0] ) { - float radius; - float dist; - - e2 = FindTargetEntity (target); - if (!e2) { - _printf ("WARNING: light at (%i %i %i) has missing target\n", - (int)dl->origin[0], (int)dl->origin[1], (int)dl->origin[2]); - } else { - GetVectorForKey (e2, "origin", dest); - VectorSubtract (dest, dl->origin, dl->normal); - dist = VectorNormalize (dl->normal, dl->normal); - radius = FloatForKey (e, "radius"); - if ( !radius ) { - radius = 64; - } - if ( !dist ) { - dist = 64; - } - dl->radiusByDist = (radius + 16) / dist; - dl->type = LIGHT_POINTSPOT; - } - } - vlights[numvlights++] = dl; - c_entityLights++; - } - _printf("%7i entity lights\n", c_entityLights); -} - -/* -================== -VL_SubdivideAreaLight -================== -*/ -void VL_SubdivideAreaLight( shaderInfo_t *ls, winding_t *w, vec3_t normal, - float areaSubdivide, qboolean backsplash ) { - float area, value, intensity; - vlight_t *dl, *dl2; - vec3_t mins, maxs; - int axis; - winding_t *front, *back; - vec3_t planeNormal; - float planeDist; - - if ( !w ) { - return; - } - - WindingBounds( w, mins, maxs ); - - // check for subdivision - for ( axis = 0 ; axis < 3 ; axis++ ) { - if ( maxs[axis] - mins[axis] > areaSubdivide ) { - VectorClear( planeNormal ); - planeNormal[axis] = 1; - planeDist = ( maxs[axis] + mins[axis] ) * 0.5; - ClipWindingEpsilon ( w, planeNormal, planeDist, ON_EPSILON, &front, &back ); - VL_SubdivideAreaLight( ls, front, normal, areaSubdivide, qfalse ); - VL_SubdivideAreaLight( ls, back, normal, areaSubdivide, qfalse ); - FreeWinding( w ); - return; - } - } - - // create a light from this - area = WindingArea (w); - if ( area <= 0 || area > 20000000 ) { - return; - } - - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - dl->type = LIGHT_POINTFAKESURFACE; - - WindingCenter( w, dl->origin ); - memcpy(dl->w.points, w->points, sizeof(vec3_t) * w->numpoints); - dl->w.numpoints = w->numpoints; - VectorCopy ( normal, dl->normal); - VectorCopy ( normal, dl->plane); - dl->plane[3] = DotProduct( dl->origin, normal ); - - value = ls->value; - intensity = value * area * lightAreaScale; - VectorAdd( dl->origin, dl->normal, dl->origin ); - - VectorCopy( ls->color, dl->color ); - - dl->photons = intensity; - - // emitColor is irrespective of the area - VectorScale( ls->color, value*lightFormFactorValueScale*lightAreaScale, dl->emitColor ); - // - VectorCopy(dl->emitColor, dl->color); - - dl->si = ls; - - if ( ls->contents & CONTENTS_FOG ) { - dl->twosided = qtrue; - } - - vlights[numvlights++] = dl; - - // optionally create a point backsplash light - if ( backsplash && ls->backsplashFraction > 0 ) { - - dl2 = malloc(sizeof(*dl)); - memset (dl2, 0, sizeof(*dl2)); - dl2->type = LIGHT_POINTRADIAL; - - VectorMA( dl->origin, ls->backsplashDistance, normal, dl2->origin ); - - VectorCopy( ls->color, dl2->color ); - - dl2->photons = dl->photons * ls->backsplashFraction; - dl2->si = ls; - - vlights[numvlights++] = dl2; - } -} - -/* -================== -VL_CreateFakeSurfaceLights -================== -*/ -void VL_CreateFakeSurfaceLights( void ) { - int i, j, side; - dsurface_t *ds; - shaderInfo_t *ls; - winding_t *w; - lFacet_t *f; - vlight_t *dl; - vec3_t origin; - drawVert_t *dv; - int c_surfaceLights; - float lightSubdivide; - vec3_t normal; - - - c_surfaceLights = 0; - _printf ("Creating surface lights...\n"); - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - // see if this surface is light emiting - ds = &drawSurfaces[i]; - - ls = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - if ( ls->value == 0 ) { - continue; - } - - // determine how much we need to chop up the surface - if ( ls->lightSubdivide ) { - lightSubdivide = ls->lightSubdivide; - } else { - lightSubdivide = lightDefaultSubdivide; - } - - c_surfaceLights++; - - // an autosprite shader will become - // a point light instead of an area light - if ( ls->autosprite ) { - // autosprite geometry should only have four vertexes - if ( lsurfaceTest[i] ) { - // curve or misc_model - f = lsurfaceTest[i]->facets; - if ( lsurfaceTest[i]->numFacets != 1 || f->numpoints != 4 ) { - _printf( "WARNING: surface at (%i %i %i) has autosprite shader but isn't a quad\n", - (int)f->points[0], (int)f->points[1], (int)f->points[2] ); - } - VectorAdd( f->points[0], f->points[1], origin ); - VectorAdd( f->points[2], origin, origin ); - VectorAdd( f->points[3], origin, origin ); - VectorScale( origin, 0.25, origin ); - } else { - // normal polygon - dv = &drawVerts[ ds->firstVert ]; - if ( ds->numVerts != 4 ) { - _printf( "WARNING: surface at (%i %i %i) has autosprite shader but %i verts\n", - (int)dv->xyz[0], (int)dv->xyz[1], (int)dv->xyz[2] ); - continue; - } - - VectorAdd( dv[0].xyz, dv[1].xyz, origin ); - VectorAdd( dv[2].xyz, origin, origin ); - VectorAdd( dv[3].xyz, origin, origin ); - VectorScale( origin, 0.25, origin ); - } - - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - VectorCopy( origin, dl->origin ); - VectorCopy( ls->color, dl->color ); - dl->photons = ls->value * lightPointScale; - dl->type = LIGHT_POINTRADIAL; - vlights[numvlights++] = dl; - continue; - } - - // possibly create for both sides of the polygon - for ( side = 0 ; side <= ls->twoSided ; side++ ) { - // create area lights - if ( lsurfaceTest[i] ) { - // curve or misc_model - for ( j = 0 ; j < lsurfaceTest[i]->numFacets ; j++ ) { - f = lsurfaceTest[i]->facets + j; - w = AllocWinding( f->numpoints ); - w->numpoints = f->numpoints; - memcpy( w->points, f->points, f->numpoints * 12 ); - - VectorCopy( f->plane.normal, normal ); - if ( side ) { - winding_t *t; - - t = w; - w = ReverseWinding( t ); - FreeWinding( t ); - VectorSubtract( vec3_origin, normal, normal ); - } - VL_SubdivideAreaLight( ls, w, normal, lightSubdivide, qtrue ); - } - } else { - // normal polygon - - w = AllocWinding( ds->numVerts ); - w->numpoints = ds->numVerts; - for ( j = 0 ; j < ds->numVerts ; j++ ) { - VectorCopy( drawVerts[ds->firstVert+j].xyz, w->points[j] ); - } - VectorCopy( ds->lightmapVecs[2], normal ); - if ( side ) { - winding_t *t; - - t = w; - w = ReverseWinding( t ); - FreeWinding( t ); - VectorSubtract( vec3_origin, normal, normal ); - } - VL_SubdivideAreaLight( ls, w, normal, lightSubdivide, qtrue ); - } - } - } - - _printf( "%7i light emitting surfaces\n", c_surfaceLights ); -} - - -/* -================== -VL_WindingForBrushSide -================== -*/ -winding_t *VL_WindingForBrushSide(dbrush_t *brush, int side, winding_t *w) -{ - int i, res; - winding_t *tmpw; - plane_t plane; - - VectorCopy(dplanes[ dbrushsides[ brush->firstSide + side ].planeNum ].normal, plane.normal); - VectorInverse(plane.normal); - plane.dist = -dplanes[ dbrushsides[ brush->firstSide + side ].planeNum ].dist; - tmpw = BaseWindingForPlane( plane.normal, plane.dist ); - memcpy(w->points, tmpw->points, sizeof(vec3_t) * tmpw->numpoints); - w->numpoints = tmpw->numpoints; - - for (i = 0; i < brush->numSides; i++) - { - if (i == side) - continue; - VectorCopy(dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].normal, plane.normal); - VectorInverse(plane.normal); - plane.dist = -dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].dist; - res = VL_ChopWinding(w, &plane, 0.1); - if (res == SIDE_BACK) - return NULL; - } - return w; -} - -/* -================== -VL_CreateSkyLights -================== -*/ -void VL_CreateSkyLights(void) -{ - int i, j, c_skyLights; - dbrush_t *b; - shaderInfo_t *si; - dbrushside_t *s; - vlight_t *dl; - vec3_t sunColor, sunDir = { 0.45, 0.3, 0.9 }; - float d; - - VectorNormalize(sunDir, sunDir); - VectorInverse(sunDir); - - c_skyLights = 0; - _printf("Creating sky lights...\n"); - // find the sky shader - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - si = ShaderInfoForShader( dshaders[ drawSurfaces[i].shaderNum ].shader ); - if ( si->surfaceFlags & SURF_SKY ) { - VectorCopy( si->sunLight, sunColor ); - VectorCopy( si->sunDirection, sunDir ); - VectorInverse(sunDir); - break; - } - } - - // find the brushes - for ( i = 0 ; i < numbrushes ; i++ ) { - b = &dbrushes[i]; - for ( j = 0 ; j < b->numSides ; j++ ) { - s = &dbrushsides[ b->firstSide + j ]; - if ( dshaders[ s->shaderNum ].surfaceFlags & SURF_SKY ) { - //if this surface doesn't face in the same direction as the sun - d = DotProduct(dplanes[ s->planeNum ].normal, sunDir); - if (d <= 0) - continue; - // - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - VectorCopy(sunColor, dl->color); - VectorCopy(sunDir, dl->normal); - VectorCopy(dplanes[ s->planeNum ].normal, dl->plane); - dl->plane[3] = dplanes[ s->planeNum ].dist; - dl->type = LIGHT_SURFACEDIRECTED; - dl->atten_disttype = LDAT_NOSCALE; - VL_WindingForBrushSide(b, j, &dl->w); -// DebugNet_DrawWinding(&dl->w, 2); - // - vlights[numvlights++] = dl; - c_skyLights++; - } - } - } - _printf("%7i light emitting sky surfaces\n", c_skyLights); -} - -/* -================== -VL_SetPortalSphere -================== -*/ -void VL_SetPortalSphere (lportal_t *p) -{ - int i; - vec3_t total, dist; - winding_t *w; - float r, bestr; - - w = p->winding; - VectorCopy (vec3_origin, total); - for (i=0 ; i<w->numpoints ; i++) - { - VectorAdd (total, w->points[i], total); - } - - for (i=0 ; i<3 ; i++) - total[i] /= w->numpoints; - - bestr = 0; - for (i=0 ; i<w->numpoints ; i++) - { - VectorSubtract (w->points[i], total, dist); - r = VectorLength (dist); - if (r > bestr) - bestr = r; - } - VectorCopy (total, p->origin); - p->radius = bestr; -} - -/* -================== -VL_PlaneFromWinding -================== -*/ -void VL_PlaneFromWinding (winding_t *w, plane_t *plane) -{ - vec3_t v1, v2; - - //calc plane - VectorSubtract (w->points[2], w->points[1], v1); - VectorSubtract (w->points[0], w->points[1], v2); - CrossProduct (v2, v1, plane->normal); - VectorNormalize (plane->normal, plane->normal); - plane->dist = DotProduct (w->points[0], plane->normal); -} - -/* -================== -VL_AllocWinding -================== -*/ -winding_t *VL_AllocWinding (int points) -{ - winding_t *w; - int size; - - if (points > MAX_POINTS_ON_WINDING) - Error ("NewWinding: %i points", points); - - size = (int)((winding_t *)0)->points[points]; - w = malloc (size); - memset (w, 0, size); - - return w; -} - -/* -============ -VL_LoadPortals -============ -*/ -void VL_LoadPortals (char *name) -{ - int i, j, hint; - lportal_t *p; - lleaf_t *l; - char magic[80]; - FILE *f; - int numpoints; - winding_t *w; - int leafnums[2]; - plane_t plane; - // - - if (!strcmp(name,"-")) - f = stdin; - else - { - f = fopen(name, "r"); - if (!f) - Error ("LoadPortals: couldn't read %s\n",name); - } - - if (fscanf (f,"%79s\n%i\n%i\n%i\n",magic, &portalclusters, &numportals, &numfaces) != 4) - Error ("LoadPortals: failed to read header"); - if (strcmp(magic, PORTALFILE)) - Error ("LoadPortals: not a portal file"); - - _printf ("%6i portalclusters\n", portalclusters); - _printf ("%6i numportals\n", numportals); - _printf ("%6i numfaces\n", numfaces); - - if (portalclusters >= MAX_CLUSTERS) - Error ("more than %d clusters in portal file\n", MAX_CLUSTERS); - - // each file portal is split into two memory portals - portals = malloc(2*numportals*sizeof(lportal_t)); - memset (portals, 0, 2*numportals*sizeof(lportal_t)); - - leafs = malloc(portalclusters*sizeof(lleaf_t)); - memset (leafs, 0, portalclusters*sizeof(lleaf_t)); - - for (i=0, p=portals ; i<numportals ; i++) - { - if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1]) != 3) - Error ("LoadPortals: reading portal %i", i); - if (numpoints > MAX_POINTS_ON_WINDING) - Error ("LoadPortals: portal %i has too many points", i); - if ( (unsigned)leafnums[0] > portalclusters - || (unsigned)leafnums[1] > portalclusters) - Error ("LoadPortals: reading portal %i", i); - if (fscanf (f, "%i ", &hint) != 1) - Error ("LoadPortals: reading hint state"); - - w = p->winding = VL_AllocWinding (numpoints); - w->numpoints = numpoints; - - for (j=0 ; j<numpoints ; j++) - { - double v[3]; - int k; - - // scanf into double, then assign to vec_t - // so we don't care what size vec_t is - if (fscanf (f, "(%lf %lf %lf ) " - , &v[0], &v[1], &v[2]) != 3) - Error ("LoadPortals: reading portal %i", i); - for (k=0 ; k<3 ; k++) - w->points[j][k] = v[k]; - } - fscanf (f, "\n"); - - // calc plane - VL_PlaneFromWinding (w, &plane); - - // create forward portal - l = &leafs[leafnums[0]]; - if (l->numportals == MAX_PORTALS_ON_LEAF) - Error ("Leaf with too many portals"); - l->portals[l->numportals] = p; - l->numportals++; - - p->winding = w; - VectorSubtract (vec3_origin, plane.normal, p->plane.normal); - p->plane.dist = -plane.dist; - p->leaf = leafnums[1]; - VL_SetPortalSphere (p); - p++; - - // create backwards portal - l = &leafs[leafnums[1]]; - if (l->numportals == MAX_PORTALS_ON_LEAF) - Error ("Leaf with too many portals"); - l->portals[l->numportals] = p; - l->numportals++; - - p->winding = VL_AllocWinding(w->numpoints); - p->winding->numpoints = w->numpoints; - for (j=0 ; j<w->numpoints ; j++) - { - VectorCopy (w->points[w->numpoints-1-j], p->winding->points[j]); - } - - p->plane = plane; - p->leaf = leafnums[0]; - VL_SetPortalSphere (p); - p++; - - } - - fclose (f); -} - -/* -============ -VLightMain -============ -*/ -int VLightMain (int argc, char **argv) { - int i; - double start, end; - const char *value; - - _printf ("----- VLighting ----\n"); - - for (i=1 ; i<argc ; i++) { - if (!strcmp(argv[i],"-v")) { - verbose = qtrue; - } else if (!strcmp(argv[i],"-threads")) { - numthreads = atoi (argv[i+1]); - _printf("num threads = %d\n", numthreads); - i++; - } else if (!strcmp(argv[i],"-area")) { - lightAreaScale *= atof(argv[i+1]); - _printf ("area light scaling at %f\n", lightAreaScale); - i++; - } else if (!strcmp(argv[i],"-point")) { - lightPointScale *= atof(argv[i+1]); - _printf ("point light scaling at %f\n", lightPointScale); - i++; - } else if (!strcmp(argv[i], "-samplesize")) { - samplesize = atoi(argv[i+1]); - if (samplesize < 1) samplesize = 1; - i++; - _printf("lightmap sample size is %dx%d units\n", samplesize, samplesize); - } else if (!strcmp(argv[i], "-novertex")) { - novertexlighting = qtrue; - _printf("no vertex lighting = true\n"); - } else if (!strcmp(argv[i], "-nogrid")) { - nogridlighting = qtrue; - _printf("no grid lighting = true\n"); - } else if (!strcmp(argv[i], "-nostitching")) { - nostitching = qtrue; - _printf("no stitching = true\n"); - } else if (!strcmp(argv[i], "-noalphashading")) { - noalphashading = qtrue; - _printf("no alpha shading = true\n"); - } else if (!strcmp(argv[i], "-nocolorshading")) { - nocolorshading = qtrue; - _printf("old style alpha shading = true\n"); - } else if (!strcmp(argv[i], "-nobackfaceculling")) { - nobackfaceculling = qtrue; - _printf("no backface culling = true\n"); - } else if (!strcmp(argv[i], "-tracelight")) { - defaulttracelight = qtrue; - _printf("default trace light = true\n"); - } else if (!strcmp(argv[i], "-radiosity")) { - radiosity = atoi(argv[i+1]); - _printf("radiosity = %d\n", radiosity); - i++; - } else { - break; - } - } - - ThreadSetDefault (); - - if (i != argc - 1) { - _printf("usage: q3map -vlight [-<switch> [-<switch> ...]] <mapname>\n" - "\n" - "Switches:\n" - " v = verbose output\n" - " threads <X> = set number of threads to X\n" - " area <V> = set the area light scale to V\n" - " point <W> = set the point light scale to W\n" - " novertex = don't calculate vertex lighting\n" - " nogrid = don't calculate light grid for dynamic model lighting\n" - " nostitching = no polygon stitching before lighting\n" - " noalphashading = don't use alpha shading\n" - " nocolorshading = don't use color alpha shading\n" - " tracelight = use old light algorithm by default\n" - " samplesize <N> = set the lightmap pixel size to NxN units\n"); - exit(0); - } - - SetQdirFromPath (argv[i]); - -#ifdef _WIN32 - InitPakFile(gamedir, NULL); -#endif - - strcpy (source, ExpandArg(argv[i])); - StripExtension (source); - DefaultExtension (source, ".bsp"); - - LoadShaderInfo(); - - _printf ("reading %s\n", source); - - LoadBSPFile (source); - ParseEntities(); - - value = ValueForKey( &entities[0], "gridsize" ); - if (strlen(value)) { - sscanf( value, "%f %f %f", &gridSize[0], &gridSize[1], &gridSize[2] ); - _printf("grid size = {%1.1f, %1.1f, %1.1f}\n", gridSize[0], gridSize[1], gridSize[2]); - } - - CountLightmaps(); - - StripExtension (source); - DefaultExtension (source, ".prt"); - - VL_LoadPortals(source); - - // set surfaceOrigin - SetEntityOrigins(); - - // grid and vertex lighting - GridAndVertexLighting(); - -#ifdef DEBUGNET - DebugNet_Setup(); -#endif - - start = clock(); - - lightFloats = (float *) malloc(numLightBytes * sizeof(float)); - memset(lightFloats, 0, numLightBytes * sizeof(float)); - - VL_InitSurfacesForTesting(); - - VL_CalcVisibleLightmapPixelArea(); - - numvlights = 0; - VL_CreateEntityLights(); - VL_CreateFakeSurfaceLights(); - VL_CreateSkyLights(); - - VL_TestLightLeafs(); - - VL_LightWorld(); - -#ifndef LIGHTPOLYS - StripExtension (source); - DefaultExtension (source, ".bsp"); - _printf ("writing %s\n", source); - WriteBSPFile (source); -#endif - - end = clock(); - - _printf ("%5.2f seconds elapsed\n", (end-start) / CLK_TCK); - -#ifdef LIGHTPOLYS - VL_DrawLightWindings(); -#endif - -#ifdef DEBUGNET - DebugNet_Shutdown(); -#endif - return 0; -} diff --git a/q3map/makefile b/q3map/makefile deleted file mode 100644 index ff8d6c1..0000000 --- a/q3map/makefile +++ /dev/null @@ -1,148 +0,0 @@ - -CFLAGS = -c -LDFLAGS = -ODIR = /q3/q3map - -EXEBASE = q3map -EXE = $(ODIR)/$(EXEBASE) -all: $(EXE) - -_irix: - make "CFLAGS = -c -Ofast=ip27 -OPT:IEEE_arithmetic=3 -I../common -Xcpluscomm " "LDFLAGS = -Ofast=ip27 -OPT:IEEE_arithmetic=3 -g" - -_irixdebug: - make "CFLAGS = -c -O2 -g -I../common -Xcpluscomm" "LDFLAGS = -g" - -_irixinst: - make "_irix" - make "install" - -clean: - rm -f $(ODIR)/*.o $(EXE) - -install: - cp $(EXE) /quake3_bin - chmod 0777 /quake3_bin/$(EXEBASE) - -installtest: - cp $(EXE) /quake3_bin/$(EXEBASE)_test - chmod 0777 /quake3_bin/$(EXEBASE)_test - - -FILES = $(ODIR)/fog.o $(ODIR)/brush.o $(ODIR)/tjunction.o $(ODIR)/vis.o $(ODIR)/visflow.o \ -$(ODIR)/light.o $(ODIR)/lightmaps.o $(ODIR)/bspfile.o \ -$(ODIR)/cmdlib.o $(ODIR)/patch.o $(ODIR)/mesh.o $(ODIR)/nodraw.o $(ODIR)/glfile.o \ -$(ODIR)/leakfile.o $(ODIR)/map.o $(ODIR)/mathlib.o $(ODIR)/polylib.o $(ODIR)/aselib.o \ -$(ODIR)/imagelib.o $(ODIR)/portals.o $(ODIR)/prtfile.o $(ODIR)/bsp.o $(ODIR)/surface.o \ -$(ODIR)/scriplib.o $(ODIR)/shaders.o $(ODIR)/threads.o $(ODIR)/tree.o \ -$(ODIR)/writebsp.o $(ODIR)/facebsp.o $(ODIR)/misc_model.o $(ODIR)/light_trace.o - -$(EXE) : $(FILES) - cc -o $(EXE) $(LDFLAGS) $(FILES) -lm - -$(ODIR)/surface.o : surface.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/fog.o : fog.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/brush.o : brush.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/tjunction.o : tjunction.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/lightmaps.o : lightmaps.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/brushbsp.o : brushbsp.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/facebsp.o : facebsp.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/patch.o : patch.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/mesh.o : mesh.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/misc_model.o : misc_model.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/nodraw.o : nodraw.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/glfile.o : glfile.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/leakfile.o : leakfile.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/map.o : map.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/portals.o : portals.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/prtfile.o : prtfile.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/bsp.o : bsp.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/tree.o : tree.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/shaders.o : shaders.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/writebsp.o : writebsp.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/csg.o : csg.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i - - -$(ODIR)/vis.o : vis.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/visflow.o : visflow.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i - - -$(ODIR)/light.o : light.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/light_trace.o : light_trace.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i - -$(ODIR)/cmdlib.o : ../common/cmdlib.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/mathlib.o : ../common/mathlib.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/polylib.o : ../common/polylib.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/aselib.o : ../common/aselib.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/imagelib.o : ../common/imagelib.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/scriplib.o : ../common/scriplib.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/threads.o : ../common/threads.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/bspfile.o : ../common/bspfile.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i - - diff --git a/q3map/map.c b/q3map/map.c deleted file mode 100644 index 3de6ede..0000000 --- a/q3map/map.c +++ /dev/null @@ -1,1251 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// map.c - -#include "qbsp.h" - - -int entitySourceBrushes; // to track editor brush numbers - -int numMapPatches; - -// undefine to make plane finding use linear sort -#define USE_HASHING -#define PLANE_HASHES 1024 -plane_t *planehash[PLANE_HASHES]; - -plane_t mapplanes[MAX_MAP_PLANES]; -int nummapplanes; - -// as brushes and patches are read in, the shaders are stored out in order -// here, so -onlytextures can just copy them out over the existing shaders -// in the drawSurfaces -char mapIndexedShaders[MAX_MAP_BRUSHSIDES][MAX_QPATH]; -int numMapIndexedShaders; - -vec3_t map_mins, map_maxs; - -entity_t *mapent; - - - -int c_boxbevels; -int c_edgebevels; - -int c_areaportals; -int c_detail; -int c_structural; - -// brushes are parsed into a temporary array of sides, -// which will have the bevels added and duplicates -// removed before the final brush is allocated -bspbrush_t *buildBrush; - - -void TestExpandBrushes (void); -void SetTerrainTextures( void ); -void ParseTerrain( void ); - - -/* -============================================================================= - -PLANE FINDING - -============================================================================= -*/ - - -/* -================ -PlaneEqual -================ -*/ -#define NORMAL_EPSILON 0.00001 -#define DIST_EPSILON 0.01 -qboolean PlaneEqual (plane_t *p, vec3_t normal, vec_t dist) -{ -#if 1 - if ( - fabs(p->normal[0] - normal[0]) < NORMAL_EPSILON - && fabs(p->normal[1] - normal[1]) < NORMAL_EPSILON - && fabs(p->normal[2] - normal[2]) < NORMAL_EPSILON - && fabs(p->dist - dist) < DIST_EPSILON ) - return qtrue; -#else - if (p->normal[0] == normal[0] - && p->normal[1] == normal[1] - && p->normal[2] == normal[2] - && p->dist == dist) - return qtrue; -#endif - return qfalse; -} - -/* -================ -AddPlaneToHash -================ -*/ -void AddPlaneToHash (plane_t *p) -{ - int hash; - - hash = (int)fabs(p->dist) / 8; - hash &= (PLANE_HASHES-1); - - p->hash_chain = planehash[hash]; - planehash[hash] = p; -} - -/* -================ -CreateNewFloatPlane -================ -*/ -int CreateNewFloatPlane (vec3_t normal, vec_t dist) -{ - plane_t *p, temp; - - if (VectorLength(normal) < 0.5) - { - _printf( "FloatPlane: bad normal\n"); - return -1; - } - - // create a new plane - if (nummapplanes+2 > MAX_MAP_PLANES) - Error ("MAX_MAP_PLANES"); - - p = &mapplanes[nummapplanes]; - VectorCopy (normal, p->normal); - p->dist = dist; - p->type = (p+1)->type = PlaneTypeForNormal (p->normal); - - VectorSubtract (vec3_origin, normal, (p+1)->normal); - (p+1)->dist = -dist; - - nummapplanes += 2; - - // allways put axial planes facing positive first - if (p->type < 3) - { - if (p->normal[0] < 0 || p->normal[1] < 0 || p->normal[2] < 0) - { - // flip order - temp = *p; - *p = *(p+1); - *(p+1) = temp; - - AddPlaneToHash (p); - AddPlaneToHash (p+1); - return nummapplanes - 1; - } - } - - AddPlaneToHash (p); - AddPlaneToHash (p+1); - return nummapplanes - 2; -} - -/* -============== -SnapVector -============== -*/ -void SnapVector (vec3_t normal) -{ - int i; - - for (i=0 ; i<3 ; i++) - { - if ( fabs(normal[i] - 1) < NORMAL_EPSILON ) - { - VectorClear (normal); - normal[i] = 1; - break; - } - if ( fabs(normal[i] - -1) < NORMAL_EPSILON ) - { - VectorClear (normal); - normal[i] = -1; - break; - } - } -} - -/* -============== -SnapPlane -============== -*/ -void SnapPlane (vec3_t normal, vec_t *dist) -{ - SnapVector (normal); - - if (fabs(*dist-Q_rint(*dist)) < DIST_EPSILON) - *dist = Q_rint(*dist); -} - -/* -============= -FindFloatPlane - -============= -*/ -#ifndef USE_HASHING -int FindFloatPlane (vec3_t normal, vec_t dist) -{ - int i; - plane_t *p; - - SnapPlane (normal, &dist); - for (i=0, p=mapplanes ; i<nummapplanes ; i++, p++) - { - if (PlaneEqual (p, normal, dist)) - return i; - } - - return CreateNewFloatPlane (normal, dist); -} -#else -int FindFloatPlane (vec3_t normal, vec_t dist) -{ - int i; - plane_t *p; - int hash, h; - - SnapPlane (normal, &dist); - hash = (int)fabs(dist) / 8; - hash &= (PLANE_HASHES-1); - - // search the border bins as well - for (i=-1 ; i<=1 ; i++) - { - h = (hash+i)&(PLANE_HASHES-1); - for (p = planehash[h] ; p ; p=p->hash_chain) - { - if (PlaneEqual (p, normal, dist)) - return p-mapplanes; - } - } - - return CreateNewFloatPlane (normal, dist); -} -#endif - -/* -================ -MapPlaneFromPoints -================ -*/ -int MapPlaneFromPoints (vec3_t p0, vec3_t p1, vec3_t p2) { - vec3_t t1, t2, normal; - vec_t dist; - - VectorSubtract (p0, p1, t1); - VectorSubtract (p2, p1, t2); - CrossProduct (t1, t2, normal); - VectorNormalize (normal, normal); - - dist = DotProduct (p0, normal); - - return FindFloatPlane (normal, dist); -} - - -//==================================================================== - -/* -=========== -SetBrushContents - -The contents on all sides of a brush should be the same -Sets contentsShader, contents, opaque, and detail -=========== -*/ -void SetBrushContents( bspbrush_t *b ) { - int contents, c2; - side_t *s; - int i; - qboolean mixed; - int allFlags; - - s = &b->sides[0]; - contents = s->contents; - b->contentShader = s->shaderInfo; - mixed = qfalse; - - allFlags = 0; - - for ( i=1 ; i<b->numsides ; i++, s++ ) { - s = &b->sides[i]; - - if ( !s->shaderInfo ) { - continue; - } - - c2 = s->contents; - if (c2 != contents) { - mixed = qtrue; - } - - allFlags |= s->surfaceFlags; - } - - if ( mixed ) { - qprintf ("Entity %i, Brush %i: mixed face contents\n" - , b->entitynum, b->brushnum); - } - - if ( ( contents & CONTENTS_DETAIL ) && ( contents & CONTENTS_STRUCTURAL ) ) { - _printf ("Entity %i, Brush %i: mixed CONTENTS_DETAIL and CONTENTS_STRUCTURAL\n" - , num_entities-1, entitySourceBrushes ); - contents &= ~CONTENTS_DETAIL; - } - - // the fulldetail flag will cause detail brushes to be - // treated like normal brushes - if ( fulldetail ) { - contents &= ~CONTENTS_DETAIL; - } - - // all translucent brushes that aren't specirically made structural will - // be detail - if ( ( contents & CONTENTS_TRANSLUCENT ) && !( contents & CONTENTS_STRUCTURAL ) ) { - contents |= CONTENTS_DETAIL; - } - - if ( contents & CONTENTS_DETAIL ) { - c_detail++; - b->detail = qtrue; - } else { - c_structural++; - b->detail = qfalse; - } - - if ( contents & CONTENTS_TRANSLUCENT ) { - b->opaque = qfalse; - } else { - b->opaque = qtrue; - } - - if ( contents & CONTENTS_AREAPORTAL ) { - c_areaportals++; - } - - b->contents = contents; -} - - -//============================================================================ - -/* -================= -AddBrushBevels - -Adds any additional planes necessary to allow the brush being -built to be expanded against axial bounding boxes -================= -*/ -void AddBrushBevels( void ) { - int axis, dir; - int i, order; - side_t sidetemp; - side_t *s; - vec3_t normal; - float dist; - - // - // add the axial planes - // - order = 0; - for (axis=0 ; axis <3 ; axis++) - { - for (dir=-1 ; dir <= 1 ; dir+=2, order++) - { - // see if the plane is allready present - for ( i=0, s=buildBrush->sides ; i < buildBrush->numsides ; i++,s++ ) { - if (mapplanes[s->planenum].normal[axis] == dir) - break; - } - - if (i == buildBrush->numsides ) - { // add a new side - if ( buildBrush->numsides == MAX_BUILD_SIDES ) { - Error( "MAX_BUILD_SIDES" ); - } - memset( s, 0, sizeof( *s ) ); - buildBrush->numsides++; - VectorClear (normal); - normal[axis] = dir; - if (dir == 1) - dist = buildBrush->maxs[axis]; - else - dist = -buildBrush->mins[axis]; - s->planenum = FindFloatPlane (normal, dist); - s->contents = buildBrush->sides[0].contents; - s->bevel = qtrue; - c_boxbevels++; - } - - // if the plane is not in it canonical order, swap it - if (i != order) - { - sidetemp = buildBrush->sides[order]; - buildBrush->sides[order] = buildBrush->sides[i]; - buildBrush->sides[i] = sidetemp; - } - } - } - - // - // add the edge bevels - // - if ( buildBrush->numsides == 6 ) { - return; // pure axial - } else { - int j, k, l; - float d; - winding_t *w, *w2; - side_t *s2; - vec3_t vec, vec2; - - // test the non-axial plane edges - // this code tends to cause some problems... - for (i=6 ; i<buildBrush->numsides ; i++) - { - s = buildBrush->sides + i; - w = s->winding; - if (!w) - continue; - for (j=0 ; j<w->numpoints ; j++) - { - k = (j+1)%w->numpoints; - VectorSubtract (w->p[j], w->p[k], vec); - if (VectorNormalize (vec, vec) < 0.5) - continue; - SnapVector (vec); - for (k=0 ; k<3 ; k++) - if ( vec[k] == -1 || vec[k] == 1) - break; // axial - if (k != 3) - continue; // only test non-axial edges - - // try the six possible slanted axials from this edge - for (axis=0 ; axis <3 ; axis++) - { - for (dir=-1 ; dir <= 1 ; dir+=2) - { - // construct a plane - VectorClear (vec2); - vec2[axis] = dir; - CrossProduct (vec, vec2, normal); - if (VectorNormalize (normal, normal) < 0.5) - continue; - dist = DotProduct (w->p[j], normal); - - // if all the points on all the sides are - // behind this plane, it is a proper edge bevel - for (k=0 ; k < buildBrush->numsides ; k++) - { - // if this plane has allready been used, skip it - if (PlaneEqual (&mapplanes[buildBrush->sides[k].planenum] - , normal, dist) ) - break; - - w2 = buildBrush->sides[k].winding; - if (!w2) - continue; - for (l=0 ; l<w2->numpoints ; l++) - { - d = DotProduct (w2->p[l], normal) - dist; - if (d > 0.1) - break; // point in front - } - if (l != w2->numpoints) - break; - } - - if (k != buildBrush->numsides) - continue; // wasn't part of the outer hull - // add this plane - if ( buildBrush->numsides == MAX_BUILD_SIDES ) { - Error( "MAX_BUILD_SIDES" ); - } - - s2 = &buildBrush->sides[buildBrush->numsides]; - buildBrush->numsides++; - memset( s2, 0, sizeof( *s2 ) ); - - s2->planenum = FindFloatPlane (normal, dist); - s2->contents = buildBrush->sides[0].contents; - s2->bevel = qtrue; - c_edgebevels++; - } - } - } - } - } -} - -/* -=============== -AddBackSides - -fog volumes need to have inside faces created -=============== -*/ -void AddBackSides( void ) { -/* - bspbrush_t *b; - int i, originalSides; - side_t *s; - side_t *newSide; - - b = buildBrush; - originalSides = b->numsides; - for ( i = 0 ; i < originalSides ; i++ ) { - s = &b->sides[i]; - if ( !s->shaderInfo ) { - continue; - } - if ( !(s->shaderInfo->contents & CONTENTS_FOG) ) { - continue; - } - - // duplicate the up-facing side - if ( mapplanes[ s->planenum ].normal[2] == 1 ) { - newSide = &b->sides[ b->numsides ]; - b->numsides++; - - *newSide = *s; - newSide->backSide = qtrue; - newSide->planenum = s->planenum ^ 1; // opposite side - } - } -*/ -} - -/* -=============== -FinishBrush - -Produces a final brush based on the buildBrush->sides array -and links it to the current entity -=============== -*/ -bspbrush_t *FinishBrush( void ) { - bspbrush_t *b; - - // liquids may need to have extra sides created for back sides - AddBackSides(); - - // create windings for sides and bounds for brush - if ( !CreateBrushWindings( buildBrush ) ) { - // don't keep this brush - return NULL; - } - - // brushes that will not be visible at all are forced to be detail - if ( buildBrush->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) ) - { - buildBrush->detail = qtrue; - c_detail++; - } - - // - // origin brushes are removed, but they set - // the rotation origin for the rest of the brushes - // in the entity. After the entire entity is parsed, - // the planenums and texinfos will be adjusted for - // the origin brush - // - if ( buildBrush->contents & CONTENTS_ORIGIN ) - { - char string[32]; - vec3_t origin; - - if (num_entities == 1) { - _printf ("Entity %i, Brush %i: origin brushes not allowed in world\n" - , num_entities - 1, entitySourceBrushes); - return NULL; - } - - VectorAdd (buildBrush->mins, buildBrush->maxs, origin); - VectorScale (origin, 0.5, origin); - - sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]); - SetKeyValue (&entities[num_entities - 1], "origin", string); - - VectorCopy (origin, entities[num_entities - 1].origin); - - // don't keep this brush - return NULL; - } - - if ( buildBrush->contents & CONTENTS_AREAPORTAL ) { - if (num_entities != 1) { - _printf ("Entity %i, Brush %i: areaportals only allowed in world\n" - , num_entities - 1, entitySourceBrushes); - return NULL; - } - } - - AddBrushBevels (); - - // keep it - b = CopyBrush( buildBrush ); - - b->entitynum = num_entities-1; - b->brushnum = entitySourceBrushes; - - b->original = b; - - b->next = mapent->brushes; - mapent->brushes = b; - - return b; -} - -//====================================================================== - - -/* -================== -textureAxisFromPlane -================== -*/ -vec3_t baseaxis[18] = -{ -{0,0,1}, {1,0,0}, {0,-1,0}, // floor -{0,0,-1}, {1,0,0}, {0,-1,0}, // ceiling -{1,0,0}, {0,1,0}, {0,0,-1}, // west wall -{-1,0,0}, {0,1,0}, {0,0,-1}, // east wall -{0,1,0}, {1,0,0}, {0,0,-1}, // south wall -{0,-1,0}, {1,0,0}, {0,0,-1} // north wall -}; - -void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv) -{ - int bestaxis; - vec_t dot,best; - int i; - - best = 0; - bestaxis = 0; - - for (i=0 ; i<6 ; i++) - { - dot = DotProduct (pln->normal, baseaxis[i*3]); - if (dot > best) - { - best = dot; - bestaxis = i; - } - } - - VectorCopy (baseaxis[bestaxis*3+1], xv); - VectorCopy (baseaxis[bestaxis*3+2], yv); -} - - - -/* -================= -QuakeTextureVecs - -Creates world-to-texture mapping vecs for crappy quake plane arrangements -================= -*/ -void QuakeTextureVecs( plane_t *plane, vec_t shift[2], vec_t rotate, vec_t scale[2], - vec_t mappingVecs[2][4] ) { - - vec3_t vecs[2]; - int sv, tv; - vec_t ang, sinv, cosv; - vec_t ns, nt; - int i, j; - - TextureAxisFromPlane(plane, vecs[0], vecs[1]); - - if (!scale[0]) - scale[0] = 1; - if (!scale[1]) - scale[1] = 1; - - // rotate axis - if (rotate == 0) - { sinv = 0 ; cosv = 1; } - else if (rotate == 90) - { sinv = 1 ; cosv = 0; } - else if (rotate == 180) - { sinv = 0 ; cosv = -1; } - else if (rotate == 270) - { sinv = -1 ; cosv = 0; } - else - { - ang = rotate / 180 * Q_PI; - sinv = sin(ang); - cosv = cos(ang); - } - - if (vecs[0][0]) - sv = 0; - else if (vecs[0][1]) - sv = 1; - else - sv = 2; - - if (vecs[1][0]) - tv = 0; - else if (vecs[1][1]) - tv = 1; - else - tv = 2; - - for (i=0 ; i<2 ; i++) { - ns = cosv * vecs[i][sv] - sinv * vecs[i][tv]; - nt = sinv * vecs[i][sv] + cosv * vecs[i][tv]; - vecs[i][sv] = ns; - vecs[i][tv] = nt; - } - - for (i=0 ; i<2 ; i++) - for (j=0 ; j<3 ; j++) - mappingVecs[i][j] = vecs[i][j] / scale[i]; - - mappingVecs[0][3] = shift[0]; - mappingVecs[1][3] = shift[1]; -} - -//====================================================================== - -/* -================= -ParseRawBrush - -Just parses the sides into buildBrush->sides[], nothing else. -no validation, back plane removal, etc. - -Timo - 08/26/99 -added brush epairs parsing ( ignoring actually ) -Timo - 08/04/99 -added exclusive brush primitive parsing -Timo - 08/08/99 -support for old brush format back in -NOTE : it would be "cleaner" to have seperate functions to parse between old and new brushes -================= -*/ -void ParseRawBrush( ) { - side_t *side; - vec3_t planepts[3]; - int planenum; - shaderInfo_t *si; - // old brushes - vec_t shift[2]; - vec_t rotate; - vec_t scale[2]; - char name[MAX_QPATH]; - char shader[MAX_QPATH]; - int flags; - - buildBrush->numsides = 0; - buildBrush->detail = qfalse; - - if (g_bBrushPrimit==BPRIMIT_NEWBRUSHES) - MatchToken( "{" ); - - do - { - if (!GetToken (qtrue)) - break; - if (!strcmp (token, "}") ) - break; - //Timo : brush primitive : here we may have to jump over brush epairs ( only used in editor ) - if (g_bBrushPrimit==BPRIMIT_NEWBRUSHES) - { - do - { - if (strcmp (token, "(") ) - GetToken( qfalse ); - else - break; - GetToken( qtrue ); - } while (1); - } - UnGetToken(); - - if ( buildBrush->numsides == MAX_BUILD_SIDES ) { - Error( "MAX_BUILD_SIDES" ); - } - - side = &buildBrush->sides[ buildBrush->numsides ]; - memset( side, 0, sizeof( *side ) ); - buildBrush->numsides++; - - // read the three point plane definition - Parse1DMatrix( 3, planepts[0] ); - Parse1DMatrix( 3, planepts[1] ); - Parse1DMatrix( 3, planepts[2] ); - - if (g_bBrushPrimit==BPRIMIT_NEWBRUSHES) - // read the texture matrix - Parse2DMatrix( 2, 3, (float *)side->texMat ); - - // read the texturedef - GetToken (qfalse); - strcpy (name, token); - - // save the shader name for retexturing - if ( numMapIndexedShaders == MAX_MAP_BRUSHSIDES ) { - Error( "MAX_MAP_BRUSHSIDES" ); - } - strcpy( mapIndexedShaders[numMapIndexedShaders], name ); - numMapIndexedShaders++; - - if (g_bBrushPrimit==BPRIMIT_OLDBRUSHES) - { - GetToken (qfalse); - shift[0] = atoi(token); - GetToken (qfalse); - shift[1] = atoi(token); - GetToken (qfalse); - rotate = atoi(token); - GetToken (qfalse); - scale[0] = atof(token); - GetToken (qfalse); - scale[1] = atof(token); - } - - // find default flags and values - sprintf( shader, "textures/%s", name ); - si = ShaderInfoForShader( shader ); - side->shaderInfo = si; - side->surfaceFlags = si->surfaceFlags; - side->value = si->value; - side->contents = si->contents; - - // allow override of default flags and values - // in Q3, the only thing you can override is DETAIL - if (TokenAvailable()) - { - GetToken (qfalse); -// side->contents = atoi(token); - flags = atoi(token); - if ( flags & CONTENTS_DETAIL ) { - side->contents |= CONTENTS_DETAIL; - } - - GetToken (qfalse); -// td.flags = atoi(token); - - GetToken (qfalse); -// td.value = atoi(token); - } - - - // find the plane number - planenum = MapPlaneFromPoints (planepts[0], planepts[1], planepts[2]); - side->planenum = planenum; - - if (g_bBrushPrimit==BPRIMIT_OLDBRUSHES) - // get the texture mapping for this texturedef / plane combination - QuakeTextureVecs( &mapplanes[planenum], shift, rotate, scale, side->vecs ); - - } while (1); - - if (g_bBrushPrimit==BPRIMIT_NEWBRUSHES) - { - UnGetToken(); - MatchToken( "}" ); - MatchToken( "}" ); - } -} - -/* -================= -RemoveDuplicateBrushPlanes - -Returns false if the brush has a mirrored set of planes, -meaning it encloses no volume. -Also removes planes without any normal -================= -*/ -qboolean RemoveDuplicateBrushPlanes( bspbrush_t * b ) { - int i, j, k; - side_t *sides; - - sides = b->sides; - - for ( i = 1 ; i < b->numsides ; i++ ) { - - // check for a degenerate plane - if ( sides[i].planenum == -1) { - _printf ("Entity %i, Brush %i: degenerate plane\n" - , b->entitynum, b->brushnum); - // remove it - for ( k = i + 1 ; k < b->numsides ; k++ ) { - sides[k-1] = sides[k]; - } - b->numsides--; - i--; - continue; - } - - // check for duplication and mirroring - for ( j = 0 ; j < i ; j++ ) { - if ( sides[i].planenum == sides[j].planenum ) { - _printf ("Entity %i, Brush %i: duplicate plane\n" - , b->entitynum, b->brushnum); - // remove the second duplicate - for ( k = i + 1 ; k < b->numsides ; k++ ) { - sides[k-1] = sides[k]; - } - b->numsides--; - i--; - break; - } - - if ( sides[i].planenum == (sides[j].planenum ^ 1) ) { - // mirror plane, brush is invalid - _printf ("Entity %i, Brush %i: mirrored plane\n" - , b->entitynum, b->brushnum); - return qfalse; - } - } - } - return qtrue; -} - - -/* -================= -ParseBrush - - qboolean parameter to true -> parse new brush primitive format ( else use old format ) -================= -*/ -void ParseBrush (void) { - bspbrush_t *b; - - ParseRawBrush(); - - buildBrush->portalareas[0] = -1; - buildBrush->portalareas[1] = -1; - buildBrush->entitynum = num_entities-1; - buildBrush->brushnum = entitySourceBrushes; - - // if there are mirrored planes, the entire brush is invalid - if ( !RemoveDuplicateBrushPlanes( buildBrush ) ) { - return; - } - - // get the content for the entire brush - SetBrushContents( buildBrush ); - - // allow detail brushes to be removed - if (nodetail && (buildBrush->contents & CONTENTS_DETAIL) ) { - FreeBrush( buildBrush ); - return; - } - - // allow water brushes to be removed - if (nowater && (buildBrush->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) ) { - FreeBrush( buildBrush ); - return; - } - - b = FinishBrush( ); - if ( !b ) { - return; - } -} - - -/* -================ -MoveBrushesToWorld - -Takes all of the brushes from the current entity and -adds them to the world's brush list. - -Used by func_group -================ -*/ -void MoveBrushesToWorld (entity_t *mapent) { - bspbrush_t *b, *next; - parseMesh_t *pm; - - // move brushes - for ( b = mapent->brushes ; b ; b = next ) { - next = b->next; - - b->next = entities[0].brushes; - entities[0].brushes = b; - } - mapent->brushes = NULL; - - // move patches - if ( mapent->patches ) { - - for ( pm = mapent->patches ; pm->next ; pm = pm->next ) { - } - - pm->next = entities[0].patches; - entities[0].patches = mapent->patches; - - mapent->patches = NULL; - } -} - - -/* -================ -AdjustBrushesForOrigin -================ -*/ -void AdjustBrushesForOrigin( entity_t *ent ) { - bspbrush_t *b; - int i; - side_t *s; - vec_t newdist; - parseMesh_t *p; - - for ( b = ent->brushes ; b ; b = b->next ) { - for (i=0 ; i<b->numsides ; i++) { - s = &b->sides[i]; - newdist = mapplanes[s->planenum].dist - - DotProduct (mapplanes[s->planenum].normal, ent->origin); - s->planenum = FindFloatPlane (mapplanes[s->planenum].normal, newdist); - } - CreateBrushWindings(b); - } - - for ( p = ent->patches ; p ; p = p->next ) { - for ( i = 0 ; i < p->mesh.width*p->mesh.height ; i++ ) { - VectorSubtract( p->mesh.verts[i].xyz, ent->origin, p->mesh.verts[i].xyz ); - } - } - -} - -/* -================ -ParseMapEntity -================ -*/ -qboolean ParseMapEntity (void) { - epair_t *e; - - if (!GetToken (qtrue)) - return qfalse; - - if (strcmp (token, "{") ) - { - Error ("ParseEntity: { not found, found %s on line %d - last entity was at: <%4.2f, %4.2f, %4.2f>...", token, scriptline, entities[num_entities].origin[0], entities[num_entities].origin[1], entities[num_entities].origin[2]); - } - - if (num_entities == MAX_MAP_ENTITIES) - Error ("num_entities == MAX_MAP_ENTITIES"); - - entitySourceBrushes = 0; - - mapent = &entities[num_entities]; - num_entities++; - memset (mapent, 0, sizeof(*mapent)); - - do - { - if (!GetToken (qtrue)) - Error ("ParseEntity: EOF without closing brace"); - if (!strcmp (token, "}") ) - break; - - if (!strcmp (token, "{") ) { - // parse a brush or patch - if (!GetToken (qtrue)) - break; - if ( !strcmp( token, "patchDef2" ) ) { - numMapPatches++; - ParsePatch(); - } else if ( !strcmp( token, "terrainDef" ) ) { - ParseTerrain(); - } else if ( !strcmp( token, "brushDef" ) ) { - if (g_bBrushPrimit==BPRIMIT_OLDBRUSHES) - Error("old brush format not allowed in new brush format map"); - g_bBrushPrimit=BPRIMIT_NEWBRUSHES; - // parse brush primitive - ParseBrush(); - } - else - { - if (g_bBrushPrimit==BPRIMIT_NEWBRUSHES) - Error("new brush format not allowed in old brush format map"); - g_bBrushPrimit=BPRIMIT_OLDBRUSHES; - // parse old brush format - UnGetToken(); - ParseBrush(); - } - entitySourceBrushes++; - } - else - { - // parse a key / value pair - e = ParseEpair (); - e->next = mapent->epairs; - mapent->epairs = e; - } - } while (1); - - GetVectorForKey (mapent, "origin", mapent->origin); - - // - // if there was an origin brush, offset all of the planes and texinfo - // for all the brushes in the entity - if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2]) { - AdjustBrushesForOrigin( mapent ); - } - - // group_info entities are just for editor grouping - // ignored - // FIXME: leak! - if (!strcmp("group_info", ValueForKey (mapent, "classname"))) - { - num_entities--; - return qtrue; - } - - // group entities are just for editor convenience - // toss all brushes into the world entity - if (!strcmp ("func_group", ValueForKey (mapent, "classname"))) - { - if ( !strcmp ("1", ValueForKey (mapent, "terrain"))) { - SetTerrainTextures(); - } - MoveBrushesToWorld (mapent); - num_entities--; - return qtrue; - } - - return qtrue; -} - -//=================================================================== - - -/* -================ -LoadMapFile -================ -*/ -void LoadMapFile (char *filename) { - bspbrush_t *b; - - qprintf ("--- LoadMapFile ---\n"); - _printf ("Loading map file %s\n", filename); - - LoadScriptFile (filename); - - num_entities = 0; - numMapDrawSurfs = 0; - c_detail = 0; - - g_bBrushPrimit = BPRIMIT_UNDEFINED; - - // allocate a very large temporary brush for building - // the brushes as they are loaded - buildBrush = AllocBrush( MAX_BUILD_SIDES ); - - while (ParseMapEntity ()) - { - } - - ClearBounds (map_mins, map_maxs); - for ( b = entities[0].brushes ; b ; b=b->next ) { - AddPointToBounds( b->mins, map_mins, map_maxs ); - AddPointToBounds( b->maxs, map_mins, map_maxs ); - } - - qprintf ("%5i total world brushes\n", CountBrushList( entities[0].brushes ) ); - qprintf ("%5i detail brushes\n", c_detail ); - qprintf ("%5i patches\n", numMapPatches); - qprintf ("%5i boxbevels\n", c_boxbevels); - qprintf ("%5i edgebevels\n", c_edgebevels); - qprintf ("%5i entities\n", num_entities); - qprintf ("%5i planes\n", nummapplanes); - qprintf ("%5i areaportals\n", c_areaportals); - qprintf ("size: %5.0f,%5.0f,%5.0f to %5.0f,%5.0f,%5.0f\n", map_mins[0],map_mins[1],map_mins[2], - map_maxs[0],map_maxs[1],map_maxs[2]); - - if ( fakemap ) { - WriteBspBrushMap ("fakemap.map", entities[0].brushes ); - } - - if ( testExpand ) { - TestExpandBrushes (); - } -} - - -//==================================================================== - - -/* -================ -TestExpandBrushes - -Expands all the brush planes and saves a new map out to -allow visual inspection of the clipping bevels -================ -*/ -void TestExpandBrushes( void ) { - side_t *s; - int i, j; - bspbrush_t *brush, *list, *copy; - vec_t dist; - plane_t *plane; - - list = NULL; - - for ( brush = entities[0].brushes ; brush ; brush = brush->next ) { - copy = CopyBrush( brush ); - copy->next = list; - list = copy; - - // expand all the planes - for ( i=0 ; i<brush->numsides ; i++ ) { - s = brush->sides + i; - plane = &mapplanes[s->planenum]; - dist = plane->dist; - for (j=0 ; j<3 ; j++) { - dist += fabs( 16 * plane->normal[j] ); - } - s->planenum = FindFloatPlane( plane->normal, dist ); - } - - } - - WriteBspBrushMap ( "expanded.map", entities[0].brushes ); - - Error ("can't proceed after expanding brushes"); -} diff --git a/q3map/mesh.c b/q3map/mesh.c deleted file mode 100644 index e2b3010..0000000 --- a/q3map/mesh.c +++ /dev/null @@ -1,682 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "qbsp.h" - - -/* -=============================================================== - -MESH SUBDIVISION - -=============================================================== -*/ - - -int originalWidths[MAX_EXPANDED_AXIS]; -int originalHeights[MAX_EXPANDED_AXIS]; - -int neighbors[8][2] = { - {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {-1,1} -}; - -/* -============ -LerpDrawVert -============ -*/ -void LerpDrawVert( drawVert_t *a, drawVert_t *b, drawVert_t *out ) { - out->xyz[0] = 0.5 * (a->xyz[0] + b->xyz[0]); - out->xyz[1] = 0.5 * (a->xyz[1] + b->xyz[1]); - out->xyz[2] = 0.5 * (a->xyz[2] + b->xyz[2]); - - out->st[0] = 0.5 * (a->st[0] + b->st[0]); - out->st[1] = 0.5 * (a->st[1] + b->st[1]); - - out->lightmap[0] = 0.5 * (a->lightmap[0] + b->lightmap[0]); - out->lightmap[1] = 0.5 * (a->lightmap[1] + b->lightmap[1]); - - out->color[0] = (a->color[0] + b->color[0]) >> 1; - out->color[1] = (a->color[1] + b->color[1]) >> 1; - out->color[2] = (a->color[2] + b->color[2]) >> 1; - out->color[3] = (a->color[3] + b->color[3]) >> 1; -} - - -void FreeMesh( mesh_t *m ) { - free( m->verts ); - free( m ); -} - -void PrintMesh( mesh_t *m ) { - int i, j; - - for ( i = 0 ; i < m->height ; i++ ) { - for ( j = 0 ; j < m->width ; j++ ) { - _printf("(%5.2f %5.2f %5.2f) " - , m->verts[i*m->width+j].xyz[0] - , m->verts[i*m->width+j].xyz[1] - , m->verts[i*m->width+j].xyz[2] ); - } - _printf("\n"); - } -} - - -mesh_t *CopyMesh( mesh_t *mesh ) { - mesh_t *out; - int size; - - out = malloc( sizeof( *out ) ); - out->width = mesh->width; - out->height = mesh->height; - - size = out->width * out->height * sizeof( *out->verts ); - out->verts = malloc( size ); - memcpy( out->verts, mesh->verts, size ); - - return out; -} - - -/* -================= -TransposeMesh - -Returns a transposed copy of the mesh, freeing the original -================= -*/ -mesh_t *TransposeMesh( mesh_t *in ) { - int w, h; - mesh_t *out; - - out = malloc( sizeof( *out ) ); - out->width = in->height; - out->height = in->width; - out->verts = malloc( out->width * out->height * sizeof( drawVert_t ) ); - - for ( h = 0 ; h < in->height ; h++ ) { - for ( w = 0 ; w < in->width ; w++ ) { - out->verts[ w * in->height + h ] = in->verts[ h * in->width + w ]; - } - } - - FreeMesh( in ); - - return out; -} - -void InvertMesh( mesh_t *in ) { - int w, h; - drawVert_t temp; - - for ( h = 0 ; h < in->height ; h++ ) { - for ( w = 0 ; w < in->width / 2 ; w++ ) { - temp = in->verts[ h * in->width + w ]; - in->verts[ h * in->width + w ] = in->verts[ h * in->width + in->width - 1 - w ]; - in->verts[ h * in->width + in->width - 1 - w ] = temp; - } - } -} - -/* -================= -MakeMeshNormals - -================= -*/ -void MakeMeshNormals( mesh_t in ) { - int i, j, k, dist; - vec3_t normal; - vec3_t sum; - int count; - vec3_t base; - vec3_t delta; - int x, y; - drawVert_t *dv; - vec3_t around[8], temp; - qboolean good[8]; - qboolean wrapWidth, wrapHeight; - float len; - - wrapWidth = qfalse; - for ( i = 0 ; i < in.height ; i++ ) { - VectorSubtract( in.verts[i*in.width].xyz, - in.verts[i*in.width+in.width-1].xyz, delta ); - len = VectorLength( delta ); - if ( len > 1.0 ) { - break; - } - } - if ( i == in.height ) { - wrapWidth = qtrue; - } - - wrapHeight = qfalse; - for ( i = 0 ; i < in.width ; i++ ) { - VectorSubtract( in.verts[i].xyz, - in.verts[i + (in.height-1)*in.width].xyz, delta ); - len = VectorLength( delta ); - if ( len > 1.0 ) { - break; - } - } - if ( i == in.width) { - wrapHeight = qtrue; - } - - - for ( i = 0 ; i < in.width ; i++ ) { - for ( j = 0 ; j < in.height ; j++ ) { - count = 0; - dv = &in.verts[j*in.width+i]; - VectorCopy( dv->xyz, base ); - for ( k = 0 ; k < 8 ; k++ ) { - VectorClear( around[k] ); - good[k] = qfalse; - - for ( dist = 1 ; dist <= 3 ; dist++ ) { - x = i + neighbors[k][0] * dist; - y = j + neighbors[k][1] * dist; - if ( wrapWidth ) { - if ( x < 0 ) { - x = in.width - 1 + x; - } else if ( x >= in.width ) { - x = 1 + x - in.width; - } - } - if ( wrapHeight ) { - if ( y < 0 ) { - y = in.height - 1 + y; - } else if ( y >= in.height ) { - y = 1 + y - in.height; - } - } - - if ( x < 0 || x >= in.width || y < 0 || y >= in.height ) { - break; // edge of patch - } - VectorSubtract( in.verts[y*in.width+x].xyz, base, temp ); - if ( VectorNormalize( temp, temp ) == 0 ) { - continue; // degenerate edge, get more dist - } else { - good[k] = qtrue; - VectorCopy( temp, around[k] ); - break; // good edge - } - } - } - - VectorClear( sum ); - for ( k = 0 ; k < 8 ; k++ ) { - if ( !good[k] || !good[(k+1)&7] ) { - continue; // didn't get two points - } - CrossProduct( around[(k+1)&7], around[k], normal ); - if ( VectorNormalize( normal, normal ) == 0 ) { - continue; - } - VectorAdd( normal, sum, sum ); - count++; - } - if ( count == 0 ) { -//_printf("bad normal\n"); - count = 1; - } - VectorNormalize( sum, dv->normal ); - } - } -} - -/* -================= -PutMeshOnCurve - -Drops the aproximating points onto the curve -================= -*/ -void PutMeshOnCurve( mesh_t in ) { - int i, j, l; - float prev, next; - - // put all the aproximating points on the curve - for ( i = 0 ; i < in.width ; i++ ) { - for ( j = 1 ; j < in.height ; j += 2 ) { - for ( l = 0 ; l < 3 ; l++ ) { - prev = ( in.verts[j*in.width+i].xyz[l] + in.verts[(j+1)*in.width+i].xyz[l] ) * 0.5; - next = ( in.verts[j*in.width+i].xyz[l] + in.verts[(j-1)*in.width+i].xyz[l] ) * 0.5; - in.verts[j*in.width+i].xyz[l] = ( prev + next ) * 0.5; - } - } - } - - for ( j = 0 ; j < in.height ; j++ ) { - for ( i = 1 ; i < in.width ; i += 2 ) { - for ( l = 0 ; l < 3 ; l++ ) { - prev = ( in.verts[j*in.width+i].xyz[l] + in.verts[j*in.width+i+1].xyz[l] ) * 0.5; - next = ( in.verts[j*in.width+i].xyz[l] + in.verts[j*in.width+i-1].xyz[l] ) * 0.5; - in.verts[j*in.width+i].xyz[l] = ( prev + next ) * 0.5; - } - } - } -} - - -/* -================= -SubdivideMesh - -================= -*/ -mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength ) { - int i, j, k, l; - drawVert_t prev, next, mid; - vec3_t prevxyz, nextxyz, midxyz; - vec3_t delta; - float len; - mesh_t out; - drawVert_t expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS]; - - out.width = in.width; - out.height = in.height; - - for ( i = 0 ; i < in.width ; i++ ) { - for ( j = 0 ; j < in.height ; j++ ) { - expand[j][i] = in.verts[j*in.width+i]; - } - } - - for ( i = 0 ; i < in.height ; i++ ) { - originalHeights[i] = i; - } - for ( i = 0 ; i < in.width ; i++ ) { - originalWidths[i] = i; - } - - // horizontal subdivisions - for ( j = 0 ; j + 2 < out.width ; j += 2 ) { - // check subdivided midpoints against control points - for ( i = 0 ; i < out.height ; i++ ) { - for ( l = 0 ; l < 3 ; l++ ) { - prevxyz[l] = expand[i][j+1].xyz[l] - expand[i][j].xyz[l]; - nextxyz[l] = expand[i][j+2].xyz[l] - expand[i][j+1].xyz[l]; - midxyz[l] = (expand[i][j].xyz[l] + expand[i][j+1].xyz[l] * 2 - + expand[i][j+2].xyz[l] ) * 0.25; - } - - // if the span length is too long, force a subdivision - if ( VectorLength( prevxyz ) > minLength - || VectorLength( nextxyz ) > minLength ) { - break; - } - - // see if this midpoint is off far enough to subdivide - VectorSubtract( expand[i][j+1].xyz, midxyz, delta ); - len = VectorLength( delta ); - if ( len > maxError ) { - break; - } - } - - if ( out.width + 2 >= MAX_EXPANDED_AXIS ) { - break; // can't subdivide any more - } - - if ( i == out.height ) { - continue; // didn't need subdivision - } - - // insert two columns and replace the peak - out.width += 2; - - for ( k = out.width - 1 ; k > j + 3 ; k-- ) { - originalWidths[k] = originalWidths[k-2]; - } - originalWidths[j+3] = originalWidths[j+1]; - originalWidths[j+2] = originalWidths[j+1]; - originalWidths[j+1] = originalWidths[j]; - - for ( i = 0 ; i < out.height ; i++ ) { - LerpDrawVert( &expand[i][j], &expand[i][j+1], &prev ); - LerpDrawVert( &expand[i][j+1], &expand[i][j+2], &next ); - LerpDrawVert( &prev, &next, &mid ); - - for ( k = out.width - 1 ; k > j + 3 ; k-- ) { - expand[i][k] = expand[i][k-2]; - } - expand[i][j + 1] = prev; - expand[i][j + 2] = mid; - expand[i][j + 3] = next; - } - - // back up and recheck this set again, it may need more subdivision - j -= 2; - - } - - // vertical subdivisions - for ( j = 0 ; j + 2 < out.height ; j += 2 ) { - // check subdivided midpoints against control points - for ( i = 0 ; i < out.width ; i++ ) { - for ( l = 0 ; l < 3 ; l++ ) { - prevxyz[l] = expand[j+1][i].xyz[l] - expand[j][i].xyz[l]; - nextxyz[l] = expand[j+2][i].xyz[l] - expand[j+1][i].xyz[l]; - midxyz[l] = (expand[j][i].xyz[l] + expand[j+1][i].xyz[l] * 2 - + expand[j+2][i].xyz[l] ) * 0.25; - } - - // if the span length is too long, force a subdivision - if ( VectorLength( prevxyz ) > minLength - || VectorLength( nextxyz ) > minLength ) { - break; - } - // see if this midpoint is off far enough to subdivide - VectorSubtract( expand[j+1][i].xyz, midxyz, delta ); - len = VectorLength( delta ); - if ( len > maxError ) { - break; - } - } - - if ( out.height + 2 >= MAX_EXPANDED_AXIS ) { - break; // can't subdivide any more - } - - if ( i == out.width ) { - continue; // didn't need subdivision - } - - // insert two columns and replace the peak - out.height += 2; - - for ( k = out.height - 1 ; k > j + 3 ; k-- ) { - originalHeights[k] = originalHeights[k-2]; - } - originalHeights[j+3] = originalHeights[j+1]; - originalHeights[j+2] = originalHeights[j+1]; - originalHeights[j+1] = originalHeights[j]; - - for ( i = 0 ; i < out.width ; i++ ) { - LerpDrawVert( &expand[j][i], &expand[j+1][i], &prev ); - LerpDrawVert( &expand[j+1][i], &expand[j+2][i], &next ); - LerpDrawVert( &prev, &next, &mid ); - - for ( k = out.height - 1 ; k > j + 3 ; k-- ) { - expand[k][i] = expand[k-2][i]; - } - expand[j+1][i] = prev; - expand[j+2][i] = mid; - expand[j+3][i] = next; - } - - // back up and recheck this set again, it may need more subdivision - j -= 2; - - } - - // collapse the verts - - out.verts = &expand[0][0]; - for ( i = 1 ; i < out.height ; i++ ) { - memmove( &out.verts[i*out.width], expand[i], out.width * sizeof(drawVert_t) ); - } - - return CopyMesh(&out); -} - -/* -================ -ProjectPointOntoVector -================ -*/ -void ProjectPointOntoVector( vec3_t point, vec3_t vStart, vec3_t vEnd, vec3_t vProj ) -{ - vec3_t pVec, vec; - - VectorSubtract( point, vStart, pVec ); - VectorSubtract( vEnd, vStart, vec ); - VectorNormalize( vec, vec ); - // project onto the directional vector for this segment - VectorMA( vStart, DotProduct( pVec, vec ), vec, vProj ); -} - -/* -================ -RemoveLinearMeshColumsRows -================ -*/ -mesh_t *RemoveLinearMeshColumnsRows( mesh_t *in ) { - int i, j, k; - float len, maxLength; - vec3_t proj, dir; - mesh_t out; - drawVert_t expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS]; - - out.width = in->width; - out.height = in->height; - - for ( i = 0 ; i < in->width ; i++ ) { - for ( j = 0 ; j < in->height ; j++ ) { - expand[j][i] = in->verts[j*in->width+i]; - } - } - - for ( j = 1 ; j < out.width - 1; j++ ) { - maxLength = 0; - for ( i = 0 ; i < out.height ; i++ ) { - ProjectPointOntoVector(expand[i][j].xyz, expand[i][j-1].xyz, expand[i][j+1].xyz, proj); - VectorSubtract(expand[i][j].xyz, proj, dir); - len = VectorLength(dir); - if (len > maxLength) { - maxLength = len; - } - } - if (maxLength < 0.1) - { - out.width--; - for ( i = 0 ; i < out.height ; i++ ) { - for (k = j; k < out.width; k++) { - expand[i][k] = expand[i][k+1]; - } - } - for (k = j; k < out.width; k++) { - originalWidths[k] = originalWidths[k+1]; - } - j--; - } - } - for ( j = 1 ; j < out.height - 1; j++ ) { - maxLength = 0; - for ( i = 0 ; i < out.width ; i++ ) { - ProjectPointOntoVector(expand[j][i].xyz, expand[j-1][i].xyz, expand[j+1][i].xyz, proj); - VectorSubtract(expand[j][i].xyz, proj, dir); - len = VectorLength(dir); - if (len > maxLength) { - maxLength = len; - } - } - if (maxLength < 0.1) - { - out.height--; - for ( i = 0 ; i < out.width ; i++ ) { - for (k = j; k < out.height; k++) { - expand[k][i] = expand[k+1][i]; - } - } - for (k = j; k < out.height; k++) { - originalHeights[k] = originalHeights[k+1]; - } - j--; - } - } - // collapse the verts - out.verts = &expand[0][0]; - for ( i = 1 ; i < out.height ; i++ ) { - memmove( &out.verts[i*out.width], expand[i], out.width * sizeof(drawVert_t) ); - } - - return CopyMesh(&out); -} - -/* -============ -LerpDrawVertAmount -============ -*/ -void LerpDrawVertAmount( drawVert_t *a, drawVert_t *b, float amount, drawVert_t *out ) { - out->xyz[0] = a->xyz[0] + amount * (b->xyz[0] - a->xyz[0]); - out->xyz[1] = a->xyz[1] + amount * (b->xyz[1] - a->xyz[1]); - out->xyz[2] = a->xyz[2] + amount * (b->xyz[2] - a->xyz[2]); - - out->st[0] = a->st[0] + amount * (b->st[0] - a->st[0]); - out->st[1] = a->st[1] + amount * (b->st[1] - a->st[1]); - - out->lightmap[0] = a->lightmap[0] + amount * (b->lightmap[0] - a->lightmap[0]); - out->lightmap[1] = a->lightmap[1] + amount * (b->lightmap[1] - a->lightmap[1]); - - out->color[0] = a->color[0] + amount * (b->color[0] - a->color[0]); - out->color[1] = a->color[1] + amount * (b->color[1] - a->color[1]); - out->color[2] = a->color[2] + amount * (b->color[2] - a->color[2]); - out->color[3] = a->color[3] + amount * (b->color[3] - a->color[3]); - - out->normal[0] = a->normal[0] + amount * (b->normal[0] - a->normal[0]); - out->normal[1] = a->normal[1] + amount * (b->normal[1] - a->normal[1]); - out->normal[2] = a->normal[2] + amount * (b->normal[2] - a->normal[2]); - VectorNormalize(out->normal, out->normal); -} - -/* -================= -SubdivideMeshQuads -================= -*/ -mesh_t *SubdivideMeshQuads( mesh_t *in, float minLength, int maxsize, int widthtable[], int heighttable[]) { - int i, j, k, w, h, maxsubdivisions, subdivisions; - vec3_t dir; - float length, maxLength, amount; - mesh_t out; - drawVert_t expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS]; - - out.width = in->width; - out.height = in->height; - - for ( i = 0 ; i < in->width ; i++ ) { - for ( j = 0 ; j < in->height ; j++ ) { - expand[j][i] = in->verts[j*in->width+i]; - } - } - - if (maxsize > MAX_EXPANDED_AXIS) - Error("SubdivideMeshQuads: maxsize > MAX_EXPANDED_AXIS"); - - // horizontal subdivisions - - maxsubdivisions = (maxsize - in->width) / (in->width - 1); - - for ( w = 0, j = 0 ; w < in->width - 1; w++, j += subdivisions + 1) { - maxLength = 0; - for ( i = 0 ; i < out.height ; i++ ) { - VectorSubtract(expand[i][j+1].xyz, expand[i][j].xyz, dir); - length = VectorLength( dir ); - if (length > maxLength) { - maxLength = length; - } - } - - subdivisions = (int) (maxLength / minLength); - if (subdivisions > maxsubdivisions) - subdivisions = maxsubdivisions; - - widthtable[w] = subdivisions + 1; - if (subdivisions <= 0) - continue; - - out.width += subdivisions; - - for ( k = out.width - 1; k >= j + subdivisions; k-- ) { - originalWidths[k] = originalWidths[k-subdivisions]; - } - for (k = 1; k <= subdivisions; k++) { - originalWidths[j+k] = originalWidths[j]; - } - - for ( i = 0 ; i < out.height ; i++ ) { - for ( k = out.width - 1 ; k > j + subdivisions; k-- ) { - expand[i][k] = expand[i][k-subdivisions]; - } - for (k = 1; k <= subdivisions; k++) - { - amount = (float) k / (subdivisions + 1); - LerpDrawVertAmount(&expand[i][j], &expand[i][j+subdivisions+1], amount, &expand[i][j+k]); - } - } - } - - maxsubdivisions = (maxsize - in->height) / (in->height - 1); - - for ( h = 0, j = 0 ; h < in->height - 1; h++, j += subdivisions + 1) { - maxLength = 0; - for ( i = 0 ; i < out.width ; i++ ) { - VectorSubtract(expand[j+1][i].xyz, expand[j][i].xyz, dir); - length = VectorLength( dir ); - if (length > maxLength) { - maxLength = length; - } - } - - subdivisions = (int) (maxLength / minLength); - if (subdivisions > maxsubdivisions) - subdivisions = maxsubdivisions; - - heighttable[h] = subdivisions + 1; - if (subdivisions <= 0) - continue; - - out.height += subdivisions; - - for ( k = out.height - 1; k >= j + subdivisions; k-- ) { - originalHeights[k] = originalHeights[k-subdivisions]; - } - for (k = 1; k <= subdivisions; k++) { - originalHeights[j+k] = originalHeights[j]; - } - - for ( i = 0 ; i < out.width ; i++ ) { - for ( k = out.height - 1 ; k > j + subdivisions; k-- ) { - expand[k][i] = expand[k-subdivisions][i]; - } - for (k = 1; k <= subdivisions; k++) - { - amount = (float) k / (subdivisions + 1); - LerpDrawVertAmount(&expand[j][i], &expand[j+subdivisions+1][i], amount, &expand[j+k][i]); - } - } - } - - // collapse the verts - out.verts = &expand[0][0]; - for ( i = 1 ; i < out.height ; i++ ) { - memmove( &out.verts[i*out.width], expand[i], out.width * sizeof(drawVert_t) ); - } - - return CopyMesh(&out); -} diff --git a/q3map/mesh.h b/q3map/mesh.h deleted file mode 100644 index ee338d4..0000000 --- a/q3map/mesh.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -// mesh.h - - -typedef struct { - int width, height; - drawVert_t *verts; -} mesh_t; - -#define MAX_EXPANDED_AXIS 128 - -extern int originalWidths[MAX_EXPANDED_AXIS]; -extern int originalHeights[MAX_EXPANDED_AXIS]; - -void FreeMesh( mesh_t *m ); -mesh_t *CopyMesh( mesh_t *mesh ); -void PrintMesh( mesh_t *m ); -mesh_t *TransposeMesh( mesh_t *in ); -void InvertMesh( mesh_t *m ); -mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength ); -mesh_t *SubdivideMeshQuads( mesh_t *in, float minLength, int maxsize, int widthtable[], int heighttable[]); -mesh_t *RemoveLinearMeshColumnsRows( mesh_t *in ); -void MakeMeshNormals( mesh_t in ); -void PutMeshOnCurve( mesh_t in ); - - -void MakeNormalVectors (vec3_t forward, vec3_t right, vec3_t up); diff --git a/q3map/misc_model.c b/q3map/misc_model.c deleted file mode 100644 index cd003d6..0000000 --- a/q3map/misc_model.c +++ /dev/null @@ -1,472 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "qbsp.h" -#include "aselib.h" -#ifdef _WIN32 -#ifdef _TTIMOBUILD -#include "pakstuff.h" -#else -#include "../libs/pakstuff.h" -#endif -#endif - - -typedef struct { - char modelName[1024]; - md3Header_t *header; -} loadedModel_t; - -int c_triangleModels; -int c_triangleSurfaces; -int c_triangleVertexes; -int c_triangleIndexes; - - -#define MAX_LOADED_MODELS 1024 -loadedModel_t loadedModels[MAX_LOADED_MODELS]; -int numLoadedModels; - -/* -================= -R_LoadMD3 -================= -*/ -#define LL(x) x=LittleLong(x) -md3Header_t *R_LoadMD3( const char *mod_name ) { - int i, j; - md3Header_t *md3; - md3Frame_t *frame; - md3Surface_t *surf; - md3Triangle_t *tri; - md3St_t *st; - md3XyzNormal_t *xyz; - int version; - char filename[1024]; - int len; - - sprintf( filename, "%s%s", gamedir, mod_name ); - len = TryLoadFile( filename, (void **)&md3 ); -#ifdef _WIN32 - if ( len <= 0 ) { - len = PakLoadAnyFile(filename, (void **)&md3); - } -#endif - if ( len <= 0 ) { - return NULL; - } - - version = LittleLong (md3->version); - if (version != MD3_VERSION) { - _printf( "R_LoadMD3: %s has wrong version (%i should be %i)\n", - mod_name, version, MD3_VERSION); - return NULL; - } - - LL(md3->ident); - LL(md3->version); - LL(md3->numFrames); - LL(md3->numTags); - LL(md3->numSurfaces); - LL(md3->numSkins); - LL(md3->ofsFrames); - LL(md3->ofsTags); - LL(md3->ofsSurfaces); - LL(md3->ofsEnd); - - if ( md3->numFrames < 1 ) { - _printf( "R_LoadMD3: %s has no frames\n", mod_name ); - return NULL; - } - - // we don't need to swap tags in the renderer, they aren't used - - // swap all the frames - frame = (md3Frame_t *) ( (byte *)md3 + md3->ofsFrames ); - for ( i = 0 ; i < md3->numFrames ; i++, frame++) { - frame->radius = LittleFloat( frame->radius ); - for ( j = 0 ; j < 3 ; j++ ) { - frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] ); - frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] ); - frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] ); - } - } - - // swap all the surfaces - surf = (md3Surface_t *) ( (byte *)md3 + md3->ofsSurfaces ); - for ( i = 0 ; i < md3->numSurfaces ; i++) { - - LL(surf->ident); - LL(surf->flags); - LL(surf->numFrames); - LL(surf->numShaders); - LL(surf->numTriangles); - LL(surf->ofsTriangles); - LL(surf->numVerts); - LL(surf->ofsShaders); - LL(surf->ofsSt); - LL(surf->ofsXyzNormals); - LL(surf->ofsEnd); - - if ( surf->numVerts > SHADER_MAX_VERTEXES ) { - Error ("R_LoadMD3: %s has more than %i verts on a surface (%i)", - mod_name, SHADER_MAX_VERTEXES, surf->numVerts ); - } - if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) { - Error ("R_LoadMD3: %s has more than %i triangles on a surface (%i)", - mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles ); - } - - // swap all the triangles - tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles ); - for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) { - LL(tri->indexes[0]); - LL(tri->indexes[1]); - LL(tri->indexes[2]); - } - - // swap all the ST - st = (md3St_t *) ( (byte *)surf + surf->ofsSt ); - for ( j = 0 ; j < surf->numVerts ; j++, st++ ) { - st->st[0] = LittleFloat( st->st[0] ); - st->st[1] = LittleFloat( st->st[1] ); - } - - // swap all the XyzNormals - xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals ); - for ( j = 0 ; j < surf->numVerts * surf->numFrames ; j++, xyz++ ) - { - xyz->xyz[0] = LittleShort( xyz->xyz[0] ); - xyz->xyz[1] = LittleShort( xyz->xyz[1] ); - xyz->xyz[2] = LittleShort( xyz->xyz[2] ); - - xyz->normal = LittleShort( xyz->normal ); - } - - - // find the next surface - surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd ); - } - - return md3; -} - - -/* -================ -LoadModel -================ -*/ -md3Header_t *LoadModel( const char *modelName ) { - int i; - loadedModel_t *lm; - - // see if we already have it loaded - for ( i = 0, lm = loadedModels ; i < numLoadedModels ; i++, lm++ ) { - if ( !strcmp( modelName, lm->modelName ) ) { - return lm->header; - } - } - - // load it - if ( numLoadedModels == MAX_LOADED_MODELS ) { - Error( "MAX_LOADED_MODELS" ); - } - numLoadedModels++; - - strcpy( lm->modelName, modelName ); - - lm->header = R_LoadMD3( modelName ); - - return lm->header; -} - -/* -============ -InsertMD3Model - -Convert a model entity to raw geometry surfaces and insert it in the tree -============ -*/ -void InsertMD3Model( const char *modelName, vec3_t origin, float angle, tree_t *tree ) { - int i, j; - md3Header_t *md3; - md3Surface_t *surf; - md3Shader_t *shader; - md3Triangle_t *tri; - md3St_t *st; - md3XyzNormal_t *xyz; - drawVert_t *outv; - float lat, lng; - float angleCos, angleSin; - mapDrawSurface_t *out; - vec3_t temp; - - angle = angle / 180 * Q_PI; - angleCos = cos( angle ); - angleSin = sin( angle ); - - // load the model - md3 = LoadModel( modelName ); - if ( !md3 ) { - return; - } - - // each md3 surface will become a new bsp surface - - c_triangleModels++; - c_triangleSurfaces += md3->numSurfaces; - - // expand, translate, and rotate the vertexes - // swap all the surfaces - surf = (md3Surface_t *) ( (byte *)md3 + md3->ofsSurfaces ); - for ( i = 0 ; i < md3->numSurfaces ; i++) { - // allocate a surface - out = AllocDrawSurf(); - out->miscModel = qtrue; - - shader = (md3Shader_t *) ( (byte *)surf + surf->ofsShaders ); - - out->shaderInfo = ShaderInfoForShader( shader->name ); - - out->numVerts = surf->numVerts; - out->verts = malloc( out->numVerts * sizeof( out->verts[0] ) ); - - out->numIndexes = surf->numTriangles * 3; - out->indexes = malloc( out->numIndexes * sizeof( out->indexes[0] ) ); - - out->lightmapNum = -1; - out->fogNum = -1; - - // emit the indexes - c_triangleIndexes += surf->numTriangles * 3; - tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles ); - for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) { - out->indexes[j*3+0] = tri->indexes[0]; - out->indexes[j*3+1] = tri->indexes[1]; - out->indexes[j*3+2] = tri->indexes[2]; - } - - // emit the vertexes - st = (md3St_t *) ( (byte *)surf + surf->ofsSt ); - xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals ); - - c_triangleVertexes += surf->numVerts; - for ( j = 0 ; j < surf->numVerts ; j++, st++, xyz++ ) { - outv = &out->verts[ j ]; - - outv->st[0] = st->st[0]; - outv->st[1] = st->st[1]; - - outv->lightmap[0] = 0; - outv->lightmap[1] = 0; - - // the colors will be set by the lighting pass - outv->color[0] = 255; - outv->color[1] = 255; - outv->color[2] = 255; - outv->color[3] = 255; - - outv->xyz[0] = origin[0] + MD3_XYZ_SCALE * ( xyz->xyz[0] * angleCos - xyz->xyz[1] * angleSin ); - outv->xyz[1] = origin[1] + MD3_XYZ_SCALE * ( xyz->xyz[0] * angleSin + xyz->xyz[1] * angleCos ); - outv->xyz[2] = origin[2] + MD3_XYZ_SCALE * ( xyz->xyz[2] ); - - // decode the lat/lng normal to a 3 float normal - lat = ( xyz->normal >> 8 ) & 0xff; - lng = ( xyz->normal & 0xff ); - lat *= Q_PI/128; - lng *= Q_PI/128; - - temp[0] = cos(lat) * sin(lng); - temp[1] = sin(lat) * sin(lng); - temp[2] = cos(lng); - - // rotate the normal - outv->normal[0] = temp[0] * angleCos - temp[1] * angleSin; - outv->normal[1] = temp[0] * angleSin + temp[1] * angleCos; - outv->normal[2] = temp[2]; - } - - // find the next surface - surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd ); - } - -} - -//============================================================================== - - -/* -============ -InsertASEModel - -Convert a model entity to raw geometry surfaces and insert it in the tree -============ -*/ -void InsertASEModel( const char *modelName, vec3_t origin, float angle, tree_t *tree ) { - int i, j; - drawVert_t *outv; - float angleCos, angleSin; - mapDrawSurface_t *out; - int numSurfaces; - const char *name; - polyset_t *pset; - int numFrames; - char filename[1024]; - - sprintf( filename, "%s%s", gamedir, modelName ); - - angle = angle / 180 * Q_PI; - angleCos = cos( angle ); - angleSin = sin( angle ); - - // load the model - ASE_Load( filename, qfalse, qfalse ); - - // each ase surface will become a new bsp surface - numSurfaces = ASE_GetNumSurfaces(); - - c_triangleModels++; - c_triangleSurfaces += numSurfaces; - - // expand, translate, and rotate the vertexes - // swap all the surfaces - for ( i = 0 ; i < numSurfaces ; i++) { - name = ASE_GetSurfaceName( i ); - - pset = ASE_GetSurfaceAnimation( i, &numFrames, -1, -1, -1 ); - if ( !name || !pset ) { - continue; - } - - // allocate a surface - out = AllocDrawSurf(); - out->miscModel = qtrue; - - out->shaderInfo = ShaderInfoForShader( pset->materialname ); - - out->numVerts = 3 * pset->numtriangles; - out->verts = malloc( out->numVerts * sizeof( out->verts[0] ) ); - - out->numIndexes = 3 * pset->numtriangles; - out->indexes = malloc( out->numIndexes * sizeof( out->indexes[0] ) ); - - out->lightmapNum = -1; - out->fogNum = -1; - - // emit the indexes - c_triangleIndexes += out->numIndexes; - for ( j = 0 ; j < out->numIndexes ; j++ ) { - out->indexes[j] = j; - } - - // emit the vertexes - c_triangleVertexes += out->numVerts; - for ( j = 0 ; j < out->numVerts ; j++ ) { - int index; - triangle_t *tri; - - index = j % 3; - tri = &pset->triangles[ j / 3 ]; - - outv = &out->verts[ j ]; - - outv->st[0] = tri->texcoords[index][0]; - outv->st[1] = tri->texcoords[index][1]; - - outv->lightmap[0] = 0; - outv->lightmap[1] = 0; - - // the colors will be set by the lighting pass - outv->color[0] = 255; - outv->color[1] = 255; - outv->color[2] = 255; - outv->color[3] = 255; - - outv->xyz[0] = origin[0] + tri->verts[index][0]; - outv->xyz[1] = origin[1] + tri->verts[index][1]; - outv->xyz[2] = origin[2] + tri->verts[index][2]; - - // rotate the normal - outv->normal[0] = tri->normals[index][0]; - outv->normal[1] = tri->normals[index][1]; - outv->normal[2] = tri->normals[index][2]; - } - } - -} - - -//============================================================================== - - - -/* -===================== -AddTriangleModels -===================== -*/ -void AddTriangleModels( tree_t *tree ) { - int entity_num; - entity_t *entity; - - qprintf("----- AddTriangleModels -----\n"); - - for ( entity_num=1 ; entity_num< num_entities ; entity_num++ ) { - entity = &entities[entity_num]; - - // convert misc_models into raw geometry - if ( !Q_stricmp( "misc_model", ValueForKey( entity, "classname" ) ) ) { - const char *model; - vec3_t origin; - float angle; - - // get the angle for rotation FIXME: support full matrix positioning - angle = FloatForKey( entity, "angle" ); - - GetVectorForKey( entity, "origin", origin ); - - model = ValueForKey( entity, "model" ); - if ( !model[0] ) { - _printf("WARNING: misc_model at %i %i %i without a model key\n", (int)origin[0], - (int)origin[1], (int)origin[2] ); - continue; - } - if ( strstr( model, ".md3" ) || strstr( model, ".MD3" ) ) { - InsertMD3Model( model, origin, angle, tree ); - continue; - } - if ( strstr( model, ".ase" ) || strstr( model, ".ASE" ) ) { - InsertASEModel( model, origin, angle, tree ); - continue; - } - _printf( "Unknown misc_model type: %s\n", model ); - continue; - } - } - - qprintf( "%5i triangle models\n", c_triangleModels ); - qprintf( "%5i triangle surfaces\n", c_triangleSurfaces ); - qprintf( "%5i triangle vertexes\n", c_triangleVertexes ); - qprintf( "%5i triangle indexes\n", c_triangleIndexes ); -} - diff --git a/q3map/nodraw.c b/q3map/nodraw.c deleted file mode 100644 index 7503a48..0000000 --- a/q3map/nodraw.c +++ /dev/null @@ -1,47 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "qbsp.h" - -vec3_t draw_mins, draw_maxs; -qboolean drawflag; - -void Draw_ClearWindow (void) -{ -} - -//============================================================ - -#define GLSERV_PORT 25001 - - -void GLS_BeginScene (void) -{ -} - -void GLS_Winding (winding_t *w, int code) -{ -} - -void GLS_EndScene (void) -{ -} diff --git a/q3map/patch.c b/q3map/patch.c deleted file mode 100644 index df461d6..0000000 --- a/q3map/patch.c +++ /dev/null @@ -1,286 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#include "qbsp.h" - - -void PrintCtrl( vec3_t ctrl[9] ) { - int i, j; - - for ( i = 0 ; i < 3 ; i++ ) { - for ( j = 0 ; j < 3 ; j++ ) { - _printf("(%5.2f %5.2f %5.2f) ", ctrl[i*3+j][0], ctrl[i*3+j][1], ctrl[i*3+j][2] ); - } - _printf("\n"); - } -} - -/* -================ -DrawSurfaceForMesh -================ -*/ -mapDrawSurface_t *DrawSurfaceForMesh( mesh_t *m ) { - mapDrawSurface_t *ds; - int i, j; - mesh_t *copy; - - // to make valid normals for patches with degenerate edges, - // we need to make a copy of the mesh and put the aproximating - // points onto the curve - copy = CopyMesh( m ); - PutMeshOnCurve( *copy ); - MakeMeshNormals( *copy ); - for ( j = 0 ; j < m->width ; j++ ) { - for ( i = 0 ; i < m->height ; i++ ) { - VectorCopy( copy->verts[i*m->width+j].normal, m->verts[i*m->width+j].normal ); - } - } - FreeMesh( copy ); - - ds = AllocDrawSurf(); - ds->mapBrush = NULL; - ds->side = NULL; - - ds->patch = qtrue; - ds->patchWidth = m->width; - ds->patchHeight = m->height; - ds->numVerts = ds->patchWidth * ds->patchHeight; - ds->verts = malloc( ds->numVerts * sizeof( *ds->verts ) ); - memcpy( ds->verts, m->verts, ds->numVerts * sizeof( *ds->verts ) ); - - ds->lightmapNum = -1; - ds->fogNum = -1; - - return ds; -} - -/* -================= -ParsePatch - -Creates a mapDrawSurface_t from the patch text -================= -*/ -void ParsePatch( void ) { - vec_t info[5]; - int i, j; - parseMesh_t *pm; - char texture[MAX_QPATH]; - char shader[MAX_QPATH]; - mesh_t m; - drawVert_t *verts; - epair_t *ep; - - MatchToken( "{" ); - - // get texture - GetToken (qtrue); - strcpy( texture, token ); - - // save the shader name for retexturing - if ( numMapIndexedShaders == MAX_MAP_BRUSHSIDES ) { - Error( "MAX_MAP_BRUSHSIDES" ); - } - strcpy( mapIndexedShaders[numMapIndexedShaders], texture ); - numMapIndexedShaders++; - - - Parse1DMatrix( 5, info ); - m.width = info[0]; - m.height = info[1]; - m.verts = verts = malloc( m.width * m.height * sizeof( m.verts[0] ) ); - - if ( m.width < 0 || m.width > MAX_PATCH_SIZE - || m.height < 0 || m.height > MAX_PATCH_SIZE ) { - Error("ParsePatch: bad size"); - } - - MatchToken( "(" ); - for ( j = 0 ; j < m.width ; j++ ) { - MatchToken( "(" ); - for ( i = 0 ; i < m.height ; i++ ) { - Parse1DMatrix( 5, verts[i*m.width+j].xyz ); - } - MatchToken( ")" ); - } - MatchToken( ")" ); - - // if brush primitives format, we may have some epairs to ignore here - GetToken(qtrue); - if (g_bBrushPrimit!=BPRIMIT_OLDBRUSHES && strcmp(token,"}")) - { - // NOTE: we leak that! - ep = ParseEpair(); - } - else - UnGetToken(); - - MatchToken( "}" ); - MatchToken( "}" ); - - if ( noCurveBrushes ) { - return; - } - - // find default flags and values - pm = malloc( sizeof( *pm ) ); - memset( pm, 0, sizeof( *pm ) ); - - sprintf( shader, "textures/%s", texture ); - pm->shaderInfo = ShaderInfoForShader( shader ); - pm->mesh = m; - - // link to the entity - pm->next = mapent->patches; - mapent->patches = pm; -} - - -void GrowGroup_r( int patchNum, int patchCount, const byte *bordering, byte *group ) { - int i; - const byte *row; - - if ( group[patchNum] ) { - return; - } - group[patchNum] = 1; - row = bordering + patchNum * patchCount; - for ( i = 0 ; i < patchCount ; i++ ) { - if ( row[i] ) { - GrowGroup_r( i, patchCount, bordering, group ); - } - } -} - - -/* -===================== -PatchMapDrawSurfs - -Any patches that share an edge need to choose their -level of detail as a unit, otherwise the edges would -pull apart. -===================== -*/ -void PatchMapDrawSurfs( entity_t *e ) { - parseMesh_t *pm; - parseMesh_t *check, *scan; - mapDrawSurface_t *ds; - int patchCount, groupCount; - int i, j, k, l, c1, c2; - drawVert_t *v1, *v2; - vec3_t bounds[2]; - byte *bordering; - parseMesh_t *meshes[MAX_MAP_DRAW_SURFS]; - qboolean grouped[MAX_MAP_DRAW_SURFS]; - byte group[MAX_MAP_DRAW_SURFS]; - - qprintf( "----- PatchMapDrawSurfs -----\n" ); - - patchCount = 0; - for ( pm = e->patches ; pm ; pm = pm->next ) { - meshes[patchCount] = pm; - patchCount++; - } - - if ( !patchCount ) { - return; - } - bordering = malloc( patchCount * patchCount ); - memset( bordering, 0, patchCount * patchCount ); - - // build the bordering matrix - for ( k = 0 ; k < patchCount ; k++ ) { - bordering[k*patchCount+k] = 1; - - for ( l = k+1 ; l < patchCount ; l++ ) { - check = meshes[k]; - scan = meshes[l]; - c1 = scan->mesh.width * scan->mesh.height; - v1 = scan->mesh.verts; - - for ( i = 0 ; i < c1 ; i++, v1++ ) { - c2 = check->mesh.width * check->mesh.height; - v2 = check->mesh.verts; - for ( j = 0 ; j < c2 ; j++, v2++ ) { - if ( fabs( v1->xyz[0] - v2->xyz[0] ) < 1.0 - && fabs( v1->xyz[1] - v2->xyz[1] ) < 1.0 - && fabs( v1->xyz[2] - v2->xyz[2] ) < 1.0 ) { - break; - } - } - if ( j != c2 ) { - break; - } - } - if ( i != c1 ) { - // we have a connection - bordering[k*patchCount+l] = - bordering[l*patchCount+k] = 1; - } else { - // no connection - bordering[k*patchCount+l] = - bordering[l*patchCount+k] = 0; - } - - } - } - - // build groups - memset( grouped, 0, sizeof(grouped) ); - groupCount = 0; - for ( i = 0 ; i < patchCount ; i++ ) { - if ( !grouped[i] ) { - groupCount++; - } - - // recursively find all patches that belong in the same group - memset( group, 0, patchCount ); - GrowGroup_r( i, patchCount, bordering, group ); - - // bound them - ClearBounds( bounds[0], bounds[1] ); - for ( j = 0 ; j < patchCount ; j++ ) { - if ( group[j] ) { - grouped[j] = qtrue; - scan = meshes[j]; - c1 = scan->mesh.width * scan->mesh.height; - v1 = scan->mesh.verts; - for ( k = 0 ; k < c1 ; k++, v1++ ) { - AddPointToBounds( v1->xyz, bounds[0], bounds[1] ); - } - } - } - - // create drawsurf - scan = meshes[i]; - scan->grouped = qtrue; - ds = DrawSurfaceForMesh( &scan->mesh ); - ds->shaderInfo = scan->shaderInfo; - VectorCopy( bounds[0], ds->lightmapVecs[0] ); - VectorCopy( bounds[1], ds->lightmapVecs[1] ); - } - - qprintf( "%5i patches\n", patchCount ); - qprintf( "%5i patch LOD groups\n", groupCount ); -} - diff --git a/q3map/portals.c b/q3map/portals.c deleted file mode 100644 index 059760f..0000000 --- a/q3map/portals.c +++ /dev/null @@ -1,843 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "qbsp.h" - - -int c_active_portals; -int c_peak_portals; -int c_boundary; -int c_boundary_sides; - -/* -=========== -AllocPortal -=========== -*/ -portal_t *AllocPortal (void) -{ - portal_t *p; - - if (numthreads == 1) - c_active_portals++; - if (c_active_portals > c_peak_portals) - c_peak_portals = c_active_portals; - - p = malloc (sizeof(portal_t)); - memset (p, 0, sizeof(portal_t)); - - return p; -} - -void FreePortal (portal_t *p) -{ - if (p->winding) - FreeWinding (p->winding); - if (numthreads == 1) - c_active_portals--; - free (p); -} - -//============================================================== - -/* -============= -Portal_Passable - -Returns true if the portal has non-opaque leafs on both sides -============= -*/ -qboolean Portal_Passable(portal_t *p) { - if (!p->onnode) { - return qfalse; // to global outsideleaf - } - - if (p->nodes[0]->planenum != PLANENUM_LEAF - || p->nodes[1]->planenum != PLANENUM_LEAF) { - Error ("Portal_EntityFlood: not a leaf"); - } - - if ( !p->nodes[0]->opaque && !p->nodes[1]->opaque ) { - return qtrue; - } - - return qfalse; -} - - -//============================================================================= - -int c_tinyportals; - -/* -============= -AddPortalToNodes -============= -*/ -void AddPortalToNodes (portal_t *p, node_t *front, node_t *back) -{ - if (p->nodes[0] || p->nodes[1]) - Error ("AddPortalToNode: allready included"); - - p->nodes[0] = front; - p->next[0] = front->portals; - front->portals = p; - - p->nodes[1] = back; - p->next[1] = back->portals; - back->portals = p; -} - - -/* -============= -RemovePortalFromNode -============= -*/ -void RemovePortalFromNode (portal_t *portal, node_t *l) -{ - portal_t **pp, *t; - -// remove reference to the current portal - pp = &l->portals; - while (1) - { - t = *pp; - if (!t) - Error ("RemovePortalFromNode: portal not in leaf"); - - if ( t == portal ) - break; - - if (t->nodes[0] == l) - pp = &t->next[0]; - else if (t->nodes[1] == l) - pp = &t->next[1]; - else - Error ("RemovePortalFromNode: portal not bounding leaf"); - } - - if (portal->nodes[0] == l) - { - *pp = portal->next[0]; - portal->nodes[0] = NULL; - } - else if (portal->nodes[1] == l) - { - *pp = portal->next[1]; - portal->nodes[1] = NULL; - } -} - -//============================================================================ - -void PrintPortal (portal_t *p) -{ - int i; - winding_t *w; - - w = p->winding; - for (i=0 ; i<w->numpoints ; i++) - _printf ("(%5.0f,%5.0f,%5.0f)\n",w->p[i][0] - , w->p[i][1], w->p[i][2]); -} - -/* -================ -MakeHeadnodePortals - -The created portals will face the global outside_node -================ -*/ -#define SIDESPACE 8 -void MakeHeadnodePortals (tree_t *tree) -{ - vec3_t bounds[2]; - int i, j, n; - portal_t *p, *portals[6]; - plane_t bplanes[6], *pl; - node_t *node; - - node = tree->headnode; - -// pad with some space so there will never be null volume leafs - for (i=0 ; i<3 ; i++) - { - bounds[0][i] = tree->mins[i] - SIDESPACE; - bounds[1][i] = tree->maxs[i] + SIDESPACE; - if ( bounds[0][i] >= bounds[1][i] ) { - Error( "Backwards tree volume" ); - } - } - - tree->outside_node.planenum = PLANENUM_LEAF; - tree->outside_node.brushlist = NULL; - tree->outside_node.portals = NULL; - tree->outside_node.opaque = qfalse; - - for (i=0 ; i<3 ; i++) - for (j=0 ; j<2 ; j++) - { - n = j*3 + i; - - p = AllocPortal (); - portals[n] = p; - - pl = &bplanes[n]; - memset (pl, 0, sizeof(*pl)); - if (j) - { - pl->normal[i] = -1; - pl->dist = -bounds[j][i]; - } - else - { - pl->normal[i] = 1; - pl->dist = bounds[j][i]; - } - p->plane = *pl; - p->winding = BaseWindingForPlane (pl->normal, pl->dist); - AddPortalToNodes (p, node, &tree->outside_node); - } - -// clip the basewindings by all the other planes - for (i=0 ; i<6 ; i++) - { - for (j=0 ; j<6 ; j++) - { - if (j == i) - continue; - ChopWindingInPlace (&portals[i]->winding, bplanes[j].normal, bplanes[j].dist, ON_EPSILON); - } - } -} - -//=================================================== - - -/* -================ -BaseWindingForNode -================ -*/ -#define BASE_WINDING_EPSILON 0.001 -#define SPLIT_WINDING_EPSILON 0.001 - -winding_t *BaseWindingForNode (node_t *node) -{ - winding_t *w; - node_t *n; - plane_t *plane; - vec3_t normal; - vec_t dist; - - w = BaseWindingForPlane (mapplanes[node->planenum].normal - , mapplanes[node->planenum].dist); - - // clip by all the parents - for (n=node->parent ; n && w ; ) - { - plane = &mapplanes[n->planenum]; - - if (n->children[0] == node) - { // take front - ChopWindingInPlace (&w, plane->normal, plane->dist, BASE_WINDING_EPSILON); - } - else - { // take back - VectorSubtract (vec3_origin, plane->normal, normal); - dist = -plane->dist; - ChopWindingInPlace (&w, normal, dist, BASE_WINDING_EPSILON); - } - node = n; - n = n->parent; - } - - return w; -} - -//============================================================ - -/* -================== -MakeNodePortal - -create the new portal by taking the full plane winding for the cutting plane -and clipping it by all of parents of this node -================== -*/ -void MakeNodePortal (node_t *node) -{ - portal_t *new_portal, *p; - winding_t *w; - vec3_t normal; - float dist; - int side; - - w = BaseWindingForNode (node); - - // clip the portal by all the other portals in the node - for (p = node->portals ; p && w; p = p->next[side]) - { - if (p->nodes[0] == node) - { - side = 0; - VectorCopy (p->plane.normal, normal); - dist = p->plane.dist; - } - else if (p->nodes[1] == node) - { - side = 1; - VectorSubtract (vec3_origin, p->plane.normal, normal); - dist = -p->plane.dist; - } - else - Error ("CutNodePortals_r: mislinked portal"); - - ChopWindingInPlace (&w, normal, dist, CLIP_EPSILON); - } - - if (!w) - { - return; - } - - if (WindingIsTiny (w)) - { - c_tinyportals++; - FreeWinding (w); - return; - } - - new_portal = AllocPortal (); - new_portal->plane = mapplanes[node->planenum]; - new_portal->onnode = node; - new_portal->winding = w; - new_portal->hint = node->hint; - AddPortalToNodes (new_portal, node->children[0], node->children[1]); -} - - -/* -============== -SplitNodePortals - -Move or split the portals that bound node so that the node's -children have portals instead of node. -============== -*/ -void SplitNodePortals (node_t *node) -{ - portal_t *p, *next_portal, *new_portal; - node_t *f, *b, *other_node; - int side; - plane_t *plane; - winding_t *frontwinding, *backwinding; - - plane = &mapplanes[node->planenum]; - f = node->children[0]; - b = node->children[1]; - - for (p = node->portals ; p ; p = next_portal) - { - if (p->nodes[0] == node) - side = 0; - else if (p->nodes[1] == node) - side = 1; - else - Error ("SplitNodePortals: mislinked portal"); - next_portal = p->next[side]; - - other_node = p->nodes[!side]; - RemovePortalFromNode (p, p->nodes[0]); - RemovePortalFromNode (p, p->nodes[1]); - -// -// cut the portal into two portals, one on each side of the cut plane -// - ClipWindingEpsilon (p->winding, plane->normal, plane->dist, - SPLIT_WINDING_EPSILON, &frontwinding, &backwinding); - - if (frontwinding && WindingIsTiny(frontwinding)) - { - if (!f->tinyportals) - VectorCopy(frontwinding->p[0], f->referencepoint); - f->tinyportals++; - if (!other_node->tinyportals) - VectorCopy(frontwinding->p[0], other_node->referencepoint); - other_node->tinyportals++; - - FreeWinding (frontwinding); - frontwinding = NULL; - c_tinyportals++; - } - - if (backwinding && WindingIsTiny(backwinding)) - { - if (!b->tinyportals) - VectorCopy(backwinding->p[0], b->referencepoint); - b->tinyportals++; - if (!other_node->tinyportals) - VectorCopy(backwinding->p[0], other_node->referencepoint); - other_node->tinyportals++; - - FreeWinding (backwinding); - backwinding = NULL; - c_tinyportals++; - } - - if (!frontwinding && !backwinding) - { // tiny windings on both sides - continue; - } - - if (!frontwinding) - { - FreeWinding (backwinding); - if (side == 0) - AddPortalToNodes (p, b, other_node); - else - AddPortalToNodes (p, other_node, b); - continue; - } - if (!backwinding) - { - FreeWinding (frontwinding); - if (side == 0) - AddPortalToNodes (p, f, other_node); - else - AddPortalToNodes (p, other_node, f); - continue; - } - - // the winding is split - new_portal = AllocPortal (); - *new_portal = *p; - new_portal->winding = backwinding; - FreeWinding (p->winding); - p->winding = frontwinding; - - if (side == 0) - { - AddPortalToNodes (p, f, other_node); - AddPortalToNodes (new_portal, b, other_node); - } - else - { - AddPortalToNodes (p, other_node, f); - AddPortalToNodes (new_portal, other_node, b); - } - } - - node->portals = NULL; -} - - -/* -================ -CalcNodeBounds -================ -*/ -void CalcNodeBounds (node_t *node) -{ - portal_t *p; - int s; - int i; - - // calc mins/maxs for both leafs and nodes - ClearBounds (node->mins, node->maxs); - for (p = node->portals ; p ; p = p->next[s]) - { - s = (p->nodes[1] == node); - for (i=0 ; i<p->winding->numpoints ; i++) - AddPointToBounds (p->winding->p[i], node->mins, node->maxs); - } -} - -/* -================== -MakeTreePortals_r -================== -*/ -void MakeTreePortals_r (node_t *node) -{ - int i; - - CalcNodeBounds (node); - if (node->mins[0] >= node->maxs[0]) - { - _printf ("WARNING: node without a volume\n"); - _printf("node has %d tiny portals\n", node->tinyportals); - _printf("node reference point %1.2f %1.2f %1.2f\n", node->referencepoint[0], - node->referencepoint[1], - node->referencepoint[2]); - } - - for (i=0 ; i<3 ; i++) - { - if (node->mins[i] < MIN_WORLD_COORD || node->maxs[i] > MAX_WORLD_COORD) - { - _printf ("WARNING: node with unbounded volume\n"); - break; - } - } - if (node->planenum == PLANENUM_LEAF) - return; - - MakeNodePortal (node); - SplitNodePortals (node); - - MakeTreePortals_r (node->children[0]); - MakeTreePortals_r (node->children[1]); -} - -/* -================== -MakeTreePortals -================== -*/ -void MakeTreePortals (tree_t *tree) -{ - qprintf( "----- MakeTreePortals -----\n"); - MakeHeadnodePortals (tree); - MakeTreePortals_r (tree->headnode); - qprintf("%6d tiny portals\n", c_tinyportals); -} - -/* -========================================================= - -FLOOD ENTITIES - -========================================================= -*/ - -int c_floodedleafs; - -/* -============= -FloodPortals_r -============= -*/ -void FloodPortals_r (node_t *node, int dist) { - portal_t *p; - int s; - - if ( node->occupied ) { - return; - } - - if ( node->opaque ) { - return; - } - - c_floodedleafs++; - node->occupied = dist; - - for (p=node->portals ; p ; p = p->next[s]) { - s = (p->nodes[1] == node); - FloodPortals_r (p->nodes[!s], dist+1); - } -} - -/* -============= -PlaceOccupant -============= -*/ -qboolean PlaceOccupant (node_t *headnode, vec3_t origin, entity_t *occupant) -{ - node_t *node; - vec_t d; - plane_t *plane; - - // find the leaf to start in - node = headnode; - while (node->planenum != PLANENUM_LEAF) - { - plane = &mapplanes[node->planenum]; - d = DotProduct (origin, plane->normal) - plane->dist; - if (d >= 0) - node = node->children[0]; - else - node = node->children[1]; - } - - if ( node->opaque ) - return qfalse; - node->occupant = occupant; - - FloodPortals_r (node, 1); - - return qtrue; -} - -/* -============= -FloodEntities - -Marks all nodes that can be reached by entites -============= -*/ -qboolean FloodEntities( tree_t *tree ) { - int i; - vec3_t origin; - const char *cl; - qboolean inside; - node_t *headnode; - - headnode = tree->headnode; - qprintf ("--- FloodEntities ---\n"); - inside = qfalse; - tree->outside_node.occupied = 0; - - c_floodedleafs = 0; - for (i=1 ; i<num_entities ; i++) - { - GetVectorForKey (&entities[i], "origin", origin); - if (VectorCompare(origin, vec3_origin)) - continue; - - cl = ValueForKey (&entities[i], "classname"); - - origin[2] += 1; // so objects on floor are ok - - if (PlaceOccupant (headnode, origin, &entities[i])) - inside = qtrue; - } - - qprintf("%5i flooded leafs\n", c_floodedleafs ); - - if (!inside) - { - qprintf ("no entities in open -- no filling\n"); - } - else if (tree->outside_node.occupied) - { - qprintf ("entity reached from outside -- no filling\n"); - } - - return (qboolean)(inside && !tree->outside_node.occupied); -} - -/* -========================================================= - -FLOOD AREAS - -========================================================= -*/ - -int c_areas; - -/* -============= -FloodAreas_r -============= -*/ -void FloodAreas_r (node_t *node) -{ - portal_t *p; - int s; - bspbrush_t *b; - - if ( node->areaportal ) { - // - if ( node->area == -1 ) { - node->area = c_areas; - } - // this node is part of an area portal brush - b = node->brushlist->original; - - // if the current area has allready touched this - // portal, we are done - if (b->portalareas[0] == c_areas || b->portalareas[1] == c_areas) - return; - - // note the current area as bounding the portal - if (b->portalareas[1] != -1) - { - _printf ("WARNING: areaportal brush %i touches > 2 areas\n", b->brushnum ); - return; - } - if (b->portalareas[0] != -1) { - b->portalareas[1] = c_areas; - } else { - b->portalareas[0] = c_areas; - } - - return; - } - - if (node->area != -1) { - return; // allready got it - } - if ( node->cluster == -1 ) { - return; - } - - node->area = c_areas; - - for (p=node->portals ; p ; p = p->next[s]) - { - s = (p->nodes[1] == node); - - if ( !Portal_Passable(p) ) - continue; - - FloodAreas_r (p->nodes[!s]); - } -} - - -/* -============= -FindAreas_r - -Just decend the tree, and for each node that hasn't had an -area set, flood fill out from there -============= -*/ -void FindAreas_r (node_t *node) -{ - if (node->planenum != PLANENUM_LEAF) - { - FindAreas_r (node->children[0]); - FindAreas_r (node->children[1]); - return; - } - - if (node->opaque) - return; - - if (node->areaportal) - return; - - if (node->area != -1) - return; // allready got it - - FloodAreas_r (node); - c_areas++; -} - -/* -============= -CheckAreas_r -============= -*/ -void CheckAreas_r (node_t *node) -{ - bspbrush_t *b; - - if (node->planenum != PLANENUM_LEAF) - { - CheckAreas_r (node->children[0]); - CheckAreas_r (node->children[1]); - return; - } - - if (node->opaque) - return; - - if (node->cluster != -1) - if (node->area == -1) - _printf("WARNING: cluster %d has area set to -1\n", node->cluster); - if (node->areaportal) - { - b = node->brushlist->original; - - // check if the areaportal touches two areas - if (b->portalareas[0] == -1 || b->portalareas[1] == -1) - _printf ("WARNING: areaportal brush %i doesn't touch two areas\n", b->brushnum); - } -} - -/* -============= -FloodAreas - -Mark each leaf with an area, bounded by CONTENTS_AREAPORTAL -============= -*/ -void FloodAreas (tree_t *tree) -{ - qprintf ("--- FloodAreas ---\n"); - FindAreas_r( tree->headnode ); - - // check for areaportal brushes that don't touch two areas - CheckAreas_r( tree->headnode ); - - qprintf ("%5i areas\n", c_areas); -} - -//====================================================== - -int c_outside; -int c_inside; -int c_solid; - -void FillOutside_r (node_t *node) -{ - if (node->planenum != PLANENUM_LEAF) - { - FillOutside_r (node->children[0]); - FillOutside_r (node->children[1]); - return; - } - - // anything not reachable by an entity - // can be filled away - if (!node->occupied) { - if ( !node->opaque ) { - c_outside++; - node->opaque = qtrue; - } else { - c_solid++; - } - } else { - c_inside++; - } - -} - -/* -============= -FillOutside - -Fill all nodes that can't be reached by entities -============= -*/ -void FillOutside (node_t *headnode) -{ - c_outside = 0; - c_inside = 0; - c_solid = 0; - qprintf ("--- FillOutside ---\n"); - FillOutside_r (headnode); - qprintf ("%5i solid leafs\n", c_solid); - qprintf ("%5i leafs filled\n", c_outside); - qprintf ("%5i inside leafs\n", c_inside); -} - - -//============================================================== - diff --git a/q3map/prtfile.c b/q3map/prtfile.c deleted file mode 100644 index 6a7bb15..0000000 --- a/q3map/prtfile.c +++ /dev/null @@ -1,272 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "qbsp.h" - -/* -============================================================================== - -PORTAL FILE GENERATION - -Save out name.prt for qvis to read -============================================================================== -*/ - - -#define PORTALFILE "PRT1" - -FILE *pf; -int num_visclusters; // clusters the player can be in -int num_visportals; -int num_solidfaces; - -void WriteFloat (FILE *f, vec_t v) -{ - if ( fabs(v - Q_rint(v)) < 0.001 ) - fprintf (f,"%i ",(int)Q_rint(v)); - else - fprintf (f,"%f ",v); -} - -/* -================= -WritePortalFile_r -================= -*/ -void WritePortalFile_r (node_t *node) -{ - int i, s; - portal_t *p; - winding_t *w; - vec3_t normal; - vec_t dist; - - // decision node - if (node->planenum != PLANENUM_LEAF) { - WritePortalFile_r (node->children[0]); - WritePortalFile_r (node->children[1]); - return; - } - - if (node->opaque) { - return; - } - - for (p = node->portals ; p ; p=p->next[s]) - { - w = p->winding; - s = (p->nodes[1] == node); - if (w && p->nodes[0] == node) - { - if (!Portal_Passable(p)) - continue; - // write out to the file - - // sometimes planes get turned around when they are very near - // the changeover point between different axis. interpret the - // plane the same way vis will, and flip the side orders if needed - // FIXME: is this still relevent? - WindingPlane (w, normal, &dist); - if ( DotProduct (p->plane.normal, normal) < 0.99 ) - { // backwards... - fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster); - } - else - fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[0]->cluster, p->nodes[1]->cluster); - if (p->hint) - fprintf (pf, "1 "); - else - fprintf (pf, "0 "); - for (i=0 ; i<w->numpoints ; i++) - { - fprintf (pf,"("); - WriteFloat (pf, w->p[i][0]); - WriteFloat (pf, w->p[i][1]); - WriteFloat (pf, w->p[i][2]); - fprintf (pf,") "); - } - fprintf (pf,"\n"); - } - } - -} - -/* -================= -WriteFaceFile_r -================= -*/ -void WriteFaceFile_r (node_t *node) -{ - int i, s; - portal_t *p; - winding_t *w; - - // decision node - if (node->planenum != PLANENUM_LEAF) { - WriteFaceFile_r (node->children[0]); - WriteFaceFile_r (node->children[1]); - return; - } - - if (node->opaque) { - return; - } - - for (p = node->portals ; p ; p=p->next[s]) - { - w = p->winding; - s = (p->nodes[1] == node); - if (w) - { - if (Portal_Passable(p)) - continue; - // write out to the file - - if (p->nodes[0] == node) - { - fprintf (pf,"%i %i ",w->numpoints, p->nodes[0]->cluster); - for (i=0 ; i<w->numpoints ; i++) - { - fprintf (pf,"("); - WriteFloat (pf, w->p[i][0]); - WriteFloat (pf, w->p[i][1]); - WriteFloat (pf, w->p[i][2]); - fprintf (pf,") "); - } - fprintf (pf,"\n"); - } - else - { - fprintf (pf,"%i %i ",w->numpoints, p->nodes[1]->cluster); - for (i = w->numpoints-1; i >= 0; i--) - { - fprintf (pf,"("); - WriteFloat (pf, w->p[i][0]); - WriteFloat (pf, w->p[i][1]); - WriteFloat (pf, w->p[i][2]); - fprintf (pf,") "); - } - fprintf (pf,"\n"); - } - } - } -} - -/* -================ -NumberLeafs_r -================ -*/ -void NumberLeafs_r (node_t *node) -{ - portal_t *p; - - if ( node->planenum != PLANENUM_LEAF ) { - // decision node - node->cluster = -99; - NumberLeafs_r (node->children[0]); - NumberLeafs_r (node->children[1]); - return; - } - - node->area = -1; - - if ( node->opaque ) { - // solid block, viewpoint never inside - node->cluster = -1; - return; - } - - node->cluster = num_visclusters; - num_visclusters++; - - // count the portals - for (p = node->portals ; p ; ) - { - if (p->nodes[0] == node) // only write out from first leaf - { - if (Portal_Passable(p)) - num_visportals++; - else - num_solidfaces++; - p = p->next[0]; - } - else - { - if (!Portal_Passable(p)) - num_solidfaces++; - p = p->next[1]; - } - } -} - - -/* -================ -NumberClusters -================ -*/ -void NumberClusters(tree_t *tree) { - num_visclusters = 0; - num_visportals = 0; - num_solidfaces = 0; - - qprintf ("--- NumberClusters ---\n"); - - // set the cluster field in every leaf and count the total number of portals - NumberLeafs_r (tree->headnode); - - qprintf ("%5i visclusters\n", num_visclusters); - qprintf ("%5i visportals\n", num_visportals); - qprintf ("%5i solidfaces\n", num_solidfaces); -} - -/* -================ -WritePortalFile -================ -*/ -void WritePortalFile (tree_t *tree) -{ - char filename[1024]; - - qprintf ("--- WritePortalFile ---\n"); - - // write the file - sprintf (filename, "%s.prt", source); - _printf ("writing %s\n", filename); - pf = fopen (filename, "w"); - if (!pf) - Error ("Error opening %s", filename); - - fprintf (pf, "%s\n", PORTALFILE); - fprintf (pf, "%i\n", num_visclusters); - fprintf (pf, "%i\n", num_visportals); - fprintf (pf, "%i\n", num_solidfaces); - - WritePortalFile_r(tree->headnode); - WriteFaceFile_r(tree->headnode); - - fclose (pf); -} - diff --git a/q3map/q3map.sln b/q3map/q3map.sln deleted file mode 100644 index e0b2699..0000000 --- a/q3map/q3map.sln +++ /dev/null @@ -1,56 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 8.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jpeg6", "..\libs\jpeg6\jpeg6.vcproj", "{A862AD26-94DD-4618-A814-F6AACA0B2FE3}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pak", "..\libs\pak\pak.vcproj", "{F2ACC9D7-D628-4624-864F-87FE58787625}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "q3map", "q3map.vcproj", "{F1162C55-66E7-4486-B1F3-071CFAA78332}" - ProjectSection(ProjectDependencies) = postProject - {F2ACC9D7-D628-4624-864F-87FE58787625} = {F2ACC9D7-D628-4624-864F-87FE58787625} - {A862AD26-94DD-4618-A814-F6AACA0B2FE3} = {A862AD26-94DD-4618-A814-F6AACA0B2FE3} - EndProjectSection -EndProject -Global - GlobalSection(SourceCodeControl) = preSolution - SccNumberOfProjects = 3 - SccProjectUniqueName0 = ..\\libs\\jpeg6\\jpeg6.vcproj - SccProjectName0 = \u0022$/source/q3radiant\u0022,\u0020FEFAAAAA - SccLocalPath0 = ..\\q3radiant - SccProvider0 = MSSCCI:Perforce\u0020SCM - SccProjectFilePathRelativizedFromConnection0 = ..\\libs\\jpeg6\\ - SccProjectUniqueName1 = ..\\libs\\pak\\pak.vcproj - SccProjectName1 = \u0022$/source/q3radiant\u0022,\u0020FEFAAAAA - SccLocalPath1 = ..\\q3radiant - SccProvider1 = MSSCCI:Perforce\u0020SCM - SccProjectFilePathRelativizedFromConnection1 = ..\\libs\\pak\\ - SccProjectUniqueName2 = q3map.vcproj - SccProjectName2 = \u0022$/source/q3map\u0022,\u0020PADAAAAA - SccLocalPath2 = . - SccProvider2 = MSSCCI:Perforce\u0020SCM - EndGlobalSection - GlobalSection(SolutionConfiguration) = preSolution - Debug = Debug - Release = Release - EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {A862AD26-94DD-4618-A814-F6AACA0B2FE3}.Debug.ActiveCfg = Debug|Win32 - {A862AD26-94DD-4618-A814-F6AACA0B2FE3}.Debug.Build.0 = Debug|Win32 - {A862AD26-94DD-4618-A814-F6AACA0B2FE3}.Release.ActiveCfg = Release|Win32 - {A862AD26-94DD-4618-A814-F6AACA0B2FE3}.Release.Build.0 = Release|Win32 - {F2ACC9D7-D628-4624-864F-87FE58787625}.Debug.ActiveCfg = Debug|Win32 - {F2ACC9D7-D628-4624-864F-87FE58787625}.Debug.Build.0 = Debug|Win32 - {F2ACC9D7-D628-4624-864F-87FE58787625}.Release.ActiveCfg = Release|Win32 - {F2ACC9D7-D628-4624-864F-87FE58787625}.Release.Build.0 = Release|Win32 - {F1162C55-66E7-4486-B1F3-071CFAA78332}.Debug.ActiveCfg = Debug|Win32 - {F1162C55-66E7-4486-B1F3-071CFAA78332}.Debug.Build.0 = Debug|Win32 - {F1162C55-66E7-4486-B1F3-071CFAA78332}.Release.ActiveCfg = Release|Win32 - {F1162C55-66E7-4486-B1F3-071CFAA78332}.Release.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/q3map/q3map.vcproj b/q3map/q3map.vcproj deleted file mode 100644 index 6fa6606..0000000 --- a/q3map/q3map.vcproj +++ /dev/null @@ -1,1606 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="7.10" - Name="q3map" - SccProjectName=""$/source/q3map", PADAAAAA" - SccLocalPath="."> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory=".\Debug" - IntermediateDirectory=".\Debug" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="../common,c:\quake3\common,c:\quake3\libs" - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" - RuntimeLibrary="1" - UsePrecompiledHeader="2" - PrecompiledHeaderFile=".\Debug/q3map.pch" - AssemblerListingLocation=".\Debug/" - ObjectFile=".\Debug/" - ProgramDataBaseFileName=".\Debug/" - BrowseInformation="1" - WarningLevel="3" - SuppressStartupBanner="TRUE" - DebugInformationFormat="4" - CompileAs="0"/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="glaux.lib glu32.lib wsock32.lib opengl32.lib odbc32.lib odbccp32.lib ..\libs\pakd.lib ..\libs\jpeg6d.lib" - OutputFile=".\Debug/q3map.exe" - LinkIncremental="2" - SuppressStartupBanner="TRUE" - GenerateDebugInformation="TRUE" - ProgramDatabaseFile=".\Debug/q3map.pdb" - SubSystem="1" - StackReserveSize="4194304" - TargetMachine="1"/> - <Tool - Name="VCMIDLTool" - TypeLibraryName=".\Debug/q3map.tlb" - HeaderFileName=""/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="_DEBUG" - Culture="1033"/> - <Tool - Name="VCWebServiceProxyGeneratorTool"/> - <Tool - Name="VCXMLDataGeneratorTool"/> - <Tool - Name="VCWebDeploymentTool"/> - <Tool - Name="VCManagedWrapperGeneratorTool"/> - <Tool - Name="VCAuxiliaryManagedWrapperGeneratorTool"/> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory=".\Release" - IntermediateDirectory=".\Release" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - InlineFunctionExpansion="1" - AdditionalIncludeDirectories="../common,c:\quake3\common,c:\quake3\libs" - PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" - StringPooling="TRUE" - RuntimeLibrary="0" - EnableFunctionLevelLinking="TRUE" - UsePrecompiledHeader="2" - PrecompiledHeaderFile=".\Release/q3map.pch" - AssemblerListingLocation=".\Release/" - ObjectFile=".\Release/" - ProgramDataBaseFileName=".\Release/" - WarningLevel="3" - SuppressStartupBanner="TRUE" - DebugInformationFormat="3" - CompileAs="0"/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="glaux.lib glu32.lib wsock32.lib opengl32.lib odbc32.lib odbccp32.lib ..\libs\pak.lib ..\libs\jpeg6.lib" - OutputFile=".\Release/q3map.exe" - LinkIncremental="1" - SuppressStartupBanner="TRUE" - GenerateDebugInformation="TRUE" - ProgramDatabaseFile=".\Release/q3map.pdb" - SubSystem="1" - StackReserveSize="4194304" - TargetMachine="1"/> - <Tool - Name="VCMIDLTool" - TypeLibraryName=".\Release/q3map.tlb" - HeaderFileName=""/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="NDEBUG" - Culture="1033"/> - <Tool - Name="VCWebServiceProxyGeneratorTool"/> - <Tool - Name="VCXMLDataGeneratorTool"/> - <Tool - Name="VCWebDeploymentTool"/> - <Tool - Name="VCManagedWrapperGeneratorTool"/> - <Tool - Name="VCAuxiliaryManagedWrapperGeneratorTool"/> - </Configuration> - <Configuration - Name="DebugTTimo|Win32" - OutputDirectory=".\q3map___Win32_DebugTTimo" - IntermediateDirectory=".\q3map___Win32_DebugTTimo" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="../common,../../Libs,c:\quake3\common,c:\quake3\libs" - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_TTIMOBUILD" - RuntimeLibrary="1" - UsePrecompiledHeader="2" - PrecompiledHeaderFile=".\q3map___Win32_DebugTTimo/q3map.pch" - AssemblerListingLocation=".\q3map___Win32_DebugTTimo/" - ObjectFile=".\q3map___Win32_DebugTTimo/" - ProgramDataBaseFileName=".\q3map___Win32_DebugTTimo/" - BrowseInformation="1" - WarningLevel="3" - SuppressStartupBanner="TRUE" - DebugInformationFormat="4" - CompileAs="0"/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="glaux.lib glu32.lib wsock32.lib opengl32.lib odbc32.lib odbccp32.lib pakd.lib jpeg6d.lib" - OutputFile=".\q3map___Win32_DebugTTimo/q3map.exe" - LinkIncremental="2" - SuppressStartupBanner="TRUE" - AdditionalLibraryDirectories="../../Libs" - GenerateDebugInformation="TRUE" - ProgramDatabaseFile=".\q3map___Win32_DebugTTimo/q3map.pdb" - SubSystem="1" - StackReserveSize="4194304" - TargetMachine="1"/> - <Tool - Name="VCMIDLTool" - TypeLibraryName=".\q3map___Win32_DebugTTimo/q3map.tlb" - HeaderFileName=""/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="_DEBUG" - Culture="1033"/> - <Tool - Name="VCWebServiceProxyGeneratorTool"/> - <Tool - Name="VCXMLDataGeneratorTool"/> - <Tool - Name="VCWebDeploymentTool"/> - <Tool - Name="VCManagedWrapperGeneratorTool"/> - <Tool - Name="VCAuxiliaryManagedWrapperGeneratorTool"/> - </Configuration> - <Configuration - Name="ReleaseTTimo|Win32" - OutputDirectory=".\q3map___Win32_ReleaseTTimo" - IntermediateDirectory=".\q3map___Win32_ReleaseTTimo" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - InlineFunctionExpansion="1" - AdditionalIncludeDirectories="../common,../../Libs,c:\quake3\common,c:\quake3\libs" - PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_TTIMOBUILD" - StringPooling="TRUE" - RuntimeLibrary="0" - EnableFunctionLevelLinking="TRUE" - UsePrecompiledHeader="2" - PrecompiledHeaderFile=".\q3map___Win32_ReleaseTTimo/q3map.pch" - AssemblerListingLocation=".\q3map___Win32_ReleaseTTimo/" - ObjectFile=".\q3map___Win32_ReleaseTTimo/" - ProgramDataBaseFileName=".\q3map___Win32_ReleaseTTimo/" - WarningLevel="3" - SuppressStartupBanner="TRUE" - DebugInformationFormat="3" - CompileAs="0"/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="glaux.lib glu32.lib wsock32.lib opengl32.lib odbc32.lib odbccp32.lib pak.lib jpeg6.lib" - OutputFile=".\q3map___Win32_ReleaseTTimo/q3map.exe" - LinkIncremental="1" - SuppressStartupBanner="TRUE" - AdditionalLibraryDirectories="../../Libs" - GenerateDebugInformation="TRUE" - ProgramDatabaseFile=".\q3map___Win32_ReleaseTTimo/q3map.pdb" - SubSystem="1" - StackReserveSize="4194304" - TargetMachine="1"/> - <Tool - Name="VCMIDLTool" - TypeLibraryName=".\q3map___Win32_ReleaseTTimo/q3map.tlb" - HeaderFileName=""/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="NDEBUG" - Culture="1033"/> - <Tool - Name="VCWebServiceProxyGeneratorTool"/> - <Tool - Name="VCXMLDataGeneratorTool"/> - <Tool - Name="VCWebDeploymentTool"/> - <Tool - Name="VCManagedWrapperGeneratorTool"/> - <Tool - Name="VCAuxiliaryManagedWrapperGeneratorTool"/> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <File - RelativePath="..\common\aselib.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="brush.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="brush_primit.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="bsp.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="..\common\bspfile.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="..\common\cmdlib.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="facebsp.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="fog.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="gldraw.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="glfile.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="..\common\imagelib.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="leakfile.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="light.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="light_trace.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="lightmaps.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="lightv.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="map.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="..\common\mathlib.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="mesh.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="misc_model.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="..\common\mutex.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="patch.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="..\common\polylib.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="portals.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="prtfile.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="..\common\scriplib.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="shaders.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="soundv.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="surface.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="terrain.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="..\common\threads.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="tjunction.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="tree.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="vis.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="visflow.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="writebsp.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/q3map/qbsp.h b/q3map/qbsp.h deleted file mode 100644 index 7c7cfba..0000000 --- a/q3map/qbsp.h +++ /dev/null @@ -1,455 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "cmdlib.h" -#include "mathlib.h" -#include "scriplib.h" -#include "polylib.h" -#include "imagelib.h" -#include "threads.h" -#include "bspfile.h" -#include "shaders.h" -#include "mesh.h" - - -#define MAX_PATCH_SIZE 32 - -#define CLIP_EPSILON 0.1 -#define PLANENUM_LEAF -1 - -#define HINT_PRIORITY 1000 - -typedef struct parseMesh_s { - struct parseMesh_s *next; - mesh_t mesh; - shaderInfo_t *shaderInfo; - - qboolean grouped; // used during shared edge grouping - struct parseMesh_s *groupChain; -} parseMesh_t; - -typedef struct bspface_s { - struct bspface_s *next; - int planenum; - int priority; // added to value calculation - qboolean checked; - qboolean hint; - winding_t *w; -} bspface_t; - -typedef struct plane_s { - vec3_t normal; - vec_t dist; - int type; - struct plane_s *hash_chain; -} plane_t; - -typedef struct side_s { - int planenum; - - float texMat[2][3]; // brush primitive texture matrix - // for old brush coordinates mode - float vecs[2][4]; // texture coordinate mapping - - winding_t *winding; - winding_t *visibleHull; // convex hull of all visible fragments - - struct shaderInfo_s *shaderInfo; - - int contents; // from shaderInfo - int surfaceFlags; // from shaderInfo - int value; // from shaderInfo - - qboolean visible; // choose visble planes first - qboolean bevel; // don't ever use for bsp splitting, and don't bother - // making windings for it - qboolean backSide; // generated side for a q3map_backShader -} side_t; - - -#define MAX_BRUSH_SIDES 1024 - -typedef struct bspbrush_s { - struct bspbrush_s *next; - - int entitynum; // editor numbering - int brushnum; // editor numbering - - struct shaderInfo_s *contentShader; - - int contents; - qboolean detail; - qboolean opaque; - int outputNumber; // set when the brush is written to the file list - - int portalareas[2]; - - struct bspbrush_s *original; // chopped up brushes will reference the originals - - vec3_t mins, maxs; - int numsides; - side_t sides[6]; // variably sized -} bspbrush_t; - - - -typedef struct drawsurf_s { - shaderInfo_t *shaderInfo; - - bspbrush_t *mapBrush; // not valid for patches - side_t *side; // not valid for patches - - struct drawsurf_s *nextOnShader; // when sorting by shader for lightmaps - - int fogNum; // set by FogDrawSurfs - - int lightmapNum; // -1 = no lightmap - int lightmapX, lightmapY; - int lightmapWidth, lightmapHeight; - - int numVerts; - drawVert_t *verts; - - int numIndexes; - int *indexes; - - // for faces only - int planeNum; - - vec3_t lightmapOrigin; // also used for flares - vec3_t lightmapVecs[3]; // also used for flares - - // for patches only - qboolean patch; - int patchWidth; - int patchHeight; - - // for misc_models only - qboolean miscModel; - - qboolean flareSurface; -} mapDrawSurface_t; - -typedef struct drawSurfRef_s { - struct drawSurfRef_s *nextRef; - int outputNumber; -} drawSurfRef_t; - -typedef struct node_s { - // both leafs and nodes - int planenum; // -1 = leaf node - struct node_s *parent; - vec3_t mins, maxs; // valid after portalization - bspbrush_t *volume; // one for each leaf/node - - // nodes only - side_t *side; // the side that created the node - struct node_s *children[2]; - qboolean hint; - int tinyportals; - vec3_t referencepoint; - - // leafs only - qboolean opaque; // view can never be inside - qboolean areaportal; - int cluster; // for portalfile writing - int area; // for areaportals - bspbrush_t *brushlist; // fragments of all brushes in this leaf - drawSurfRef_t *drawSurfReferences; // references to patches pushed down - - int occupied; // 1 or greater can reach entity - entity_t *occupant; // for leak file testing - - struct portal_s *portals; // also on nodes during construction -} node_t; - -typedef struct portal_s { - plane_t plane; - node_t *onnode; // NULL = outside box - node_t *nodes[2]; // [0] = front side of plane - struct portal_s *next[2]; - winding_t *winding; - - qboolean sidefound; // false if ->side hasn't been checked - qboolean hint; - side_t *side; // NULL = non-visible -} portal_t; - -typedef struct { - node_t *headnode; - node_t outside_node; - vec3_t mins, maxs; -} tree_t; - -extern int entity_num; - - -extern qboolean noprune; -extern qboolean nodetail; -extern qboolean fulldetail; -extern qboolean nowater; -extern qboolean noCurveBrushes; -extern qboolean fakemap; -extern qboolean coplanar; -extern qboolean nofog; -extern qboolean testExpand; -extern qboolean showseams; - -extern vec_t microvolume; - -extern char outbase[32]; -extern char source[1024]; - -extern int samplesize; //sample size in units -extern int novertexlighting; -extern int nogridlighting; - -//============================================================================= - -// brush.c - -int CountBrushList (bspbrush_t *brushes); -bspbrush_t *AllocBrush (int numsides); -void FreeBrush (bspbrush_t *brushes); -void FreeBrushList (bspbrush_t *brushes); -bspbrush_t *CopyBrush (bspbrush_t *brush); -void DrawBrushList (bspbrush_t *brush); -void WriteBrushList (char *name, bspbrush_t *brush, qboolean onlyvis); -void PrintBrush (bspbrush_t *brush); -qboolean BoundBrush (bspbrush_t *brush); -qboolean CreateBrushWindings (bspbrush_t *brush); -bspbrush_t *BrushFromBounds (vec3_t mins, vec3_t maxs); -vec_t BrushVolume (bspbrush_t *brush); -void WriteBspBrushMap (char *name, bspbrush_t *list); - -void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree ); -void FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree ); - -//============================================================================= - -// map.c - -extern int entitySourceBrushes; - -// mapplanes[ num^1 ] will always be the mirror or mapplanes[ num ] -// nummapplanes will always be even -extern plane_t mapplanes[MAX_MAP_PLANES]; -extern int nummapplanes; - -extern vec3_t map_mins, map_maxs; - -extern char mapIndexedShaders[MAX_MAP_BRUSHSIDES][MAX_QPATH]; -extern int numMapIndexedShaders; - -extern entity_t *mapent; - -#define MAX_BUILD_SIDES 300 -extern bspbrush_t *buildBrush; - - -void LoadMapFile (char *filename); -int FindFloatPlane (vec3_t normal, vec_t dist); -int PlaneTypeForNormal (vec3_t normal); -bspbrush_t *FinishBrush( void ); -mapDrawSurface_t *AllocDrawSurf( void ); -mapDrawSurface_t *DrawSurfaceForSide( bspbrush_t *b, side_t *s, winding_t *w ); - -//============================================================================= - -//============================================================================= - -// draw.c - -extern vec3_t draw_mins, draw_maxs; -extern qboolean drawflag; - -void Draw_ClearWindow (void); -void DrawWinding (winding_t *w); - -void GLS_BeginScene (void); -void GLS_Winding (winding_t *w, int code); -void GLS_EndScene (void); - -//============================================================================= - -// csg - -bspbrush_t *MakeBspBrushList ( bspbrush_t *brushes, vec3_t clipmins, vec3_t clipmaxs); - -//============================================================================= - -// brushbsp - -#define PSIDE_FRONT 1 -#define PSIDE_BACK 2 -#define PSIDE_BOTH (PSIDE_FRONT|PSIDE_BACK) -#define PSIDE_FACING 4 - -int BoxOnPlaneSide (vec3_t mins, vec3_t maxs, plane_t *plane); -qboolean WindingIsTiny (winding_t *w); - -void SplitBrush (bspbrush_t *brush, int planenum, - bspbrush_t **front, bspbrush_t **back); - -tree_t *AllocTree (void); -node_t *AllocNode (void); - -tree_t *BrushBSP (bspbrush_t *brushlist, vec3_t mins, vec3_t maxs); - -//============================================================================= - -// portals.c - -void MakeHeadnodePortals (tree_t *tree); -void MakeNodePortal (node_t *node); -void SplitNodePortals (node_t *node); - -qboolean Portal_Passable(portal_t *p); - -qboolean FloodEntities (tree_t *tree); -void FillOutside (node_t *headnode); -void FloodAreas (tree_t *tree); -bspface_t *VisibleFaces(entity_t *e, tree_t *tree); -void FreePortal (portal_t *p); - -void MakeTreePortals (tree_t *tree); - -//============================================================================= - -// glfile.c - -void OutputWinding( winding_t *w, FILE *glview ); -void WriteGLView( tree_t *tree, char *source ); - -//============================================================================= - -// leakfile.c - -void LeakFile( tree_t *tree ); - -//============================================================================= - -// prtfile.c - -void NumberClusters( tree_t *tree ); -void WritePortalFile( tree_t *tree ); - -//============================================================================= - -// writebsp.c - -void SetModelNumbers (void); -void SetLightStyles (void); - -int EmitShader( const char *shader ); - -void BeginBSPFile (void); -void EndBSPFile (void); - -void BeginModel (void); -void EndModel( node_t *headnode ); - - -//============================================================================= - -// tree.c - -void FreeTree (tree_t *tree); -void FreeTree_r (node_t *node); -void PrintTree_r (node_t *node, int depth); -void FreeTreePortals_r (node_t *node); - -//============================================================================= - -// patch.c - -extern int numMapPatches; - -mapDrawSurface_t *DrawSurfaceForMesh( mesh_t *m ); -void ParsePatch( void ); -mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength ); -void PatchMapDrawSurfs( entity_t *e ); - -//============================================================================= - -// lightmap.c - -void AllocateLightmaps( entity_t *e ); - -//============================================================================= - -// tjunction.c - -void FixTJunctions( entity_t *e ); - - -//============================================================================= - -// fog.c - -void FogDrawSurfs( void ); -winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds ); - -//============================================================================= - -// facebsp.c - -bspface_t *BspFaceForPortal( portal_t *p ); -bspface_t *MakeStructuralBspFaceList( bspbrush_t *list ); -bspface_t *MakeVisibleBspFaceList( bspbrush_t *list ); -tree_t *FaceBSP( bspface_t *list ); - -//============================================================================= - -// misc_model.c - -extern int c_triangleModels; -extern int c_triangleSurfaces; -extern int c_triangleVertexes; -extern int c_triangleIndexes; - -void AddTriangleModels( tree_t *tree ); - -//============================================================================= - -// surface.c - -extern mapDrawSurface_t mapDrawSurfs[MAX_MAP_DRAW_SURFS]; -extern int numMapDrawSurfs; - -mapDrawSurface_t *AllocDrawSurf( void ); -void MergeSides( entity_t *e, tree_t *tree ); -void SubdivideDrawSurfs( entity_t *e, tree_t *tree ); -void MakeDrawSurfaces( bspbrush_t *b ); -void ClipSidesIntoTree( entity_t *e, tree_t *tree ); -void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree ); - -//============================================================================== - -// brush_primit.c - -#define BPRIMIT_UNDEFINED 0 -#define BPRIMIT_OLDBRUSHES 1 -#define BPRIMIT_NEWBRUSHES 2 -extern int g_bBrushPrimit; - -void ComputeAxisBase( vec3_t normal, vec3_t texX, vec3_t texY); diff --git a/q3map/shaders.c b/q3map/shaders.c deleted file mode 100644 index 4adfcf0..0000000 --- a/q3map/shaders.c +++ /dev/null @@ -1,608 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include <string.h> -#include <math.h> -#include "cmdlib.h" -#include "mathlib.h" -#include "imagelib.h" -#include "scriplib.h" - -#ifdef _TTIMOBUILD -#include "../common/qfiles.h" -#include "../common/surfaceflags.h" -#else -#include "../code/qcommon/qfiles.h" -#include "../code/game/surfaceflags.h" -#endif - -#include "shaders.h" -#ifdef _WIN32 - -#ifdef _TTIMOBUILD -#include "pakstuff.h" -#include "jpeglib.h" -#else -#include "../libs/pakstuff.h" -#include "../libs/jpeglib.h" -#endif - -#endif - - -// 5% backsplash by default -#define DEFAULT_BACKSPLASH_FRACTION 0.05 -#define DEFAULT_BACKSPLASH_DISTANCE 24 - - -#define MAX_SURFACE_INFO 4096 - -shaderInfo_t defaultInfo; -shaderInfo_t shaderInfo[MAX_SURFACE_INFO]; -int numShaderInfo; - - -typedef struct { - char *name; - int clearSolid, surfaceFlags, contents; -} infoParm_t; - -infoParm_t infoParms[] = { - // server relevant contents - {"water", 1, 0, CONTENTS_WATER }, - {"slime", 1, 0, CONTENTS_SLIME }, // mildly damaging - {"lava", 1, 0, CONTENTS_LAVA }, // very damaging - {"playerclip", 1, 0, CONTENTS_PLAYERCLIP }, - {"monsterclip", 1, 0, CONTENTS_MONSTERCLIP }, - {"nodrop", 1, 0, CONTENTS_NODROP }, // don't drop items or leave bodies (death fog, lava, etc) - {"nonsolid", 1, SURF_NONSOLID, 0}, // clears the solid flag - - // utility relevant attributes - {"origin", 1, 0, CONTENTS_ORIGIN }, // center of rotating brushes - {"trans", 0, 0, CONTENTS_TRANSLUCENT }, // don't eat contained surfaces - {"detail", 0, 0, CONTENTS_DETAIL }, // don't include in structural bsp - {"structural", 0, 0, CONTENTS_STRUCTURAL }, // force into structural bsp even if trnas - {"areaportal", 1, 0, CONTENTS_AREAPORTAL }, // divides areas - {"clusterportal",1, 0, CONTENTS_CLUSTERPORTAL },// for bots - {"donotenter", 1, 0, CONTENTS_DONOTENTER }, // for bots - {"botclip", 1, 0, CONTENTS_BOTCLIP }, // for bots - {"nobotclip", 0, 0, CONTENTS_NOBOTCLIP }, // don't use for bot clipping - - {"fog", 1, 0, CONTENTS_FOG}, // carves surfaces entering - {"sky", 0, SURF_SKY, 0 }, // emit light from an environment map - {"lightfilter", 0, SURF_LIGHTFILTER, 0 }, // filter light going through it - {"alphashadow", 0, SURF_ALPHASHADOW, 0 }, // test light on a per-pixel basis - {"hint", 0, SURF_HINT, 0 }, // use as a primary splitter - - // server attributes - {"slick", 0, SURF_SLICK, 0 }, - {"noimpact", 0, SURF_NOIMPACT, 0 }, // don't make impact explosions or marks - {"nomarks", 0, SURF_NOMARKS, 0 }, // don't make impact marks, but still explode - {"ladder", 0, SURF_LADDER, 0 }, - {"nodamage", 0, SURF_NODAMAGE, 0 }, - {"metalsteps", 0, SURF_METALSTEPS,0 }, - {"flesh", 0, SURF_FLESH, 0 }, - {"nosteps", 0, SURF_NOSTEPS, 0 }, - - // drawsurf attributes - {"nodraw", 0, SURF_NODRAW, 0 }, // don't generate a drawsurface (or a lightmap) - {"pointlight", 0, SURF_POINTLIGHT, 0 }, // sample lighting at vertexes - {"nolightmap", 0, SURF_NOLIGHTMAP,0 }, // don't generate a lightmap - {"nodlight", 0, SURF_NODLIGHT, 0 }, // don't ever add dynamic lights - {"dust", 0, SURF_DUST, 0} // leave dust trail when walking on this surface -}; - - -/* -=============== -LoadShaderImage -=============== -*/ - -byte* LoadImageFile(char *filename, qboolean *bTGA) -{ - byte *buffer = NULL; - int nLen = 0; - *bTGA = qtrue; - if (FileExists(filename)) - { - LoadFileBlock(filename, &buffer); - } -#ifdef _WIN32 - else - { - PakLoadAnyFile(filename, &buffer); - } -#endif - if ( buffer == NULL) - { - nLen = strlen(filename); - filename[nLen-3] = 'j'; - filename[nLen-2] = 'p'; - filename[nLen-1] = 'g'; - if (FileExists(filename)) - { - LoadFileBlock(filename, &buffer); - } -#ifdef _WIN32 - else - { - PakLoadAnyFile(filename, &buffer); - } -#endif - if ( buffer ) - { - *bTGA = qfalse; - } - } - return buffer; -} - -/* -=============== -LoadShaderImage -=============== -*/ -static void LoadShaderImage( shaderInfo_t *si ) { - char filename[1024]; - int i, count; - float color[4]; - byte *buffer; - qboolean bTGA = qtrue; - - // look for the lightimage if it is specified - if ( si->lightimage[0] ) { - sprintf( filename, "%s%s", gamedir, si->lightimage ); - DefaultExtension( filename, ".tga" ); - buffer = LoadImageFile(filename, &bTGA); - if ( buffer != NULL) { - goto loadTga; - } - } - - // look for the editorimage if it is specified - if ( si->editorimage[0] ) { - sprintf( filename, "%s%s", gamedir, si->editorimage ); - DefaultExtension( filename, ".tga" ); - buffer = LoadImageFile(filename, &bTGA); - if ( buffer != NULL) { - goto loadTga; - } - } - - // just try the shader name with a .tga - // on unix, we have case sensitivity problems... - sprintf( filename, "%s%s.tga", gamedir, si->shader ); - buffer = LoadImageFile(filename, &bTGA); - if ( buffer != NULL) { - goto loadTga; - } - - sprintf( filename, "%s%s.TGA", gamedir, si->shader ); - buffer = LoadImageFile(filename, &bTGA); - if ( buffer != NULL) { - goto loadTga; - } - - // couldn't load anything - _printf("WARNING: Couldn't find image for shader %s\n", si->shader ); - - si->color[0] = 1; - si->color[1] = 1; - si->color[2] = 1; - si->width = 64; - si->height = 64; - si->pixels = malloc( si->width * si->height * 4 ); - memset ( si->pixels, 255, si->width * si->height * 4 ); - return; - - // load the image to get dimensions and color -loadTga: - if ( bTGA) { - LoadTGABuffer( buffer, &si->pixels, &si->width, &si->height ); - } - else { -#ifdef _WIN32 - LoadJPGBuff(buffer, &si->pixels, &si->width, &si->height ); -#endif - } - - free(buffer); - - count = si->width * si->height; - - VectorClear( color ); - color[ 3 ] = 0; - for ( i = 0 ; i < count ; i++ ) { - color[0] += si->pixels[ i * 4 + 0 ]; - color[1] += si->pixels[ i * 4 + 1 ]; - color[2] += si->pixels[ i * 4 + 2 ]; - color[3] += si->pixels[ i * 4 + 3 ]; - } - ColorNormalize( color, si->color ); - VectorScale( color, 1.0/count, si->averageColor ); -} - -/* -=============== -AllocShaderInfo -=============== -*/ -static shaderInfo_t *AllocShaderInfo( void ) { - shaderInfo_t *si; - - if ( numShaderInfo == MAX_SURFACE_INFO ) { - Error( "MAX_SURFACE_INFO" ); - } - si = &shaderInfo[ numShaderInfo ]; - numShaderInfo++; - - // set defaults - - si->contents = CONTENTS_SOLID; - - si->backsplashFraction = DEFAULT_BACKSPLASH_FRACTION; - si->backsplashDistance = DEFAULT_BACKSPLASH_DISTANCE; - - si->lightmapSampleSize = 0; - si->forceTraceLight = qfalse; - si->forceVLight = qfalse; - si->patchShadows = qfalse; - si->vertexShadows = qfalse; - si->noVertexShadows = qfalse; - si->forceSunLight = qfalse; - si->vertexScale = 1.0; - si->notjunc = qfalse; - - return si; -} - -/* -=============== -ShaderInfoForShader -=============== -*/ -shaderInfo_t *ShaderInfoForShader( const char *shaderName ) { - int i; - shaderInfo_t *si; - char shader[MAX_QPATH]; - - // strip off extension - strcpy( shader, shaderName ); - StripExtension( shader ); - - // search for it - for ( i = 0 ; i < numShaderInfo ; i++ ) { - si = &shaderInfo[ i ]; - if ( !Q_stricmp( shader, si->shader ) ) { - if ( !si->width ) { - LoadShaderImage( si ); - } - return si; - } - } - - si = AllocShaderInfo(); - strcpy( si->shader, shader ); - - LoadShaderImage( si ); - - return si; -} - -/* -=============== -ParseShaderFile -=============== -*/ -static void ParseShaderFile( const char *filename ) { - int i; - int numInfoParms = sizeof(infoParms) / sizeof(infoParms[0]); - shaderInfo_t *si; - -// qprintf( "shaderFile: %s\n", filename ); - LoadScriptFile( filename ); - while ( 1 ) { - if ( !GetToken( qtrue ) ) { - break; - } - - si = AllocShaderInfo(); - strcpy( si->shader, token ); - MatchToken( "{" ); - while ( 1 ) { - if ( !GetToken( qtrue ) ) { - break; - } - if ( !strcmp( token, "}" ) ) { - break; - } - - // skip internal braced sections - if ( !strcmp( token, "{" ) ) { - si->hasPasses = qtrue; - while ( 1 ) { - if ( !GetToken( qtrue ) ) { - break; - } - if ( !strcmp( token, "}" ) ) { - break; - } - } - continue; - } - - if ( !Q_stricmp( token, "surfaceparm" ) ) { - GetToken( qfalse ); - for ( i = 0 ; i < numInfoParms ; i++ ) { - if ( !Q_stricmp( token, infoParms[i].name ) ) { - si->surfaceFlags |= infoParms[i].surfaceFlags; - si->contents |= infoParms[i].contents; - if ( infoParms[i].clearSolid ) { - si->contents &= ~CONTENTS_SOLID; - } - break; - } - } - if ( i == numInfoParms ) { - // we will silently ignore all tokens beginning with qer, - // which are QuakeEdRadient parameters - if ( Q_strncasecmp( token, "qer", 3 ) ) { - _printf( "Unknown surfaceparm: \"%s\"\n", token ); - } - } - continue; - } - - - // qer_editorimage <image> - if ( !Q_stricmp( token, "qer_editorimage" ) ) { - GetToken( qfalse ); - strcpy( si->editorimage, token ); - DefaultExtension( si->editorimage, ".tga" ); - continue; - } - - // q3map_lightimage <image> - if ( !Q_stricmp( token, "q3map_lightimage" ) ) { - GetToken( qfalse ); - strcpy( si->lightimage, token ); - DefaultExtension( si->lightimage, ".tga" ); - continue; - } - - // q3map_surfacelight <value> - if ( !Q_stricmp( token, "q3map_surfacelight" ) ) { - GetToken( qfalse ); - si->value = atoi( token ); - continue; - } - - // q3map_lightsubdivide <value> - if ( !Q_stricmp( token, "q3map_lightsubdivide" ) ) { - GetToken( qfalse ); - si->lightSubdivide = atoi( token ); - continue; - } - - // q3map_lightmapsamplesize <value> - if ( !Q_stricmp( token, "q3map_lightmapsamplesize" ) ) { - GetToken( qfalse ); - si->lightmapSampleSize = atoi( token ); - continue; - } - - // q3map_tracelight - if ( !Q_stricmp( token, "q3map_tracelight" ) ) { - si->forceTraceLight = qtrue; - continue; - } - - // q3map_vlight - if ( !Q_stricmp( token, "q3map_vlight" ) ) { - si->forceVLight = qtrue; - continue; - } - - // q3map_patchshadows - if ( !Q_stricmp( token, "q3map_patchshadows" ) ) { - si->patchShadows = qtrue; - continue; - } - - // q3map_vertexshadows - if ( !Q_stricmp( token, "q3map_vertexshadows" ) ) { - si->vertexShadows = qtrue; - continue; - } - - // q3map_novertexshadows - if ( !Q_stricmp( token, "q3map_novertexshadows" ) ) { - si->noVertexShadows = qtrue; - continue; - } - - // q3map_forcesunlight - if ( !Q_stricmp( token, "q3map_forcesunlight" ) ) { - si->forceSunLight = qtrue; - continue; - } - - // q3map_vertexscale - if ( !Q_stricmp( token, "q3map_vertexscale" ) ) { - GetToken( qfalse ); - si->vertexScale = atof(token); - continue; - } - - // q3map_notjunc - if ( !Q_stricmp( token, "q3map_notjunc" ) ) { - si->notjunc = qtrue; - continue; - } - - // q3map_globaltexture - if ( !Q_stricmp( token, "q3map_globaltexture" ) ) { - si->globalTexture = qtrue; - continue; - } - - // q3map_backsplash <percent> <distance> - if ( !Q_stricmp( token, "q3map_backsplash" ) ) { - GetToken( qfalse ); - si->backsplashFraction = atof( token ) * 0.01; - GetToken( qfalse ); - si->backsplashDistance = atof( token ); - continue; - } - - // q3map_backshader <shader> - if ( !Q_stricmp( token, "q3map_backshader" ) ) { - GetToken( qfalse ); - strcpy( si->backShader, token ); - continue; - } - - // q3map_flare <shader> - if ( !Q_stricmp( token, "q3map_flare" ) ) { - GetToken( qfalse ); - strcpy( si->flareShader, token ); - continue; - } - - // light <value> - // old style flare specification - if ( !Q_stricmp( token, "light" ) ) { - GetToken( qfalse ); - strcpy( si->flareShader, "flareshader" ); - continue; - } - - // q3map_sun <red> <green> <blue> <intensity> <degrees> <elivation> - // color will be normalized, so it doesn't matter what range you use - // intensity falls off with angle but not distance 100 is a fairly bright sun - // degree of 0 = from the east, 90 = north, etc. altitude of 0 = sunrise/set, 90 = noon - if ( !Q_stricmp( token, "q3map_sun" ) ) { - float a, b; - - GetToken( qfalse ); - si->sunLight[0] = atof( token ); - GetToken( qfalse ); - si->sunLight[1] = atof( token ); - GetToken( qfalse ); - si->sunLight[2] = atof( token ); - - VectorNormalize( si->sunLight, si->sunLight); - - GetToken( qfalse ); - a = atof( token ); - VectorScale( si->sunLight, a, si->sunLight); - - GetToken( qfalse ); - a = atof( token ); - a = a / 180 * Q_PI; - - GetToken( qfalse ); - b = atof( token ); - b = b / 180 * Q_PI; - - si->sunDirection[0] = cos( a ) * cos( b ); - si->sunDirection[1] = sin( a ) * cos( b ); - si->sunDirection[2] = sin( b ); - - si->surfaceFlags |= SURF_SKY; - continue; - } - - // tesssize is used to force liquid surfaces to subdivide - if ( !Q_stricmp( token, "tesssize" ) ) { - GetToken( qfalse ); - si->subdivisions = atof( token ); - continue; - } - - // cull none will set twoSided - if ( !Q_stricmp( token, "cull" ) ) { - GetToken( qfalse ); - if ( !Q_stricmp( token, "none" ) ) { - si->twoSided = qtrue; - } - continue; - } - - - // deformVertexes autosprite[2] - // we catch this so autosprited surfaces become point - // lights instead of area lights - if ( !Q_stricmp( token, "deformVertexes" ) ) { - GetToken( qfalse ); - if ( !Q_strncasecmp( token, "autosprite", 10 ) ) { - si->autosprite = qtrue; - si->contents = CONTENTS_DETAIL; - } - continue; - } - - - // ignore all other tokens on the line - - while ( TokenAvailable() ) { - GetToken( qfalse ); - } - } - } -} - -/* -=============== -LoadShaderInfo -=============== -*/ -#define MAX_SHADER_FILES 64 -void LoadShaderInfo( void ) { - char filename[1024]; - int i; - char *shaderFiles[MAX_SHADER_FILES]; - int numShaderFiles; - - sprintf( filename, "%sscripts/shaderlist.txt", gamedir ); - LoadScriptFile( filename ); - - numShaderFiles = 0; - while ( 1 ) { - if ( !GetToken( qtrue ) ) { - break; - } - shaderFiles[numShaderFiles] = malloc(MAX_OS_PATH); - strcpy( shaderFiles[ numShaderFiles ], token ); - numShaderFiles++; - } - - for ( i = 0 ; i < numShaderFiles ; i++ ) { - sprintf( filename, "%sscripts/%s.shader", gamedir, shaderFiles[i] ); - ParseShaderFile( filename ); - free(shaderFiles[i]); - } - - qprintf( "%5i shaderInfo\n", numShaderInfo); -} - diff --git a/q3map/shaders.h b/q3map/shaders.h deleted file mode 100644 index 27918bb..0000000 --- a/q3map/shaders.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - - -typedef struct shaderInfo_s { - char shader[MAX_QPATH]; - int surfaceFlags; - int contents; - int value; - - char backShader[MAX_QPATH]; // for surfaces that generate different front and back passes - char flareShader[MAX_QPATH]; // for light flares - - float subdivisions; // from a "tesssize xxx" - float backsplashFraction; // floating point value, usually 0.05 - float backsplashDistance; // default 16 - float lightSubdivide; // default 120 - int lightmapSampleSize; // lightmap sample size - - qboolean hasPasses; // false if the shader doesn't define any rendering passes - - qboolean globalTexture; // don't normalize texture repeats - - qboolean twoSided; // cull none - qboolean autosprite; // autosprite shaders will become point lights - // instead of area lights - qboolean lightFilter; // light rays that cross surfaces of this type - // should test against the filter image - qboolean forceTraceLight; // always use -light for this surface - qboolean forceVLight; // always use -vlight for this surface - qboolean patchShadows; // have patches casting shadows when using -light for this surface - qboolean vertexShadows; // shadows will be casted at this surface even when vertex lit - qboolean noVertexShadows; // no shadows will be casted at this surface in vertex lighting - qboolean forceSunLight; // force sun light at this surface even tho we might not calculate shadows in vertex lighting - qboolean notjunc; // don't use this surface for tjunction fixing - float vertexScale; // vertex light scale - - char editorimage[MAX_QPATH]; // use this image to generate texture coordinates - char lightimage[MAX_QPATH]; // use this image to generate color / averageColor - vec3_t color; // colorNormalized - vec3_t averageColor; - - int width, height; - byte *pixels; - - vec3_t sunLight; - vec3_t sunDirection; -} shaderInfo_t; - -void LoadShaderInfo( void ); -shaderInfo_t *ShaderInfoForShader( const char *shader ); - diff --git a/q3map/soundv.c b/q3map/soundv.c deleted file mode 100644 index e7a57b6..0000000 --- a/q3map/soundv.c +++ /dev/null @@ -1,5742 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -/***************************************************************************** - * name: soundv.c - *****************************************************************************/ - -#include "cmdlib.h" -#include "mathlib.h" -#include "bspfile.h" -#include "imagelib.h" -#include "threads.h" -#include "mutex.h" -#include "scriplib.h" - -#include "shaders.h" -#include "mesh.h" - -#ifdef _WIN32 -//Improve floating-point consistency. -#pragma optimize( "p", on ) -#endif - -#ifdef _WIN32 -#include "../libs/pakstuff.h" -#endif - -#define MAX_CLUSTERS 16384 -#define MAX_PORTALS 32768 -#define MAX_FACETS 65536 -#define MAX_LIGHTS 16384 - -#define LIGHTMAP_SIZE 128 - -#define LIGHTMAP_PIXELSHIFT 0.5 - -//#define LIGHTMAP_PATCHSHIFT - -#define PORTALFILE "PRT1" - -#define ON_EPSILON 0.1 - -#define VectorSet(v, x, y, z) v[0] = x;v[1] = y;v[2] = z; - -typedef struct -{ - vec3_t normal; - float dist; -} plane_t; - -#define MAX_POINTS_ON_WINDING 64 -//NOTE: whenever this is overflowed parts of lightmaps might end up not being lit -#define MAX_POINTS_ON_FIXED_WINDING 48 - -typedef struct -{ - int numpoints; - vec3_t points[MAX_POINTS_ON_FIXED_WINDING]; // variable sized -} winding_t; - -typedef struct -{ - plane_t plane; // normal pointing into neighbor - int leaf; // neighbor - winding_t *winding; - vec3_t origin; // for fast clip testing - float radius; -} lportal_t; - -#define MAX_PORTALS_ON_LEAF 128 -typedef struct lleaf_s -{ - int numportals; - lportal_t *portals[MAX_PORTALS_ON_LEAF]; - // - int numSurfaces; - int firstSurface; -} lleaf_t; - -typedef struct lFacet_s -{ - int num; - plane_t plane; - vec3_t points[4]; // - int numpoints; - float lightmapCoords[4][2]; - plane_t boundaries[4]; // negative is outside the bounds - float textureMatrix[2][4]; // texture coordinates for translucency - float lightmapMatrix[2][4]; // lightmap texture coordinates - vec3_t mins; - int x, y, width, height; -} lFacet_t; - -typedef struct lsurfaceTest_s -{ - vec3_t mins, maxs; - vec3_t origin; - float radius; - qboolean patch; // true if this is a patch - qboolean trisoup; // true if this is a triangle soup - int numFacets; - lFacet_t *facets; - mesh_t *detailMesh; // detailed mesh with points for each lmp - shaderInfo_t *shader; // for translucency - mutex_t *mutex; - int numvolumes; // number of volumes casted at this surface - // - int always_tracelight; - int always_vsound; -} lsurfaceTest_t; - -//volume types -#define VOLUME_NORMAL 0 -#define VOLUME_DIRECTED 1 - -#define MAX_TRANSLUCENTFACETS 32 - -typedef struct lightvolume_s -{ - int num; - int cluster; //cluster this light volume started in - plane_t endplane; //end plane - plane_t farplane; //original end plane - vec3_t points[MAX_POINTS_ON_WINDING]; //end winding points - plane_t planes[MAX_POINTS_ON_WINDING]; //volume bounding planes - int numplanes; //number of volume bounding planes - int type; //light volume type - //list with translucent surfaces the volume went through - int transFacets[MAX_TRANSLUCENTFACETS]; - int transSurfaces[MAX_TRANSLUCENTFACETS]; - int numtransFacets; - //clusters already tested - byte clusterTested[MAX_CLUSTERS/8]; - //facets already tested - byte facetTested[MAX_FACETS/8]; - int facetNum; //number of the facet blocking the light in this volume - int surfaceNum; //number of the surface blocking the light in this volume -} lightvolume_t; - -//light types -#define LIGHT_POINTRADIAL 1 -#define LIGHT_POINTSPOT 2 -#define LIGHT_POINTFAKESURFACE 3 -#define LIGHT_SURFACEDIRECTED 4 -#define LIGHT_SURFACERADIAL 5 -#define LIGHT_SURFACESPOT 6 - -//light distance attenuation types -#define LDAT_QUADRATIC 0 -#define LDAT_LINEAR 1 -#define LDAT_NOSCALE 2 - -//light angle attenuation types -#define LAAT_NORMAL 0 -#define LAAT_QUADRATIC 1 -#define LAAT_DOUBLEQUADRATIC 2 - -typedef struct vsound_s -{ - vec3_t origin; //light origin, for point lights - winding_t w; //light winding, for area lights - vec4_t plane; //light winding plane - vec3_t normal; //direction of the light - int type; //light type - vec3_t color; //light color - qboolean twosided; //radiates light at both sides of the winding - int style; //light style (not used) - int atten_disttype; //light distance attenuation type - int atten_angletype; //light angle attenuation type - float atten_distscale; //distance attenuation scale - float atten_anglescale; //angle attenuation scale - float radiusByDist; //radius by distance for spot lights - float photons; //emitted photons - float intensity; //intensity - vec3_t emitColor; //full out-of-gamut value (not used) - struct shaderInfo_s *si; //shader info - int insolid; //set when light is in solid -} vsound_t; - -static float lightLinearScale = 1.0 / 8000; -static float lightPointScale = 7500; -static float lightAreaScale = 0.25; -static float lightFormFactorValueScale = 3; -static int lightDefaultSubdivide = 999; // vary by surface size? -static vec3_t lightAmbientColor; - -static int portalclusters, numportals, numfaces; -static lleaf_t *leafs; -static lportal_t *portals; -static int numvsounds = 0; -static vsound_t *vsounds[MAX_LIGHTS]; -static int nostitching = 0; -static int noalphashading = 0; -static int nocolorshading = 0; -static int nobackfaceculling = 0; -static int defaulttracelight = 0; -static int radiosity = 0; -static int radiosity_scale; - -static int clustersurfaces[MAX_MAP_LEAFFACES]; -static int numclustersurfaces = 0; -static lsurfaceTest_t *lsurfaceTest[MAX_MAP_DRAW_SURFS]; -static int numfacets; -static float lightmappixelarea[MAX_MAP_LIGHTING/3]; -static float *lightFloats;//[MAX_MAP_LIGHTING]; - -// from polylib.c -winding_t *AllocWinding (int points); -void FreeWinding (winding_t *w); -void WindingCenter (winding_t *w, vec3_t center); -void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs); -vec_t WindingArea (winding_t *w); -winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist); -void ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, - vec_t epsilon, winding_t **front, winding_t **back); -winding_t *ReverseWinding (winding_t *w); - -// from light.c -extern char source[1024]; -extern vec3_t surfaceOrigin[ MAX_MAP_DRAW_SURFS ]; -extern int entitySurface[ MAX_MAP_DRAW_SURFS ]; -extern int samplesize; -extern qboolean patchshadows; -extern vec3_t gridSize; - -float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const winding_t *w ); -void ColorToBytes( const float *color, byte *colorBytes ); -void CountLightmaps( void ); -void GridAndVertexLighting( void ); -void SetEntityOrigins( void ); - - -//#define DEBUGNET - -#ifdef DEBUGNET - -#include "l_net.h" - -socket_t *debug_socket; - -/* -===================== -DebugNet_Setup -===================== -*/ -void DebugNet_Setup(void) -{ - address_t address; - int i; - - Net_Setup(); - Net_StringToAddress("127.0.0.1:28000", &address); - for (i = 0; i < 10; i++) - { - debug_socket = Net_Connect(&address, 28005 + i); - if (debug_socket) - break; - } -} - -/* -===================== -DebugNet_Shutdown -===================== -*/ -void DebugNet_Shutdown(void) -{ - netmessage_t msg; - - if (debug_socket) - { - NMSG_Clear(&msg); - NMSG_WriteByte(&msg, 1); - Net_Send(debug_socket, &msg); - Net_Disconnect(debug_socket); - } - debug_socket = NULL; - Net_Shutdown(); -} - -/* -===================== -DebugNet_RemoveAllPolys -===================== -*/ -void DebugNet_RemoveAllPolys(void) -{ - netmessage_t msg; - - if (!debug_socket) - return; - NMSG_Clear(&msg); - NMSG_WriteByte(&msg, 2); //remove all debug polys - Net_Send(debug_socket, &msg); -} - -/* -==================== -DebugNet_DrawWinding -===================== -*/ -void DebugNet_DrawWinding(winding_t *w, int color) -{ - netmessage_t msg; - int i; - - if (!debug_socket) - return; - NMSG_Clear(&msg); - NMSG_WriteByte(&msg, 0); //draw a winding - NMSG_WriteByte(&msg, w->numpoints); //number of points - NMSG_WriteLong(&msg, color); //color - for (i = 0; i < w->numpoints; i++) - { - NMSG_WriteFloat(&msg, w->points[i][0]); - NMSG_WriteFloat(&msg, w->points[i][1]); - NMSG_WriteFloat(&msg, w->points[i][2]); - } - Net_Send(debug_socket, &msg); -} - -/* -===================== -DebugNet_DrawLine -===================== -*/ -void DebugNet_DrawLine(vec3_t p1, vec3_t p2, int color) -{ - netmessage_t msg; - - if (!debug_socket) - return; - NMSG_Clear(&msg); - NMSG_WriteByte(&msg, 1); //draw a line - NMSG_WriteLong(&msg, color); //color - NMSG_WriteFloat(&msg, p1[0]); - NMSG_WriteFloat(&msg, p1[1]); - NMSG_WriteFloat(&msg, p1[2]); - NMSG_WriteFloat(&msg, p2[0]); - NMSG_WriteFloat(&msg, p2[1]); - NMSG_WriteFloat(&msg, p2[2]); - Net_Send(debug_socket, &msg); -} - -/* -===================== -DebugNet_DrawMesh -===================== -*/ -void DebugNet_DrawMesh(mesh_t *mesh) -{ - int i, j; - float dot; - drawVert_t *v1, *v2, *v3, *v4; - winding_t winding; - plane_t plane; - vec3_t d1, d2; - - for ( i = 0 ; i < mesh->width - 1 ; i++ ) { - for ( j = 0 ; j < mesh->height - 1 ; j++ ) { - - v1 = mesh->verts + j * mesh->width + i; - v2 = v1 + 1; - v3 = v1 + mesh->width + 1; - v4 = v1 + mesh->width; - - VectorSubtract( v4->xyz, v1->xyz, d1 ); - VectorSubtract( v3->xyz, v1->xyz, d2 ); - CrossProduct( d2, d1, plane.normal ); - if ( VectorNormalize( plane.normal, plane.normal ) != 0 ) - { - plane.dist = DotProduct( v1->xyz, plane.normal ); - dot = DotProduct(plane.normal, v2->xyz) - plane.dist; - if (fabs(dot) < 0.1) - { - VectorCopy(v1->xyz, winding.points[0]); - VectorCopy(v4->xyz, winding.points[1]); - VectorCopy(v3->xyz, winding.points[2]); - VectorCopy(v2->xyz, winding.points[3]); - winding.numpoints = 4; - DebugNet_DrawWinding(&winding, 2); - continue; - } - } - - winding.numpoints = 3; - VectorCopy(v1->xyz, winding.points[0]); - VectorCopy(v4->xyz, winding.points[1]); - VectorCopy(v3->xyz, winding.points[2]); - DebugNet_DrawWinding(&winding, 2); - - VectorCopy(v1->xyz, winding.points[0]); - VectorCopy(v3->xyz, winding.points[1]); - VectorCopy(v2->xyz, winding.points[2]); - DebugNet_DrawWinding(&winding, 2); - } - } -} - -/* -===================== -VS_DrawLightVolume -===================== -*/ -int VS_ChopWinding (winding_t *in, plane_t *split, float epsilon); - -void VS_DrawLightVolume(vsound_t *light, lightvolume_t *volume) -{ - winding_t w; - int i; - vec3_t p2, invsound; - - memcpy(w.points, volume->points, volume->numplanes * sizeof(vec3_t)); - w.numpoints = volume->numplanes; - DebugNet_DrawWinding(&w, 2); - - if (volume->type == VOLUME_DIRECTED) - { - VectorCopy(light->normal, invsound); - VectorInverse(invsound); - for (i = 0; i < volume->numplanes; i++) - { - VectorCopy(volume->points[i], w.points[0]); - VectorCopy(volume->points[(i+1) % volume->numplanes], w.points[1]); - VectorMA(w.points[1], MAX_WORLD_COORD, invsound, w.points[2]); - VectorMA(w.points[0], MAX_WORLD_COORD, invsound, w.points[3]); - w.numpoints = 4; - DebugNet_DrawWinding(&w, 2); - VectorMA(volume->points[i], 8, volume->planes[i].normal, p2); - DebugNet_DrawLine(volume->points[i], p2, 3); - } - } - else - { - // - VectorCopy(light->origin, w.points[0]); - w.numpoints = 3; - for (i = 0; i < volume->numplanes; i++) - { - VectorCopy(volume->points[i], w.points[1]); - VectorCopy(volume->points[(i+1) % volume->numplanes], w.points[2]); - VS_ChopWinding(&w, &volume->endplane, 0); - DebugNet_DrawWinding(&w, 2); - VectorMA(volume->points[i], 8, volume->planes[i].normal, p2); - DebugNet_DrawLine(volume->points[i], p2, 3); - } - } -} - -/* -============= -VS_DrawLightmapPixel -============= -*/ -void VS_DrawLightmapPixel(int surfaceNum, int x, int y, int color) -{ - winding_t w; - dsurface_t *ds; - mesh_t *mesh; - - ds = &drawSurfaces[surfaceNum]; - - if (ds->surfaceType == MST_PATCH) - { - mesh = lsurfaceTest[surfaceNum]->detailMesh; - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[0]); - VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[1]); - VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[2]); - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[3]); - w.numpoints = 4; - } - else - { - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT - ds->lightmapX, ds->lightmapVecs[0], w.points[0]); - VectorMA(w.points[0], (float) y - LIGHTMAP_PIXELSHIFT - ds->lightmapY, ds->lightmapVecs[1], w.points[0]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT - ds->lightmapX, ds->lightmapVecs[0], w.points[1]); - VectorMA(w.points[1], (float) y - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapY, ds->lightmapVecs[1], w.points[1]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapX, ds->lightmapVecs[0], w.points[2]); - VectorMA(w.points[2], (float) y - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapY, ds->lightmapVecs[1], w.points[2]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapX, ds->lightmapVecs[0], w.points[3]); - VectorMA(w.points[3], (float) y - LIGHTMAP_PIXELSHIFT - ds->lightmapY, ds->lightmapVecs[1], w.points[3]); - w.numpoints = 4; - } - DebugNet_DrawWinding(&w, color); -} - -/* -============ -VS_DrawPortals -============ -*/ -void VS_DrawPortals(void) -{ - int j; - lportal_t *p; - - for (j = 0; j < numportals * 2; j++) - { - p = portals + j; - DebugNet_DrawWinding(p->winding, 1); - } -} - -/* -============ -VS_DrawLeaf -============ -*/ -void VS_DrawLeaf(int cluster) -{ - int i; - lleaf_t *leaf; - lportal_t *p; - - leaf = &leafs[cluster]; - for (i = 0; i < leaf->numportals; i++) - { - p = leaf->portals[i]; - DebugNet_DrawWinding(p->winding, 1); - } -} - -#endif //DEBUGNET - -/* -============= -VS_SplitWinding -============= -*/ -int VS_SplitWinding (winding_t *in, winding_t *back, plane_t *split, float epsilon) -{ - vec_t dists[128]; - int sides[128]; - int counts[3]; - vec_t dot; - int i, j; - vec_t *p1, *p2; - vec3_t mid; - winding_t out; - winding_t *neww; - - counts[0] = counts[1] = counts[2] = 0; - - // determine sides for each point - for (i=0 ; i<in->numpoints ; i++) - { - dot = DotProduct (in->points[i], split->normal); - dot -= split->dist; - dists[i] = dot; - if (dot > epsilon) - sides[i] = SIDE_FRONT; - else if (dot < -epsilon) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - - if (!counts[SIDE_BACK]) - { - if (!counts[SIDE_FRONT]) - return SIDE_ON; - else - return SIDE_FRONT; - } - - if (!counts[SIDE_FRONT]) - { - return SIDE_BACK; - } - - sides[i] = sides[0]; - dists[i] = dists[0]; - - neww = &out; - - neww->numpoints = 0; - back->numpoints = 0; - - for (i=0 ; i<in->numpoints ; i++) - { - p1 = in->points[i]; - - if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VS_SplitWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; // can't chop -- fall back to original - } - if (back->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VS_SplitWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; - } - - if (sides[i] == SIDE_ON) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - VectorCopy (p1, back->points[back->numpoints]); - back->numpoints++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - } - if (sides[i] == SIDE_BACK) - { - VectorCopy (p1, back->points[back->numpoints]); - back->numpoints++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VS_SplitWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; // can't chop -- fall back to original - } - - if (back->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VS_SplitWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; // can't chop -- fall back to original - } - - // generate a split point - p2 = in->points[(i+1)%in->numpoints]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (split->normal[j] == 1) - mid[j] = split->dist; - else if (split->normal[j] == -1) - mid[j] = -split->dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, neww->points[neww->numpoints]); - neww->numpoints++; - VectorCopy (mid, back->points[back->numpoints]); - back->numpoints++; - } - memcpy(in, &out, sizeof(winding_t)); - - return SIDE_CROSS; -} - -/* -===================== -VS_LinkSurfaceIntoCluster -===================== -*/ -void VS_LinkSurfaceIntoCluster(int cluster, int surfaceNum) -{ - lleaf_t *leaf; - int i; - - leaf = &leafs[cluster]; - - for (i = 0; i < leaf->numSurfaces; i++) - { - if (clustersurfaces[leaf->firstSurface + i] == surfaceNum) - return; - } - for (i = numclustersurfaces; i > leaf->firstSurface + leaf->numSurfaces; i--) - clustersurfaces[i] = clustersurfaces[i-1]; - for (i = 0; i < portalclusters; i++) - { - if (i == cluster) - continue; - if (leafs[i].firstSurface >= leaf->firstSurface + leaf->numSurfaces) - leafs[i].firstSurface++; - } - clustersurfaces[leaf->firstSurface + leaf->numSurfaces] = surfaceNum; - leaf->numSurfaces++; - numclustersurfaces++; - if (numclustersurfaces >= MAX_MAP_LEAFFACES) - Error("MAX_MAP_LEAFFACES"); -} - -/* -===================== -VS_R_LinkSurface -===================== -*/ -void VS_R_LinkSurface(int nodenum, int surfaceNum, winding_t *w) -{ - int leafnum, cluster, res; - dnode_t *node; - dplane_t *plane; - winding_t back; - plane_t split; - - while(nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - - VectorCopy(plane->normal, split.normal); - split.dist = plane->dist; - res = VS_SplitWinding (w, &back, &split, 0.1); - - if (res == SIDE_FRONT) - { - nodenum = node->children[0]; - } - else if (res == SIDE_BACK) - { - nodenum = node->children[1]; - } - else if (res == SIDE_ON) - { - memcpy(&back, w, sizeof(winding_t)); - VS_R_LinkSurface(node->children[1], surfaceNum, &back); - nodenum = node->children[0]; - } - else - { - VS_R_LinkSurface(node->children[1], surfaceNum, &back); - nodenum = node->children[0]; - } - } - leafnum = -nodenum - 1; - cluster = dleafs[leafnum].cluster; - if (cluster != -1) - { - VS_LinkSurfaceIntoCluster(cluster, surfaceNum); - } -} - -/* -===================== -VS_LinkSurfaces - -maybe link each facet seperately instead of the test surfaces? -===================== -*/ -void VS_LinkSurfaces(void) -{ - int i, j; - lsurfaceTest_t *test; - lFacet_t *facet; - winding_t winding; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - for (j = 0; j < test->numFacets; j++) - { - facet = &test->facets[j]; - memcpy(winding.points, facet->points, facet->numpoints * sizeof(vec3_t)); - winding.numpoints = facet->numpoints; - VS_R_LinkSurface(0, i, &winding); - } - } -} - -/* -===================== -VS_TextureMatrixFromPoints -===================== -*/ -void VS_TextureMatrixFromPoints( lFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) { - int i, j; - float t; - float m[3][4]; - float s; - - // This is an incredibly stupid way of solving a three variable equation - for ( i = 0 ; i < 2 ; i++ ) { - - m[0][0] = a->xyz[0]; - m[0][1] = a->xyz[1]; - m[0][2] = a->xyz[2]; - m[0][3] = a->st[i]; - - m[1][0] = b->xyz[0]; - m[1][1] = b->xyz[1]; - m[1][2] = b->xyz[2]; - m[1][3] = b->st[i]; - - m[2][0] = c->xyz[0]; - m[2][1] = c->xyz[1]; - m[2][2] = c->xyz[2]; - m[2][3] = c->st[i]; - - if ( fabs(m[1][0]) > fabs(m[0][0]) && fabs(m[1][0]) > fabs(m[2][0]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[0][j]; - m[0][j] = m[1][j]; - m[1][j] = t; - } - } else if ( fabs(m[2][0]) > fabs(m[0][0]) && fabs(m[2][0]) > fabs(m[1][0]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[0][j]; - m[0][j] = m[2][j]; - m[2][j] = t; - } - } - - s = 1.0 / m[0][0]; - m[0][0] *= s; - m[0][1] *= s; - m[0][2] *= s; - m[0][3] *= s; - - s = m[1][0]; - m[1][0] -= m[0][0] * s; - m[1][1] -= m[0][1] * s; - m[1][2] -= m[0][2] * s; - m[1][3] -= m[0][3] * s; - - s = m[2][0]; - m[2][0] -= m[0][0] * s; - m[2][1] -= m[0][1] * s; - m[2][2] -= m[0][2] * s; - m[2][3] -= m[0][3] * s; - - if ( fabs(m[2][1]) > fabs(m[1][1]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[1][j]; - m[1][j] = m[2][j]; - m[2][j] = t; - } - } - - s = 1.0 / m[1][1]; - m[1][0] *= s; - m[1][1] *= s; - m[1][2] *= s; - m[1][3] *= s; - - s = m[2][1];// / m[1][1]; - m[2][0] -= m[1][0] * s; - m[2][1] -= m[1][1] * s; - m[2][2] -= m[1][2] * s; - m[2][3] -= m[1][3] * s; - - s = 1.0 / m[2][2]; - m[2][0] *= s; - m[2][1] *= s; - m[2][2] *= s; - m[2][3] *= s; - - f->textureMatrix[i][2] = m[2][3]; - f->textureMatrix[i][1] = m[1][3] - f->textureMatrix[i][2] * m[1][2]; - f->textureMatrix[i][0] = m[0][3] - f->textureMatrix[i][2] * m[0][2] - f->textureMatrix[i][1] * m[0][1]; - - f->textureMatrix[i][3] = 0; -/* - s = fabs( DotProduct( a->xyz, f->textureMatrix[i] ) - a->st[i] ); - if ( s > 0.01 ) { - Error( "Bad textureMatrix" ); - } - s = fabs( DotProduct( b->xyz, f->textureMatrix[i] ) - b->st[i] ); - if ( s > 0.01 ) { - Error( "Bad textureMatrix" ); - } - s = fabs( DotProduct( c->xyz, f->textureMatrix[i] ) - c->st[i] ); - if ( s > 0.01 ) { - Error( "Bad textureMatrix" ); - } -*/ - } -} - -/* -===================== -VS_LightmapMatrixFromPoints -===================== -*/ -void VS_LightmapMatrixFromPoints( dsurface_t *dsurf, shaderInfo_t *si, lFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) { - int i, j; - float t; - float m[3][4], al, bl, cl; - float s; - int h, w, ssize; - vec3_t mins, maxs, delta, size, planeNormal; - drawVert_t *verts; - static int message; - - // vertex-lit triangle model - if ( dsurf->surfaceType == MST_TRIANGLE_SOUP ) { - return; - } - - if ( dsurf->lightmapNum < 0 ) { - return; // doesn't need lighting - } - - VectorClear(f->mins); - if (dsurf->surfaceType != MST_PATCH) - { - ssize = samplesize; - if (si->lightmapSampleSize) - ssize = si->lightmapSampleSize; - ClearBounds( mins, maxs ); - verts = &drawVerts[dsurf->firstVert]; - for ( i = 0 ; i < dsurf->numVerts ; i++ ) { - AddPointToBounds( verts[i].xyz, mins, maxs ); - } - // round to the lightmap resolution - for ( i = 0 ; i < 3 ; i++ ) { - mins[i] = ssize * floor( mins[i] / ssize ); - maxs[i] = ssize * ceil( maxs[i] / ssize ); - f->mins[i] = mins[i]; - size[i] = (maxs[i] - mins[i]) / ssize + 1; - } - // the two largest axis will be the lightmap size - VectorClear(f->lightmapMatrix[0]); - f->lightmapMatrix[0][3] = 0; - VectorClear(f->lightmapMatrix[1]); - f->lightmapMatrix[1][3] = 0; - - planeNormal[0] = fabs( dsurf->lightmapVecs[2][0] ); - planeNormal[1] = fabs( dsurf->lightmapVecs[2][1] ); - planeNormal[2] = fabs( dsurf->lightmapVecs[2][2] ); - - if ( planeNormal[0] >= planeNormal[1] && planeNormal[0] >= planeNormal[2] ) { - w = size[1]; - h = size[2]; - f->lightmapMatrix[0][1] = 1.0 / ssize; - f->lightmapMatrix[1][2] = 1.0 / ssize; - } else if ( planeNormal[1] >= planeNormal[0] && planeNormal[1] >= planeNormal[2] ) { - w = size[0]; - h = size[2]; - f->lightmapMatrix[0][0] = 1.0 / ssize; - f->lightmapMatrix[1][2] = 1.0 / ssize; - } else { - w = size[0]; - h = size[1]; - f->lightmapMatrix[0][0] = 1.0 / ssize; - f->lightmapMatrix[1][1] = 1.0 / ssize; - } - if ( w > LIGHTMAP_WIDTH ) { - VectorScale ( f->lightmapMatrix[0], (float)LIGHTMAP_SIZE/w, f->lightmapMatrix[0] ); - } - - if ( h > LIGHTMAP_HEIGHT ) { - VectorScale ( f->lightmapMatrix[1], (float)LIGHTMAP_SIZE/h, f->lightmapMatrix[1] ); - } - VectorSubtract(a->xyz, f->mins, delta); - s = (DotProduct( delta, f->lightmapMatrix[0] ) + dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - if ( fabs(s - a->lightmap[0]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - t = (DotProduct( delta, f->lightmapMatrix[1] ) + dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - if ( fabs(t - a->lightmap[1]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - VectorSubtract(b->xyz, f->mins, delta); - s = (DotProduct( delta, f->lightmapMatrix[0] ) + dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - if ( fabs(s - b->lightmap[0]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - t = (DotProduct( delta, f->lightmapMatrix[1] ) + dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - if ( fabs(t - b->lightmap[1]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - VectorSubtract(c->xyz, f->mins, delta); - s = (DotProduct( delta, f->lightmapMatrix[0] ) + dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - if ( fabs(s - c->lightmap[0]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - t = (DotProduct( delta, f->lightmapMatrix[1] ) + dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - if ( fabs(t - c->lightmap[1]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - VectorAdd(f->mins, surfaceOrigin[dsurf - drawSurfaces], f->mins); - return; - } - // This is an incredibly stupid way of solving a three variable equation - for ( i = 0 ; i < 2 ; i++ ) { - - if (i) - al = a->lightmap[i] - ((float) dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - else - al = a->lightmap[i] - ((float) dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - - m[0][0] = a->xyz[0] - f->mins[0]; - m[0][1] = a->xyz[1] - f->mins[1]; - m[0][2] = a->xyz[2] - f->mins[2]; - m[0][3] = al; - - if (i) - bl = b->lightmap[i] - ((float) dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - else - bl = b->lightmap[i] - ((float) dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - - m[1][0] = b->xyz[0] - f->mins[0]; - m[1][1] = b->xyz[1] - f->mins[1]; - m[1][2] = b->xyz[2] - f->mins[2]; - m[1][3] = bl; - - if (i) - cl = c->lightmap[i] - ((float) dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - else - cl = c->lightmap[i] - ((float) dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - - m[2][0] = c->xyz[0] - f->mins[0]; - m[2][1] = c->xyz[1] - f->mins[1]; - m[2][2] = c->xyz[2] - f->mins[2]; - m[2][3] = cl; - - if ( fabs(m[1][0]) > fabs(m[0][0]) && fabs(m[1][0]) >= fabs(m[2][0]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[0][j]; - m[0][j] = m[1][j]; - m[1][j] = t; - } - } else if ( fabs(m[2][0]) > fabs(m[0][0]) && fabs(m[2][0]) >= fabs(m[1][0]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[0][j]; - m[0][j] = m[2][j]; - m[2][j] = t; - } - } - - if (m[0][0]) - { - s = 1.0 / m[0][0]; - m[0][0] *= s; - m[0][1] *= s; - m[0][2] *= s; - m[0][3] *= s; - - s = m[1][0]; - m[1][0] -= m[0][0] * s; - m[1][1] -= m[0][1] * s; - m[1][2] -= m[0][2] * s; - m[1][3] -= m[0][3] * s; - - s = m[2][0]; - m[2][0] -= m[0][0] * s; - m[2][1] -= m[0][1] * s; - m[2][2] -= m[0][2] * s; - m[2][3] -= m[0][3] * s; - } - - if ( fabs(m[2][1]) > fabs(m[1][1]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[1][j]; - m[1][j] = m[2][j]; - m[2][j] = t; - } - } - - if (m[1][1]) - { - s = 1.0 / m[1][1]; - m[1][0] *= s; - m[1][1] *= s; - m[1][2] *= s; - m[1][3] *= s; - - s = m[2][1]; - m[2][0] -= m[1][0] * s; - m[2][1] -= m[1][1] * s; - m[2][2] -= m[1][2] * s; - m[2][3] -= m[1][3] * s; - } - - if (m[2][2]) - { - s = 1.0 / m[2][2]; - m[2][0] *= s; - m[2][1] *= s; - m[2][2] *= s; - m[2][3] *= s; - } - - f->lightmapMatrix[i][2] = m[2][3]; - f->lightmapMatrix[i][1] = m[1][3] - f->lightmapMatrix[i][2] * m[1][2]; - f->lightmapMatrix[i][0] = m[0][3] - f->lightmapMatrix[i][2] * m[0][2] - f->lightmapMatrix[i][1] * m[0][1]; - - f->lightmapMatrix[i][3] = 0; - - VectorSubtract(a->xyz, f->mins, delta); - s = fabs( DotProduct( delta, f->lightmapMatrix[i] ) - al ); - if ( s > 0.01 ) { - if (!message) - _printf( "Bad lightmapMatrix\n" ); - message = qtrue; - } - VectorSubtract(b->xyz, f->mins, delta); - s = fabs( DotProduct( delta, f->lightmapMatrix[i] ) - bl ); - if ( s > 0.01 ) { - if (!message) - _printf( "Bad lightmapMatrix\n" ); - message = qtrue; - } - VectorSubtract(c->xyz, f->mins, delta); - s = fabs( DotProduct( delta, f->lightmapMatrix[i] ) - cl ); - if ( s > 0.01 ) { - if (!message) - _printf( "Bad lightmapMatrix\n" ); - message = qtrue; - } - VectorAdd(f->mins, surfaceOrigin[dsurf - drawSurfaces], f->mins); - } -} - -/* -============= -Plane_Equal -============= -*/ -#define NORMAL_EPSILON 0.0001 -#define DIST_EPSILON 0.02 - -static int Plane_Equal(plane_t *a, plane_t *b, int flip) -{ - vec3_t normal; - float dist; - - if (flip) { - normal[0] = - b->normal[0]; - normal[1] = - b->normal[1]; - normal[2] = - b->normal[2]; - dist = - b->dist; - } - else { - normal[0] = b->normal[0]; - normal[1] = b->normal[1]; - normal[2] = b->normal[2]; - dist = b->dist; - } - if ( - fabs(a->normal[0] - normal[0]) < NORMAL_EPSILON - && fabs(a->normal[1] - normal[1]) < NORMAL_EPSILON - && fabs(a->normal[2] - normal[2]) < NORMAL_EPSILON - && fabs(a->dist - dist) < DIST_EPSILON ) - return qtrue; - return qfalse; -} - -/* -============= -VS_PlaneFromPoints -============= -*/ -qboolean VS_PlaneFromPoints( plane_t *plane, const vec3_t a, const vec3_t b, const vec3_t c ) { - vec3_t d1, d2; - - VectorSubtract( b, a, d1 ); - VectorSubtract( c, a, d2 ); - CrossProduct( d2, d1, plane->normal ); - if ( VectorNormalize( plane->normal, plane->normal ) == 0 ) { - return qfalse; - } - - plane->dist = DotProduct( a, plane->normal ); - return qtrue; -} - -/* -===================== -VS_GenerateBoundaryForPoints -===================== -*/ -void VS_GenerateBoundaryForPoints( plane_t *boundary, plane_t *plane, vec3_t a, vec3_t b ) { - vec3_t d1; - - // make a perpendicular vector to the edge and the surface - VectorSubtract( a, b, d1 ); - CrossProduct( plane->normal, d1, boundary->normal ); - VectorNormalize( boundary->normal, boundary->normal ); - boundary->dist = DotProduct( a, boundary->normal ); -} - -/* -===================== -VS_GenerateFacetFor3Points -===================== -*/ -qboolean VS_GenerateFacetFor3Points( dsurface_t *dsurf, shaderInfo_t *si, lFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) { - // - vec3_t dir; - int i; - - // if we can't generate a valid plane for the points, ignore the facet - if ( !VS_PlaneFromPoints( &f->plane, a->xyz, b->xyz, c->xyz ) ) { - f->numpoints = 0; - return qfalse; - } - - f->num = numfacets++; - - VectorAdd( a->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[0] ); - VectorAdd( b->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[1] ); - VectorAdd( c->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[2] ); - - f->lightmapCoords[0][0] = a->lightmap[0]; - f->lightmapCoords[0][1] = a->lightmap[1]; - f->lightmapCoords[1][0] = b->lightmap[0]; - f->lightmapCoords[1][1] = b->lightmap[1]; - f->lightmapCoords[2][0] = c->lightmap[0]; - f->lightmapCoords[2][1] = c->lightmap[1]; - - VS_GenerateBoundaryForPoints( &f->boundaries[0], &f->plane, f->points[0], f->points[1] ); - VS_GenerateBoundaryForPoints( &f->boundaries[1], &f->plane, f->points[1], f->points[2] ); - VS_GenerateBoundaryForPoints( &f->boundaries[2], &f->plane, f->points[2], f->points[0] ); - - for (i = 0; i < 3; i++) - { - VectorSubtract(f->points[(i+1)%3], f->points[i], dir); - if (VectorLength(dir) < 0.1) - return qfalse; - } - - VS_TextureMatrixFromPoints( f, a, b, c ); - VS_LightmapMatrixFromPoints( dsurf, si, f, a, b, c ); - - f->numpoints = 3; - - return qtrue; -} - -/* -===================== -VS_GenerateFacetFor4Points - -Attempts to use four points as a planar quad -===================== -*/ -#define PLANAR_EPSILON 0.1 -qboolean VS_GenerateFacetFor4Points( dsurface_t *dsurf, shaderInfo_t *si, lFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c, drawVert_t *d ) { - float dist; - vec3_t dir; - int i; - plane_t plane; - - // if we can't generate a valid plane for the points, ignore the facet - if ( !VS_PlaneFromPoints( &f->plane, a->xyz, b->xyz, c->xyz ) ) { - f->numpoints = 0; - return qfalse; - } - - // if the fourth point is also on the plane, we can make a quad facet - dist = DotProduct( d->xyz, f->plane.normal ) - f->plane.dist; - if ( fabs( dist ) > PLANAR_EPSILON ) { - f->numpoints = 0; - return qfalse; - } - - VectorAdd( a->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[0] ); - VectorAdd( b->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[1] ); - VectorAdd( c->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[2] ); - VectorAdd( d->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[3] ); - - for (i = 1; i < 4; i++) - { - if ( !VS_PlaneFromPoints( &plane, f->points[i], f->points[(i+1) % 4], f->points[(i+2) % 4]) ) { - f->numpoints = 0; - return qfalse; - } - - if (!Plane_Equal(&f->plane, &plane, qfalse)) { - f->numpoints = 0; - return qfalse; - } - } - - f->lightmapCoords[0][0] = a->lightmap[0]; - f->lightmapCoords[0][1] = a->lightmap[1]; - f->lightmapCoords[1][0] = b->lightmap[0]; - f->lightmapCoords[1][1] = b->lightmap[1]; - f->lightmapCoords[2][0] = c->lightmap[0]; - f->lightmapCoords[2][1] = c->lightmap[1]; - f->lightmapCoords[3][0] = d->lightmap[0]; - f->lightmapCoords[3][1] = d->lightmap[1]; - - VS_GenerateBoundaryForPoints( &f->boundaries[0], &f->plane, f->points[0], f->points[1] ); - VS_GenerateBoundaryForPoints( &f->boundaries[1], &f->plane, f->points[1], f->points[2] ); - VS_GenerateBoundaryForPoints( &f->boundaries[2], &f->plane, f->points[2], f->points[3] ); - VS_GenerateBoundaryForPoints( &f->boundaries[3], &f->plane, f->points[3], f->points[0] ); - - for (i = 0; i < 4; i++) - { - VectorSubtract(f->points[(i+1)%4], f->points[i], dir); - if (VectorLength(dir) < 0.1) - return qfalse; - } - - VS_TextureMatrixFromPoints( f, a, b, c ); - VS_LightmapMatrixFromPoints( dsurf, si, f, a, b, c ); - - f->num = numfacets++; - f->numpoints = 4; - - return qtrue; -} - -/* -=============== -VS_SphereFromBounds -=============== -*/ -void VS_SphereFromBounds( vec3_t mins, vec3_t maxs, vec3_t origin, float *radius ) { - vec3_t temp; - - VectorAdd( mins, maxs, origin ); - VectorScale( origin, 0.5, origin ); - VectorSubtract( maxs, origin, temp ); - *radius = VectorLength( temp ); -} - -/* -==================== -VS_FacetsForTriangleSurface -==================== -*/ -void VS_FacetsForTriangleSurface( dsurface_t *dsurf, shaderInfo_t *si, lsurfaceTest_t *test ) { - int i; - drawVert_t *v1, *v2, *v3, *v4; - int count; - int i1, i2, i3, i4, i5, i6; - - test->patch = qfalse; - if (dsurf->surfaceType == MST_TRIANGLE_SOUP) - test->trisoup = qtrue; - else - test->trisoup = qfalse; - test->numFacets = dsurf->numIndexes / 3; - test->facets = malloc( sizeof( test->facets[0] ) * test->numFacets ); - test->shader = si; - - count = 0; - for ( i = 0 ; i < test->numFacets ; i++ ) { - i1 = drawIndexes[ dsurf->firstIndex + i*3 ]; - i2 = drawIndexes[ dsurf->firstIndex + i*3 + 1 ]; - i3 = drawIndexes[ dsurf->firstIndex + i*3 + 2 ]; - - v1 = &drawVerts[ dsurf->firstVert + i1 ]; - v2 = &drawVerts[ dsurf->firstVert + i2 ]; - v3 = &drawVerts[ dsurf->firstVert + i3 ]; - - // try and make a quad out of two triangles - if ( i != test->numFacets - 1 ) { - i4 = drawIndexes[ dsurf->firstIndex + i*3 + 3 ]; - i5 = drawIndexes[ dsurf->firstIndex + i*3 + 4 ]; - i6 = drawIndexes[ dsurf->firstIndex + i*3 + 5 ]; - if ( i4 == i3 && i5 == i2 ) { - v4 = &drawVerts[ dsurf->firstVert + i6 ]; - if ( VS_GenerateFacetFor4Points( dsurf, si, &test->facets[count], v1, v2, v4, v3 ) ) { - count++; - i++; // skip next tri - continue; - } - } - } - - if (VS_GenerateFacetFor3Points( dsurf, si, &test->facets[count], v1, v2, v3 )) { - count++; - } - } - - // we may have turned some pairs into quads - test->numFacets = count; -} - -/* -==================== -VS_FacetsForPatch -==================== -*/ -void VS_FacetsForPatch( dsurface_t *dsurf, int surfaceNum, shaderInfo_t *si, lsurfaceTest_t *test ) { - int i, j, x, y; - drawVert_t *v1, *v2, *v3, *v4; - int count, ssize; - mesh_t mesh; - mesh_t *subdivided, *detailmesh, *newmesh; - int widthtable[LIGHTMAP_SIZE], heighttable[LIGHTMAP_SIZE]; - - mesh.width = dsurf->patchWidth; - mesh.height = dsurf->patchHeight; - mesh.verts = &drawVerts[ dsurf->firstVert ]; - - newmesh = SubdivideMesh( mesh, 8, 999 ); - PutMeshOnCurve( *newmesh ); - MakeMeshNormals( *newmesh ); - - subdivided = RemoveLinearMeshColumnsRows( newmesh ); - FreeMesh(newmesh); - - // DebugNet_RemoveAllPolys(); - // DebugNet_DrawMesh(subdivided); - - ssize = samplesize; - if (si->lightmapSampleSize) - ssize = si->lightmapSampleSize; - - if ( dsurf->lightmapNum >= 0 ) { - - detailmesh = SubdivideMeshQuads( subdivided, ssize, LIGHTMAP_SIZE, widthtable, heighttable); - test->detailMesh = detailmesh; - - // DebugNet_RemoveAllPolys(); - // DebugNet_DrawMesh(detailmesh); - - if ( detailmesh->width != dsurf->lightmapWidth || detailmesh->height != dsurf->lightmapHeight ) { - Error( "Mesh lightmap miscount"); - } - } - else { - test->detailMesh = NULL; - memset(widthtable, 0, sizeof(widthtable)); - memset(heighttable, 0, sizeof(heighttable)); - } - - test->patch = qtrue; - test->trisoup = qfalse; - test->numFacets = ( subdivided->width - 1 ) * ( subdivided->height - 1 ) * 2; - test->facets = malloc( sizeof( test->facets[0] ) * test->numFacets ); - test->shader = si; - - count = 0; - x = 0; - for ( i = 0 ; i < subdivided->width - 1 ; i++ ) { - y = 0; - for ( j = 0 ; j < subdivided->height - 1 ; j++ ) { - - v1 = subdivided->verts + j * subdivided->width + i; - v2 = v1 + 1; - v3 = v1 + subdivided->width + 1; - v4 = v1 + subdivided->width; - - if ( VS_GenerateFacetFor4Points( dsurf, si, &test->facets[count], v1, v4, v3, v2 ) ) { - test->facets[count].x = x; - test->facets[count].y = y; - test->facets[count].width = widthtable[i]; - test->facets[count].height = heighttable[j]; - count++; - } else { - if (VS_GenerateFacetFor3Points( dsurf, si, &test->facets[count], v1, v4, v3 )) { - test->facets[count].x = x; - test->facets[count].y = y; - test->facets[count].width = widthtable[i]; - test->facets[count].height = heighttable[j]; - count++; - } - if (VS_GenerateFacetFor3Points( dsurf, si, &test->facets[count], v1, v3, v2 )) { - test->facets[count].x = x; - test->facets[count].y = y; - test->facets[count].width = widthtable[i]; - test->facets[count].height = heighttable[j]; - count++; - } - } - y += heighttable[j]; - } - x += widthtable[i]; - } - test->numFacets = count; - - FreeMesh(subdivided); -} - -/* -===================== -VS_InitSurfacesForTesting -===================== -*/ -void VS_InitSurfacesForTesting( void ) { - - int i, j, k; - dsurface_t *dsurf; - lsurfaceTest_t *test; - shaderInfo_t *si; - lFacet_t *facet; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - // don't light the entity surfaces with vsound - if ( entitySurface[i] ) - continue; - // - dsurf = &drawSurfaces[ i ]; - if ( !dsurf->numIndexes && !dsurf->patchWidth ) { - continue; - } - - si = ShaderInfoForShader( dshaders[ dsurf->shaderNum].shader ); - // if the surface is translucent and does not cast an alpha shadow - if ( (si->contents & CONTENTS_TRANSLUCENT) && !(si->surfaceFlags & SURF_ALPHASHADOW) ) { - // if the surface has no lightmap - if ( dsurf->lightmapNum < 0 ) - continue; - } - - test = malloc( sizeof( *test ) ); - memset(test, 0, sizeof( *test )); - test->mutex = MutexAlloc(); - test->numvolumes = 0; - if (si->forceTraceLight) - test->always_tracelight = qtrue; - else if (si->forceVLight) - test->always_vsound = qtrue; - lsurfaceTest[i] = test; - - if ( dsurf->surfaceType == MST_TRIANGLE_SOUP || dsurf->surfaceType == MST_PLANAR ) { - VS_FacetsForTriangleSurface( dsurf, si, test ); - } else if ( dsurf->surfaceType == MST_PATCH ) { - VS_FacetsForPatch( dsurf, i, si, test ); - } - if (numfacets >= MAX_FACETS) - Error("numfacets >= MAX_FACETS (%d)", MAX_FACETS); - - ClearBounds( test->mins, test->maxs ); - for (j = 0; j < test->numFacets; j++) - { - facet = &test->facets[j]; - for ( k = 0 ; k < facet->numpoints; k++) { - AddPointToBounds( facet->points[k], test->mins, test->maxs ); - } - } - VS_SphereFromBounds( test->mins, test->maxs, test->origin, &test->radius ); - } - _printf("%6d facets\n", numfacets); - _printf("linking surfaces...\n"); - VS_LinkSurfaces(); -} - -/* -============= -VS_ChopWinding -============= -*/ -int VS_ChopWinding (winding_t *in, plane_t *split, float epsilon) -{ - vec_t dists[128]; - int sides[128]; - int counts[3]; - vec_t dot; - int i, j; - vec_t *p1, *p2; - vec3_t mid; - winding_t out; - winding_t *neww; - - counts[0] = counts[1] = counts[2] = 0; - - // determine sides for each point - for (i=0 ; i<in->numpoints ; i++) - { - dot = DotProduct (in->points[i], split->normal); - dot -= split->dist; - dists[i] = dot; - if (dot > epsilon) - sides[i] = SIDE_FRONT; - else if (dot < -epsilon) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - - if (!counts[SIDE_BACK]) - { - if (!counts[SIDE_FRONT]) - return SIDE_ON; - else - return SIDE_FRONT; - } - - if (!counts[SIDE_FRONT]) - { - return SIDE_BACK; - } - - sides[i] = sides[0]; - dists[i] = dists[0]; - - neww = &out; - - neww->numpoints = 0; - - for (i=0 ; i<in->numpoints ; i++) - { - p1 = in->points[i]; - - if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VS_ChopWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; // can't chop -- fall back to original - } - - if (sides[i] == SIDE_ON) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VS_ChopWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; // can't chop -- fall back to original - } - - // generate a split point - p2 = in->points[(i+1)%in->numpoints]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (split->normal[j] == 1) - mid[j] = split->dist; - else if (split->normal[j] == -1) - mid[j] = -split->dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, neww->points[neww->numpoints]); - neww->numpoints++; - } - memcpy(in, &out, sizeof(winding_t)); - - return SIDE_CROSS; -} - -/* -============= -VS_ChopWindingWithBrush - - returns all winding fragments outside the brush -============= -*/ -int VS_ChopWindingWithBrush(winding_t *w, dbrush_t *brush, winding_t *outwindings, int maxout) -{ - int i, res, numout; - winding_t front, back; - plane_t plane; - - numout = 0; - memcpy(front.points, w->points, w->numpoints * sizeof(vec3_t)); - front.numpoints = w->numpoints; - for (i = 0; i < brush->numSides; i++) - { - VectorCopy(dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].normal, plane.normal); - VectorInverse(plane.normal); - plane.dist = -dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].dist; - res = VS_SplitWinding(&front, &back, &plane, 0.1); - if (res == SIDE_BACK || res == SIDE_ON) - { - memcpy(outwindings[0].points, w->points, w->numpoints * sizeof(vec3_t)); - outwindings[0].numpoints = w->numpoints; - return 1; //did not intersect - } - if (res != SIDE_FRONT) - { - if (numout >= maxout) - { - _printf("WARNING: VS_ChopWindingWithBrush: more than %d windings\n", maxout); - return 0; - } - memcpy(outwindings[numout].points, back.points, back.numpoints * sizeof(vec3_t)); - outwindings[numout].numpoints = back.numpoints; - numout++; - } - } - return numout; -} - -/* -============= -VS_WindingAreaOutsideBrushes -============= -*/ -float VS_WindingAreaOutsideBrushes(winding_t *w, int *brushnums, int numbrushes) -{ - int i, j, numwindings[2], n; - winding_t windingsbuf[2][64]; - dbrush_t *brush; - float area; - - memcpy(windingsbuf[0][0].points, w->points, w->numpoints * sizeof(vec3_t)); - windingsbuf[0][0].numpoints = w->numpoints; - numwindings[0] = 1; - for (i = 0; i < numbrushes; i++) - { - brush = &dbrushes[brushnums[i]]; - if (!(dshaders[brush->shaderNum].contentFlags & ( - CONTENTS_LAVA - | CONTENTS_SLIME - | CONTENTS_WATER - | CONTENTS_FOG - | CONTENTS_AREAPORTAL - | CONTENTS_PLAYERCLIP - | CONTENTS_MONSTERCLIP - | CONTENTS_CLUSTERPORTAL - | CONTENTS_DONOTENTER - | CONTENTS_BODY - | CONTENTS_CORPSE - | CONTENTS_TRANSLUCENT - | CONTENTS_TRIGGER - | CONTENTS_NODROP) ) && - (dshaders[brush->shaderNum].contentFlags & CONTENTS_SOLID) ) - { - numwindings[!(i & 1)] = 0; - for (j = 0; j < numwindings[i&1]; j++) - { - n = VS_ChopWindingWithBrush(&windingsbuf[i&1][j], brush, - &windingsbuf[!(i&1)][numwindings[!(i&1)]], - 64 - numwindings[!(i&1)]); - numwindings[!(i&1)] += n; - } - if (!numwindings[!(i&1)]) - return 0; - } - else - { - for (j = 0; j < numwindings[i&1]; j++) - { - windingsbuf[!(i&1)][j] = windingsbuf[i&1][j]; - } - numwindings[!(i&1)] = numwindings[i&1]; - } - } - area = 0; - for (j = 0; j < numwindings[i&1]; j++) - { - area += WindingArea(&windingsbuf[i&1][j]); - } - return area; -} - -/* -============= -VS_R_WindingAreaOutsideSolid -============= -*/ -float VS_R_WindingAreaOutsideSolid(winding_t *w, vec3_t normal, int nodenum) -{ - int leafnum, res; - float area; - dnode_t *node; - dleaf_t *leaf; - dplane_t *plane; - winding_t back; - plane_t split; - - area = 0; - while(nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - - VectorCopy(plane->normal, split.normal); - split.dist = plane->dist; - res = VS_SplitWinding (w, &back, &split, 0.1); - - if (res == SIDE_FRONT) - { - nodenum = node->children[0]; - } - else if (res == SIDE_BACK) - { - nodenum = node->children[1]; - } - else if (res == SIDE_ON) - { - if (DotProduct(normal, plane->normal) > 0) - nodenum = node->children[0]; - else - nodenum = node->children[1]; - } - else - { - area += VS_R_WindingAreaOutsideSolid(&back, normal, node->children[1]); - nodenum = node->children[0]; - } - } - leafnum = -nodenum - 1; - leaf = &dleafs[leafnum]; - if (leaf->cluster != -1) - { - area += VS_WindingAreaOutsideBrushes(w, &dleafbrushes[leaf->firstLeafBrush], leaf->numLeafBrushes); - } - return area; -} - -/* -============= -VS_WindingAreaOutsideSolid -============= -*/ -float VS_WindingAreaOutsideSolid(winding_t *w, vec3_t normal) -{ - return VS_R_WindingAreaOutsideSolid(w, normal, 0); -} - -/* -============= -VS_ChopWindingWithFacet -============= -*/ -float VS_ChopWindingWithFacet(winding_t *w, lFacet_t *facet) -{ - int i; - - for (i = 0; i < facet->numpoints; i++) - { - if (VS_ChopWinding(w, &facet->boundaries[i], 0) == SIDE_BACK) - return 0; - } - if (nostitching) - return WindingArea(w); - else - return VS_WindingAreaOutsideSolid(w, facet->plane.normal); -} - -/* -============= -VS_CalcVisibleLightmapPixelArea - -nice brute force ;) -============= -*/ -void VS_CalcVisibleLightmapPixelArea(void) -{ - int i, j, x, y, k; - dsurface_t *ds; - lsurfaceTest_t *test; - mesh_t *mesh; - winding_t w, tmpw; - float area; - - _printf("calculating visible lightmap pixel area...\n"); - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - ds = &drawSurfaces[ i ]; - - if ( ds->lightmapNum < 0 ) - continue; - - for (y = 0; y < ds->lightmapHeight; y++) - { - for (x = 0; x < ds->lightmapWidth; x++) - { - if (ds->surfaceType == MST_PATCH) - { - if (y == ds->lightmapHeight-1) - continue; - if (x == ds->lightmapWidth-1) - continue; - mesh = lsurfaceTest[i]->detailMesh; - VectorCopy( mesh->verts[y*mesh->width+x].xyz, w.points[0]); - VectorCopy( mesh->verts[(y+1)*mesh->width+x].xyz, w.points[1]); - VectorCopy( mesh->verts[(y+1)*mesh->width+x+1].xyz, w.points[2]); - VectorCopy( mesh->verts[y*mesh->width+x+1].xyz, w.points[3]); - w.numpoints = 4; - if (nostitching) - area = WindingArea(&w); - else - area = VS_WindingAreaOutsideSolid(&w, mesh->verts[y*mesh->width+x].normal); - } - else - { - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[0], w.points[0]); - VectorMA(w.points[0], (float) y - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[1], w.points[0]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[0], w.points[3]); - VectorMA(w.points[3], (float) y - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[1], w.points[3]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[0], w.points[2]); - VectorMA(w.points[2], (float) y - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[1], w.points[2]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[0], w.points[1]); - VectorMA(w.points[1], (float) y - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[1], w.points[1]); - w.numpoints = 4; - area = 0; - for (j = 0; j < test->numFacets; j++) - { - memcpy(&tmpw, &w, sizeof(winding_t)); - area += VS_ChopWindingWithFacet(&tmpw, &test->facets[j]); - } - } - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - lightmappixelarea[k] = area; - } - } - } -} - -/* -============= -VS_FindAdjacentSurface -============= -*/ -int VS_FindAdjacentSurface(int surfaceNum, int facetNum, vec3_t p1, vec3_t p2, int *sNum, int *fNum, int *point) -{ - int i, j, k; - lsurfaceTest_t *test; - lFacet_t *facet; - dsurface_t *ds; - float *fp1, *fp2; - vec3_t dir; - plane_t *facetplane; - // winding_t w; - - facetplane = &lsurfaceTest[surfaceNum]->facets[facetNum].plane; - // DebugNet_RemoveAllPolys(); - // memcpy(w.points, lsurfaceTest[surfaceNum]->facets[facetNum].points, - // lsurfaceTest[surfaceNum]->facets[facetNum].numpoints * sizeof(vec3_t)); - // w.numpoints = lsurfaceTest[surfaceNum]->facets[facetNum].numpoints; - // DebugNet_DrawWinding(&w, 2); - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - if (i == surfaceNum) - continue; - test = lsurfaceTest[ i ]; - if (!test) - continue; - if (test->trisoup)// || test->patch) - continue; - ds = &drawSurfaces[i]; - if ( ds->lightmapNum < 0 ) - continue; - //if this surface is not even near the edge - VectorSubtract(p1, test->origin, dir); - if (fabs(dir[0]) > test->radius || - fabs(dir[1]) > test->radius || - fabs(dir[1]) > test->radius) - { - VectorSubtract(p2, test->origin, dir); - if (fabs(dir[0]) > test->radius || - fabs(dir[1]) > test->radius || - fabs(dir[1]) > test->radius) - { - continue; - } - } - // - for (j = 0; j < test->numFacets; j++) - { - facet = &test->facets[j]; - // - //if (!Plane_Equal(&facet->plane, facetplane, qfalse)) - if (DotProduct(facet->plane.normal, facetplane->normal) < 0.9) - { - if (!test->trisoup && !test->patch) - break; - continue; - } - // - for (k = 0; k < facet->numpoints; k++) - { - fp1 = facet->points[k]; - if (fabs(p2[0] - fp1[0]) < 0.1 && - fabs(p2[1] - fp1[1]) < 0.1 && - fabs(p2[2] - fp1[2]) < 0.1) - { - fp2 = facet->points[(k+1) % facet->numpoints]; - if (fabs(p1[0] - fp2[0]) < 0.1 && - fabs(p1[1] - fp2[1]) < 0.1 && - fabs(p1[2] - fp2[2]) < 0.1) - { - // memcpy(w.points, facet->points, facet->numpoints * sizeof(vec3_t)); - // w.numpoints = facet->numpoints; - // DebugNet_DrawWinding(&w, 1); - *sNum = i; - *fNum = j; - *point = k; - return qtrue; - } - } - /* - else if (fabs(p1[0] - fp1[0]) < 0.1 && - fabs(p1[1] - fp1[1]) < 0.1 && - fabs(p1[2] - fp1[2]) < 0.1) - { - fp2 = facet->points[(k+1) % facet->numpoints]; - if (fabs(p2[0] - fp2[0]) < 0.1 && - fabs(p2[1] - fp2[1]) < 0.1 && - fabs(p2[2] - fp2[2]) < 0.1) - { - // memcpy(w.points, facet->points, facet->numpoints * sizeof(vec3_t)); - // w.numpoints = facet->numpoints; - // DebugNet_DrawWinding(&w, 1); - *sNum = i; - *fNum = j; - *point = k; - return qtrue; - } - } - //*/ - } - } - } - return qfalse; -} - -/* -============= -VS_SmoothenLightmapEdges - -this code is used to smoothen lightmaps across surface edges -============= -*/ -void VS_SmoothenLightmapEdges(void) -{ - int i, j, k, coords1[2][2]; - float coords2[2][2]; - int x1, y1, xinc1, yinc1, k1, k2; - float x2, y2, xinc2, yinc2, length; - int surfaceNum, facetNum, point; - lsurfaceTest_t *test; - lFacet_t *facet1, *facet2; - dsurface_t *ds1, *ds2; - float *p[2], s, t, *color1, *color2; - vec3_t dir, cross; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - if (test->trisoup)// || test->patch) - continue; - ds1 = &drawSurfaces[i]; - if ( ds1->lightmapNum < 0 ) - continue; - for (j = 0; j < test->numFacets; j++) - { - facet1 = &test->facets[j]; - // - for (k = 0; k < facet1->numpoints; k++) - { - p[0] = facet1->points[k]; - p[1] = facet1->points[(k+1)%facet1->numpoints]; - // - coords1[0][0] = facet1->lightmapCoords[k][0] * LIGHTMAP_SIZE; - coords1[0][1] = facet1->lightmapCoords[k][1] * LIGHTMAP_SIZE; - coords1[1][0] = facet1->lightmapCoords[(k+1)%facet1->numpoints][0] * LIGHTMAP_SIZE; - coords1[1][1] = facet1->lightmapCoords[(k+1)%facet1->numpoints][1] * LIGHTMAP_SIZE; - if (coords1[0][0] >= LIGHTMAP_SIZE) - coords1[0][0] = LIGHTMAP_SIZE-1; - if (coords1[0][1] >= LIGHTMAP_SIZE) - coords1[0][1] = LIGHTMAP_SIZE-1; - if (coords1[1][0] >= LIGHTMAP_SIZE) - coords1[1][0] = LIGHTMAP_SIZE-1; - if (coords1[1][1] >= LIGHTMAP_SIZE) - coords1[1][1] = LIGHTMAP_SIZE-1; - // try one row or column further because on flat faces the lightmap can - // extend beyond the edge - VectorSubtract(p[1], p[0], dir); - VectorNormalize(dir, dir); - CrossProduct(dir, facet1->plane.normal, cross); - // - if (coords1[0][0] - coords1[1][0] == 0) - { - s = DotProduct( cross, facet1->lightmapMatrix[0] ); - coords1[0][0] += s < 0 ? 1 : -1; - coords1[1][0] += s < 0 ? 1 : -1; - if (coords1[0][0] < ds1->lightmapX || coords1[0][0] >= ds1->lightmapX + ds1->lightmapWidth) - { - coords1[0][0] += s < 0 ? -1 : 1; - coords1[1][0] += s < 0 ? -1 : 1; - } - length = fabs(coords1[1][1] - coords1[0][1]); - } - else if (coords1[0][1] - coords1[1][1] == 0) - { - t = DotProduct( cross, facet1->lightmapMatrix[1] ); - coords1[0][1] += t < 0 ? 1 : -1; - coords1[1][1] += t < 0 ? 1 : -1; - if (coords1[0][1] < ds1->lightmapY || coords1[0][1] >= ds1->lightmapY + ds1->lightmapHeight) - { - coords1[0][1] += t < 0 ? -1 : 1; - coords1[1][1] += t < 0 ? -1 : 1; - } - length = fabs(coords1[1][0] - coords1[0][0]); - } - else - { - //the edge is not parallell to one of the lightmap axis - continue; - } - // - x1 = coords1[0][0]; - y1 = coords1[0][1]; - xinc1 = coords1[1][0] - coords1[0][0]; - if (xinc1 < 0) xinc1 = -1; - if (xinc1 > 0) xinc1 = 1; - yinc1 = coords1[1][1] - coords1[0][1]; - if (yinc1 < 0) yinc1 = -1; - if (yinc1 > 0) yinc1 = 1; - // the edge should be parallell to one of the lightmap axis - if (xinc1 != 0 && yinc1 != 0) - continue; - // - if (!VS_FindAdjacentSurface(i, j, p[0], p[1], &surfaceNum, &facetNum, &point)) - continue; - // - ds2 = &drawSurfaces[surfaceNum]; - facet2 = &lsurfaceTest[surfaceNum]->facets[facetNum]; - coords2[0][0] = facet2->lightmapCoords[(point+1)%facet2->numpoints][0] * LIGHTMAP_SIZE; - coords2[0][1] = facet2->lightmapCoords[(point+1)%facet2->numpoints][1] * LIGHTMAP_SIZE; - coords2[1][0] = facet2->lightmapCoords[point][0] * LIGHTMAP_SIZE; - coords2[1][1] = facet2->lightmapCoords[point][1] * LIGHTMAP_SIZE; - if (coords2[0][0] >= LIGHTMAP_SIZE) - coords2[0][0] = LIGHTMAP_SIZE-1; - if (coords2[0][1] >= LIGHTMAP_SIZE) - coords2[0][1] = LIGHTMAP_SIZE-1; - if (coords2[1][0] >= LIGHTMAP_SIZE) - coords2[1][0] = LIGHTMAP_SIZE-1; - if (coords2[1][1] >= LIGHTMAP_SIZE) - coords2[1][1] = LIGHTMAP_SIZE-1; - // - x2 = coords2[0][0]; - y2 = coords2[0][1]; - xinc2 = coords2[1][0] - coords2[0][0]; - if (length) - xinc2 = xinc2 / length; - yinc2 = coords2[1][1] - coords2[0][1]; - if (length) - yinc2 = yinc2 / length; - // the edge should be parallell to one of the lightmap axis - if ((int) xinc2 != 0 && (int) yinc2 != 0) - continue; - // - while(1) - { - k1 = ( ds1->lightmapNum * LIGHTMAP_HEIGHT + y1) * LIGHTMAP_WIDTH + x1; - k2 = ( ds2->lightmapNum * LIGHTMAP_HEIGHT + ((int) y2)) * LIGHTMAP_WIDTH + ((int) x2); - color1 = lightFloats + k1*3; - color2 = lightFloats + k2*3; - if (lightmappixelarea[k1] < 0.01) - { - color1[0] = color2[0]; - color1[1] = color2[1]; - color1[2] = color2[2]; - } - else - { - color1[0] = (float) color2[0] * 0.7 + (float) color1[0] * 0.3; - color1[1] = (float) color2[1] * 0.7 + (float) color1[1] * 0.3; - color1[2] = (float) color2[2] * 0.7 + (float) color1[2] * 0.3; - } - // - if (x1 == coords1[1][0] && - y1 == coords1[1][1]) - break; - x1 += xinc1; - y1 += yinc1; - x2 += xinc2; - y2 += yinc2; - if (x2 < ds2->lightmapX) - x2 = ds2->lightmapX; - if (x2 >= ds2->lightmapX + ds2->lightmapWidth) - x2 = ds2->lightmapX + ds2->lightmapWidth-1; - if (y2 < ds2->lightmapY) - y2 = ds2->lightmapY; - if (y2 >= ds2->lightmapY + ds2->lightmapHeight) - y2 = ds2->lightmapY + ds2->lightmapHeight-1; - } - } - } - } -} - -/* -============= -VS_FixLightmapEdges -============= -*/ -void VS_FixLightmapEdges(void) -{ - int i, j, x, y, k, foundvalue, height, width, index; - int pos, top, bottom; - dsurface_t *ds; - lsurfaceTest_t *test; - float color[3]; - float *ptr; - byte filled[(LIGHTMAP_SIZE+1) * (LIGHTMAP_SIZE+1) / 8]; - float lightmap_edge_epsilon; - - lightmap_edge_epsilon = 0.1 * samplesize; - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - ds = &drawSurfaces[ i ]; - - if ( ds->lightmapNum < 0 ) - continue; - if (ds->surfaceType == MST_PATCH) - { - height = ds->lightmapHeight - 1; - width = ds->lightmapWidth - 1; - } - else - { - height = ds->lightmapHeight; - width = ds->lightmapWidth; - } - memset(filled, 0, sizeof(filled)); -// printf("\n"); - for (x = 0; x < width; x++) - { - for (y = 0; y < height; y++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (lightmappixelarea[k] > lightmap_edge_epsilon) - { - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - filled[index >> 3] |= 1 << (index & 7); -// printf("*"); - } -// else -// printf("_"); - } -// printf("\n"); - } - for (y = 0; y < height; y++) - { - pos = -2; - for (x = 0; x < width; x++) - { - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (pos == -2) - { - if (filled[index >> 3] & (1 << (index & 7))) - pos = -1; - } - else if (pos == -1) - { - if (!(filled[index >> 3] & (1 << (index & 7)))) - pos = x - 1; - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - bottom = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + pos; - top = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - for (j = 0; j < (x - pos + 1) / 2; j++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + pos + j + 1; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + pos + j + 1; - filled[index >> 3] |= 1 << (index & 7); - (lightFloats + k*3)[0] = (lightFloats + top*3)[0]; - (lightFloats + k*3)[1] = (lightFloats + top*3)[1]; - (lightFloats + k*3)[2] = (lightFloats + top*3)[2]; - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x - j - 1; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x - j - 1; - filled[index >> 3] |= 1 << (index & 7); - (lightFloats + k*3)[0] = (lightFloats + bottom*3)[0]; - (lightFloats + k*3)[1] = (lightFloats + bottom*3)[1]; - (lightFloats + k*3)[2] = (lightFloats + bottom*3)[2]; - } - pos = -1; - } - } - } - } - for (x = 0; x < width; x++) - { - pos = -2; - for (y = 0; y < height; y++) - { - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (pos == -2) - { - if (filled[index >> 3] & (1 << (index & 7))) - pos = -1; - } - else if (pos == -1) - { - if (!(filled[index >> 3] & (1 << (index & 7)))) - pos = y - 1; - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - bottom = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + pos) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - top = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - for (j = 0; j < (y - pos + 1) / 2; j++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + pos + j + 1) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + pos + j + 1) * LIGHTMAP_WIDTH + ds->lightmapX + x; - filled[index >> 3] |= 1 << (index & 7); - (lightFloats + k*3)[0] = (lightFloats + top*3)[0]; - (lightFloats + k*3)[1] = (lightFloats + top*3)[1]; - (lightFloats + k*3)[2] = (lightFloats + top*3)[2]; - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y - j - 1) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + y - j - 1) * LIGHTMAP_WIDTH + ds->lightmapX + x; - filled[index >> 3] |= 1 << (index & 7); - (lightFloats + k*3)[0] = (lightFloats + bottom*3)[0]; - (lightFloats + k*3)[1] = (lightFloats + bottom*3)[1]; - (lightFloats + k*3)[2] = (lightFloats + bottom*3)[2]; - } - pos = -1; - } - } - } - } - for (y = 0; y < height; y++) - { - foundvalue = qfalse; - for (x = 0; x < width; x++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (foundvalue) - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - } - else - { - ptr = lightFloats + k*3; - ptr[0] = color[0]; - ptr[1] = color[1]; - ptr[2] = color[2]; - filled[index >> 3] |= 1 << (index & 7); - } - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - foundvalue = qtrue; - } - } - } - foundvalue = qfalse; - for (x = width-1; x >= 0; x--) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (foundvalue) - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - } - else - { - ptr = lightFloats + k*3; - ptr[0] = color[0]; - ptr[1] = color[1]; - ptr[2] = color[2]; - filled[index >> 3] |= 1 << (index & 7); - } - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - foundvalue = qtrue; - } - } - } - } - for (x = 0; x < width; x++) - { - foundvalue = qfalse; - for (y = 0; y < height; y++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (foundvalue) - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - } - else - { - ptr = lightFloats + k*3; - ptr[0] = color[0]; - ptr[1] = color[1]; - ptr[2] = color[2]; - filled[index >> 3] |= 1 << (index & 7); - } - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - foundvalue = qtrue; - } - } - } - foundvalue = qfalse; - for (y = height-1; y >= 0; y--) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (foundvalue) - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - } - else - { - ptr = lightFloats + k*3; - ptr[0] = color[0]; - ptr[1] = color[1]; - ptr[2] = color[2]; - filled[index >> 3] |= 1 << (index & 7); - } - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - foundvalue = qtrue; - } - } - } - } - if (ds->surfaceType == MST_PATCH) - { - x = ds->lightmapWidth-1; - for (y = 0; y < ds->lightmapHeight; y++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = (lightFloats + (k-1)*3)[0]; - ptr[1] = (lightFloats + (k-1)*3)[1]; - ptr[2] = (lightFloats + (k-1)*3)[2]; - } - y = ds->lightmapHeight-1; - for (x = 0; x < ds->lightmapWidth; x++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[0]; - ptr[1] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[1]; - ptr[2] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[2]; - } - } - /* - //colored debug edges - if (ds->surfaceType == MST_PATCH) - { - x = ds->lightmapWidth-1; - for (y = 0; y < ds->lightmapHeight; y++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = 255; - ptr[1] = 0; - ptr[2] = 0; - } - y = ds->lightmapHeight-1; - for (x = 0; x < ds->lightmapWidth; x++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = 0; - ptr[1] = 255; - ptr[2] = 0; - } - } - //*/ - } - // - VS_SmoothenLightmapEdges(); -} - -/* -============= -VS_ShiftPatchLightmaps -============= -*/ -void VS_ShiftPatchLightmaps(void) -{ - int i, j, x, y, k; - drawVert_t *verts; - dsurface_t *ds; - lsurfaceTest_t *test; - float *ptr; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - ds = &drawSurfaces[ i ]; - - if ( ds->lightmapNum < 0 ) - continue; - if (ds->surfaceType != MST_PATCH) - continue; - for (x = ds->lightmapWidth; x > 0; x--) - { - for (y = 0; y <= ds->lightmapHeight; y++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = (lightFloats + (k-1)*3)[0]; - ptr[1] = (lightFloats + (k-1)*3)[1]; - ptr[2] = (lightFloats + (k-1)*3)[2]; - } - } - for (y = ds->lightmapHeight; y > 0; y--) - { - for (x = 0; x <= ds->lightmapWidth; x++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[0]; - ptr[1] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[1]; - ptr[2] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[2]; - } - } - verts = &drawVerts[ ds->firstVert ]; - for ( j = 0 ; j < ds->patchHeight * ds->patchWidth; j++ ) - { - verts[j].lightmap[0] += 0.5 / LIGHTMAP_WIDTH; - verts[j].lightmap[1] += 0.5 / LIGHTMAP_HEIGHT; - } - ds->lightmapHeight++; - ds->lightmapWidth++; - } -} - -/* -============= -VS_StoreLightmap -============= -*/ -void VS_StoreLightmap(void) -{ - int i, x, y, k; - dsurface_t *ds; - lsurfaceTest_t *test; - float *src; - byte *dst; - - _printf("storing lightmaps...\n"); - //fix lightmap edges before storing them - VS_FixLightmapEdges(); - // -#ifdef LIGHTMAP_PATCHSHIFT - VS_ShiftPatchLightmaps(); -#endif - // - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - ds = &drawSurfaces[ i ]; - - if ( ds->lightmapNum < 0 ) - continue; - - for (y = 0; y < ds->lightmapHeight; y++) - { - for (x = 0; x < ds->lightmapWidth; x++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - VectorAdd((lightFloats + k*3), lightAmbientColor, (lightFloats + k*3)); - src = &lightFloats[k*3]; - dst = lightBytes + k*3; - ColorToBytes(src, dst); - } - } - } -} - -/* -============= -PointInLeafnum -============= -*/ -static int PointInLeafnum(vec3_t point) -{ - int nodenum; - vec_t dist; - dnode_t *node; - dplane_t *plane; - - nodenum = 0; - while (nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - dist = DotProduct (point, plane->normal) - plane->dist; - if (dist > 0) - nodenum = node->children[0]; - else - nodenum = node->children[1]; - } - - return -nodenum - 1; -} - -/* -============= -VS_PointInLeafnum_r -============= -*/ -int VS_PointInLeafnum_r(vec3_t point, int nodenum) -{ - int leafnum; - vec_t dist; - dnode_t *node; - dplane_t *plane; - - while (nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - dist = DotProduct (point, plane->normal) - plane->dist; - if (dist > 0.1) - { - nodenum = node->children[0]; - } - else if (dist < -0.1) - { - nodenum = node->children[1]; - } - else - { - leafnum = VS_PointInLeafnum_r(point, node->children[0]); - if (dleafs[leafnum].cluster != -1) - return leafnum; - nodenum = node->children[1]; - } - } - - leafnum = -nodenum - 1; - return leafnum; -} - -/* -============= -VS_PointInLeafnum -============= -*/ -int VS_PointInLeafnum(vec3_t point) -{ - return VS_PointInLeafnum_r(point, 0); -} - -/* -============= -VS_LightLeafnum -============= -*/ -int VS_LightLeafnum(vec3_t point) -{ - /* - int leafnum; - dleaf_t *leaf; - float x, y, z; - vec3_t test; - - leafnum = VS_PointInLeafnum(point); - leaf = &dleafs[leafnum]; - if (leaf->cluster != -1) - return leafnum; - for (z = 1; z >= -1; z -= 1) - { - for (x = 1; x >= -1; x -= 1) - { - for (y = 1; y >= -1; y -= 1) - { - VectorCopy(point, test); - test[0] += x; - test[1] += y; - test[2] += z; - leafnum = VS_PointInLeafnum(test); - leaf = &dleafs[leafnum]; - if (leaf->cluster != -1) - { - VectorCopy(test, point); - return leafnum; - } - } - } - } - return leafnum; - */ - return VS_PointInLeafnum(point); -} - -//#define LIGHTPOLYS - -#ifdef LIGHTPOLYS - -winding_t *lightwindings[MAX_MAP_DRAW_SURFS]; -int numlightwindings; - -/* -============= -VS_DrawLightWindings -============= -*/ -void VS_DrawLightWindings(void) -{ - int i; - for (i = 0; i < numlightwindings; i++) - { -#ifdef DEBUGNET - DebugNet_DrawWinding(lightwindings[i], 1); -#endif - } -} - -/* -============= -VS_LightSurfaceWithVolume -============= -*/ -void VS_LightSurfaceWithVolume(int surfaceNum, int facetNum, vsound_t *light, lightvolume_t *volume) -{ - winding_t *w; - lsurfaceTest_t *test; - lFacet_t *facet; - int i; - - test = lsurfaceTest[ surfaceNum ]; - facet = &test->facets[ facetNum ]; - - // - w = (winding_t *) malloc(sizeof(winding_t)); - memcpy(w->points, facet->points, sizeof(vec3_t) * facet->numpoints); - w->numpoints = facet->numpoints; - - for (i = 0; i < volume->numplanes; i++) - { - //if totally on the back - if (VS_ChopWinding(w, &volume->planes[i], 0.01) == SIDE_BACK) - return; - } - lightwindings[numlightwindings] = w; - numlightwindings++; - if (numlightwindings >= MAX_MAP_DRAW_SURFS) - Error("MAX_LIGHTWINDINGS"); -} - -#else - -/* -============= -VS_LightSurfaceWithVolume -============= -*/ -/* -int VS_PointInsideLightVolume(vec3_t point, lightvolume_t *volume) -{ - int i; - float d; - - for (i = 0; i < volume->numplanes; i++) - { - d = DotProduct(volume->planes[i].normal, point) - volume->planes[i].dist; - if (d < 0) return qfalse; - } - return qtrue; -} - -void VS_LightSurfaceWithVolume( int surfaceNum, int facetNum, vsound_t *light, lightvolume_t *volume ) -{ - dsurface_t *ds; - int i, j, k; - int numPositions; - vec3_t base, normal, color; - int sampleWidth, sampleHeight; - vec3_t lightmapOrigin, lightmapVecs[2], dir; - unsigned char *ptr; - float add, dist, angle; - mesh_t * mesh; - - ds = &drawSurfaces[surfaceNum]; - - // vertex-lit triangle model - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) { - return; - } - - if ( ds->lightmapNum < 0 ) { - return; // doesn't need lighting - } - - if ( ds->surfaceType == MST_PATCH ) { - mesh = lsurfaceTest[surfaceNum]->detailMesh; - } else { - VectorCopy( ds->lightmapVecs[2], normal ); - - VectorCopy( ds->lightmapOrigin, lightmapOrigin ); - VectorCopy( ds->lightmapVecs[0], lightmapVecs[0] ); - VectorCopy( ds->lightmapVecs[1], lightmapVecs[1] ); - } - - sampleWidth = ds->lightmapWidth; - sampleHeight = ds->lightmapHeight; - - //calculate lightmap - for ( i = 0 ; i < sampleWidth; i++ ) { - for ( j = 0 ; j < sampleHeight; j++ ) { - - if ( ds->patchWidth ) { - numPositions = 9; - VectorCopy( mesh->verts[j*mesh->width+i].normal, normal ); - // VectorNormalize( normal, normal ); - // push off of the curve a bit - VectorMA( mesh->verts[j*mesh->width+i].xyz, 1, normal, base ); - -// MakeNormalVectors( normal, lightmapVecs[0], lightmapVecs[1] ); - } else { - numPositions = 9; - for ( k = 0 ; k < 3 ; k++ ) { - base[k] = lightmapOrigin[k] + normal[k] - + ((float) i) * lightmapVecs[0][k] - + ((float) j) * lightmapVecs[1][k]; - } - } - VectorAdd( base, surfaceOrigin[ surfaceNum ], base ); - - VectorSubtract(base, light->origin, dir); - dist = VectorNormalize(dir, dir); - if ( dist < 16 ) { - dist = 16; - } - angle = 1;//DotProduct( normal, dir ); //1; - if (angle > 1) - angle = 1; - if ( light->atten_disttype == LDAT_LINEAR ) { - add = angle * light->photons * lightLinearScale - dist; - if ( add < 0 ) { - add = 0; - } - } else { - add = light->photons / ( dist * dist ) * angle; - } - if (add <= 1.0) - continue; - - if (VS_PointInsideLightVolume(base, volume)) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + j) - * LIGHTMAP_WIDTH + ds->lightmapX + i; - ptr = lightBytes + k*3; - color[0] = (float) ptr[0] + add * light->color[0]; - color[1] = (float) ptr[1] + add * light->color[1]; - color[2] = (float) ptr[2] + add * light->color[2]; - ColorToBytes(color, ptr); - } - } - } -} -*/ - -/* -============= -VS_GetFilter - -FIXME: don't use a lightmap pixel origin but use the four corner points - to map part of a translucent surface onto the lightmap pixel -============= -*/ -void VS_GetFilter(vsound_t *light, lightvolume_t *volume, vec3_t lmp, vec3_t filter) -{ - lFacet_t *facet; - lsurfaceTest_t *test; - float d, d1, d2, frac, s, t, ns; - int i, j, is, it, b; - int x, y, u, v, numsamples, radius, color[4], largest; - byte *image; - vec3_t point, origin, total; - - VectorSet(filter, 1, 1, 1); - - if (noalphashading) - return; - - if (volume->numtransFacets <= 0) - return; - - if (light->type == LIGHT_SURFACEDIRECTED) - { - // project the light map pixel origin onto the area light source plane - d = DotProduct(lmp, light->normal) - DotProduct(light->normal, light->w.points[0]); - VectorMA(lmp, -d, light->normal, origin); - } - else - { - VectorCopy(light->origin, origin); - } - for (i = 0; i < volume->numtransFacets; i++) - { - test = lsurfaceTest[ volume->transSurfaces[i] ]; - facet = &test->facets[ volume->transFacets[i] ]; - // if this surface does not cast an alpha shadow - if ( !(test->shader->surfaceFlags & SURF_ALPHASHADOW) ) - continue; - // if there are no texture pixel available - if ( !test->shader->pixels ) { - continue; - } - // - d1 = DotProduct( origin, facet->plane.normal) - facet->plane.dist; - d2 = DotProduct( lmp, facet->plane.normal ) - facet->plane.dist; - // this should never happen because the light volume went through the facet - if ( ( d1 < 0 ) == ( d2 < 0 ) ) { - continue; - } - // calculate the crossing point - frac = d1 / ( d1 - d2 ); - - for ( j = 0 ; j < 3 ; j++ ) { - point[j] = origin[j] + frac * ( lmp[j] - origin[j] ); - } - - s = DotProduct( point, facet->textureMatrix[0] ) + facet->textureMatrix[0][3]; - t = DotProduct( point, facet->textureMatrix[1] ) + facet->textureMatrix[1][3]; - if (s < 0) - s = 0; - if (t < 0) - t = 0; - - s = s - floor( s ); - t = t - floor( t ); - - is = s * test->shader->width; - it = t * test->shader->height; - - //if old style alpha shading - if (nocolorshading) { - image = test->shader->pixels + 4 * ( it * test->shader->width + is ); - - // alpha filter - b = image[3]; - - // alpha test makes this a binary option - b = b < 128 ? 0 : 255; - - filter[0] = filter[0] * (255-b) / 255; - filter[1] = filter[1] * (255-b) / 255; - filter[2] = filter[2] * (255-b) / 255; - } - else { - VectorClear(total); - numsamples = 0; - radius = 2; - for ( u = -radius; u <= radius; u++ ) - { - x = is + u; - if ( x < 0 || x >= test->shader->width) - continue; - for ( v = -radius; v <= radius; v++ ) - { - y = it + v; - if ( y < 0 || y >= test->shader->height) - continue; - - image = test->shader->pixels + 4 * ( y * test->shader->width + x ); - color[0] = image[0]; - color[1] = image[1]; - color[2] = image[2]; - largest = 0; - for (j = 0; j < 3; j++) - if (image[j] > largest) - largest = image[j]; - if (largest <= 0 || image[3] == 0) { - color[0] = 255; - color[1] = 255; - color[2] = 255; - largest = 255; - } - total[0] += ((float) color[0]/largest) * (255-image[3]) / 255.0; - total[1] += ((float) color[1]/largest) * (255-image[3]) / 255.0; - total[2] += ((float) color[2]/largest) * (255-image[3]) / 255.0; - numsamples++; - } - } - ns = numsamples; - // - filter[0] *= total[0] / ns; - filter[1] *= total[1] / ns; - filter[2] *= total[2] / ns; - } - } -} - -/* -============= -VS_LightSurfaceWithVolume -============= -*/ -void VS_LightSurfaceWithVolume( int surfaceNum, int facetNum, vsound_t *light, lightvolume_t *volume ) -{ - int i; - dsurface_t *ds; - lFacet_t *facet; - lsurfaceTest_t *test; - winding_t w; - vec3_t base, dir, delta, normal, filter, origin; - int min_x[LIGHTMAP_SIZE+2], max_x[LIGHTMAP_SIZE+2]; - int min_y, max_y, k, x, y, n; - float *color, distscale; - float d, add, angle, dist, area, insidearea, coords[MAX_POINTS_ON_WINDING+1][2]; - mesh_t *mesh; - byte polygonedges[(LIGHTMAP_SIZE+1) * (LIGHTMAP_SIZE+1) / 8]; - - - ds = &drawSurfaces[surfaceNum]; - - // vertex-lit triangle model - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) { - return; - } - - if ( ds->lightmapNum < 0 ) { - return; // doesn't need lighting - } - - test = lsurfaceTest[ surfaceNum ]; - facet = &test->facets[ facetNum ]; - - if (defaulttracelight && !test->always_vsound) - return; - if (test->always_tracelight) - return; - - memcpy(w.points, facet->points, sizeof(vec3_t) * facet->numpoints); - w.numpoints = facet->numpoints; - - for (i = 0; i < volume->numplanes; i++) - { - //if totally on the back - if (VS_ChopWinding(&w, &volume->planes[i], 0.01) == SIDE_BACK) - return; - } - - // only one thread at a time may write to the lightmap of this surface - MutexLock(test->mutex); - - test->numvolumes++; - - if (ds->surfaceType == MST_PATCH) - { - // FIXME: reduce size and don't mark all as edge - min_y = ds->lightmapY + facet->y; - max_y = ds->lightmapY + facet->y + facet->height - 1; - for (y = min_y; y <= max_y; y++) - { - min_x[y] = ds->lightmapX + facet->x; - max_x[y] = ds->lightmapX + facet->x + facet->width - 1; - for (x = min_x[y]; x <= max_x[y]; x++) - { - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - } - } - } - else - { - for (i = 0; i < w.numpoints; i++) - { - float s, t; - - if (i >= MAX_POINTS_ON_WINDING) - _printf("coords overflow\n"); - if (ds->surfaceType != MST_PATCH) - { - VectorSubtract(w.points[i], facet->mins, delta); - s = DotProduct( delta, facet->lightmapMatrix[0] ) + ds->lightmapX + 0.5; - t = DotProduct( delta, facet->lightmapMatrix[1] ) + ds->lightmapY + 0.5; - if (s >= LIGHTMAP_SIZE) - s = LIGHTMAP_SIZE - 0.5; - if (s < 0) - s = 0; - if (t >= LIGHTMAP_SIZE) - t = LIGHTMAP_SIZE - 0.5; - if (t < 0) - t = 0; - coords[i][0] = s; - coords[i][1] = t; - } - else - { - s = DotProduct( w.points[i], facet->lightmapMatrix[0] ) + facet->lightmapMatrix[0][3]; - t = DotProduct( w.points[i], facet->lightmapMatrix[1] ) + facet->lightmapMatrix[1][3]; - - s = s - floor( s ); - t = t - floor( t ); - - coords[i][0] = ds->lightmapX + s * LIGHTMAP_SIZE;// + 0.5; - coords[i][1] = ds->lightmapY + t * LIGHTMAP_SIZE;// + 0.5; - - if (coords[i][0] >= LIGHTMAP_SIZE) - coords[i][0] -= LIGHTMAP_SIZE; - if (coords[i][1] >= LIGHTMAP_SIZE) - coords[i][1] -= LIGHTMAP_SIZE; - if (coords[i][0] < ds->lightmapX) - coords[i][0] = ds->lightmapX; - if (coords[i][1] < ds->lightmapY) - coords[i][1] = ds->lightmapY; - } - x = coords[i][0]; - y = coords[i][1]; - if (x < ds->lightmapX || x >= LIGHTMAP_SIZE) - _printf("VS_LightSurfaceWithVolume: x outside lightmap\n"); - if (y < ds->lightmapY || y >= LIGHTMAP_SIZE) - _printf("VS_LightSurfaceWithVolume: y outside lightmap\n"); - } - coords[i][0] = coords[0][0]; - coords[i][1] = coords[0][1]; - - // - min_y = LIGHTMAP_SIZE; - max_y = 0; - for (i = 0; i < LIGHTMAP_SIZE; i++) - { - min_x[i] = LIGHTMAP_SIZE; - max_x[i] = 0; - } - memset(polygonedges, 0, sizeof(polygonedges)); - // scan convert the polygon onto the lightmap - // for each edge it marks *every* lightmap pixel the edge goes through - // so no brasenham and no scan conversion used for texture mapping but - // more something like ray casting - // this is necesary because we need all lightmap pixels totally or partly - // inside the light volume. these lightmap pixels are only lit for the part - // that they are inside the light volume. - for (i = 0; i < w.numpoints; i++) - { - float xf, yf, dx, dy, xstep, ystep, xfrac, yfrac; - int xinc, yinc; - - xf = coords[i][0]; - yf = coords[i][1]; - dx = coords[i+1][0] - xf; - dy = coords[i+1][1] - yf; - // - x = (int) xf; - y = (int) yf; - // - if (y < min_y) - min_y = y; - if (y > max_y) - max_y = y; - // - if (fabs(dx) > fabs(dy)) - { - if (dx > 0) - { - // y fraction at integer x below fractional x - yfrac = yf + (floor(xf) - xf) * dy / dx; - xinc = 1; - } - else if (dx < 0) - { - // y fraction at integer x above fractional x - yfrac = yf + (floor(xf) + 1 - xf) * dy / dx; - xinc = -1; - } - else - { - yfrac = yf; - xinc = 0; - } - // step in y direction per 1 unit in x direction - if (dx) - ystep = dy / fabs(dx); - else - ystep = 0; - while(1) - { - if (x < ds->lightmapX || x >= LIGHTMAP_SIZE) - _printf("VS_LightSurfaceWithVolume: x outside lightmap\n"); - if (y < ds->lightmapY || y >= LIGHTMAP_SIZE) - _printf("VS_LightSurfaceWithVolume: y outside lightmap\n"); - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - if (x == (int) coords[i+1][0]) - break; - yfrac += ystep; - if (dy > 0) - { - if (yfrac > (float) y + 1) - { - y += 1; - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - } - } - else - { - if (yfrac < (float) y) - { - y -= 1; - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - } - } - x += xinc; - } - } - else - { - if (dy > 0) - { - //x fraction at integer y below fractional y - xfrac = xf + (floor(yf) - yf) * dx / dy; - yinc = 1; - } - else if (dy < 0) - { - //x fraction at integer y above fractional y - xfrac = xf + (floor(yf) + 1 - yf) * dx / dy; - yinc = -1; - } - else - { - xfrac = xf; - yinc = 0; - } - // step in x direction per 1 unit in y direction - if (dy) - xstep = dx / fabs(dy); - else - xstep = 0; - while(1) - { - if (x < ds->lightmapX || x >= LIGHTMAP_SIZE) - _printf("VS_LightSurfaceWithVolume: x outside lightmap\n"); - if (y < ds->lightmapY || y >= LIGHTMAP_SIZE) - _printf("VS_LightSurfaceWithVolume: y outside lightmap\n"); - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - if (y == (int) coords[i+1][1]) - break; - xfrac += xstep; - if (dx > 0) - { - if (xfrac > (float) x + 1) - { - x += 1; - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - } - } - else - { - if (xfrac < (float) x) - { - x -= 1; - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - } - } - y += yinc; - } - } - } - } - // map light onto the lightmap - for (y = min_y; y <= max_y; y++) - { - for (x = min_x[y]; x <= max_x[y]; x++) - { - if (ds->surfaceType == MST_PATCH) - { - mesh = test->detailMesh; - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, base); - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].normal, normal); - //VectorCopy(facet->plane.normal, normal); - } - else - { - VectorMA(ds->lightmapOrigin, (float) x - ds->lightmapX, ds->lightmapVecs[0], base); - VectorMA(base, (float) y - ds->lightmapY, ds->lightmapVecs[1], base); - VectorCopy(facet->plane.normal, normal); - } - if (light->type == LIGHT_POINTSPOT) - { - float distByNormal; - vec3_t pointAtDist; - float radiusAtDist; - float sampleRadius; - vec3_t distToSample; - float coneScale; - - VectorSubtract( light->origin, base, dir ); - - distByNormal = -DotProduct( dir, light->normal ); - if ( distByNormal < 0 ) { - continue; - } - VectorMA( light->origin, distByNormal, light->normal, pointAtDist ); - radiusAtDist = light->radiusByDist * distByNormal; - - VectorSubtract( base, pointAtDist, distToSample ); - sampleRadius = VectorLength( distToSample ); - - if ( sampleRadius >= radiusAtDist ) { - continue; // outside the cone - } - if ( sampleRadius <= radiusAtDist - 32 ) { - coneScale = 1.0; // fully inside - } else { - coneScale = ( radiusAtDist - sampleRadius ) / 32.0; - } - - dist = VectorNormalize( dir, dir ); - // clamp the distance to prevent super hot spots - if ( dist < 16 ) { - dist = 16; - } - angle = DotProduct( normal, dir ); - if (angle > 1) - angle = 1; - if (angle > 0) { - if ( light->atten_angletype == LAAT_QUADRATIC ) { - angle = 1 - angle; - angle *= angle; - angle = 1 - angle; - } - else if ( light->atten_angletype == LAAT_DOUBLEQUADRATIC ) { - angle = 1 - angle; - angle *= angle * angle; - angle = 1 - angle; - } - } - if (light->atten_anglescale > 0) { - angle /= light->atten_anglescale; - if (angle > 1) - angle = 1; - } - if (light->atten_distscale > 0) { - distscale = light->atten_distscale; - } - else { - distscale = 1; - } - // - if ( light->atten_disttype == LDAT_NOSCALE ) { - add = angle * coneScale; - } - else if ( light->atten_disttype == LDAT_LINEAR ) { - add = angle * light->photons * lightLinearScale * coneScale - dist * distscale; - if ( add < 0 ) { - add = 0; - } - } - else { - add = light->photons / ( dist * dist * distscale) * angle * coneScale; - } - if (add <= 1.0) - continue; - } - else if (light->type == LIGHT_POINTFAKESURFACE) - { - // calculate the contribution - add = PointToPolygonFormFactor( base, normal, &light->w ); - if ( add <= 0 ) { - if ( light->twosided ) { - add = -add; - } else { - continue; - } - } - } - else if (light->type == LIGHT_SURFACEDIRECTED) - { - //VectorCopy(light->normal, dir); - //VectorInverse(dir); - // project the light map pixel origin onto the area light source plane - d = DotProduct(base, light->normal) - DotProduct(light->normal, light->w.points[0]); - VectorMA(base, -d, light->normal, origin); - VectorSubtract(origin, base, dir); - dist = VectorNormalize(dir, dir); - if ( dist < 16 ) { - dist = 16; - } - // - angle = DotProduct( normal, dir ); - if (angle > 1) - angle = 1; - if (angle > 0) { - if ( light->atten_angletype == LAAT_QUADRATIC ) { - angle = 1 - angle; - angle *= angle; - angle = 1 - angle; - } - else if ( light->atten_angletype == LAAT_DOUBLEQUADRATIC ) { - angle = 1 - angle; - angle *= angle * angle; - angle = 1 - angle; - } - } - if (light->atten_anglescale > 0) { - angle /= light->atten_anglescale; - if (angle > 1) - angle = 1; - } - if (light->atten_distscale > 0) { - distscale = light->atten_distscale; - } - else { - distscale = 1; - } - if ( light->atten_disttype == LDAT_NOSCALE ) { - add = angle; - } - else if ( light->atten_disttype == LDAT_LINEAR ) { - add = angle * light->photons * lightLinearScale - dist * distscale; - if ( add < 0 ) { - add = 0; - } - } else { //default quadratic - add = light->photons / ( dist * dist * distscale) * angle; - } - if (add <= 0) - continue; - } - else //normal radial point light - { - VectorSubtract(light->origin, base, dir); - dist = VectorNormalize(dir, dir); - if ( dist < 16 ) { - dist = 16; - } - angle = DotProduct( normal, dir ); - if (angle > 1) - angle = 1; - if (angle > 0) { - if ( light->atten_angletype == LAAT_QUADRATIC ) { - angle = 1 - angle; - angle *= angle; - angle = 1 - angle; - } - else if ( light->atten_angletype == LAAT_DOUBLEQUADRATIC ) { - angle = 1 - angle; - angle *= angle * angle; - angle = 1 - angle; - } - } - if (light->atten_anglescale > 0) { - angle /= light->atten_anglescale; - if (angle > 1) - angle = 1; - } - if (light->atten_distscale > 0) { - distscale = light->atten_distscale; - } - else { - distscale = 1; - } - if ( light->atten_disttype == LDAT_NOSCALE ) { - add = angle; - } - else if ( light->atten_disttype == LDAT_LINEAR ) { - add = angle * light->photons * lightLinearScale - dist * distscale; - if ( add < 0 ) { - add = 0; - } - } else { - add = light->photons / ( dist * dist * distscale) * angle; - } - if (add <= 1.0) - continue; - } - // - k = (ds->lightmapNum * LIGHTMAP_HEIGHT + y) * LIGHTMAP_WIDTH + x; - //if on one of the edges - n = y * LIGHTMAP_SIZE + x; - if ((polygonedges[n >> 3] & (1 << (n & 7)) )) - { - // multiply 'add' by the relative area being lit of the total visible lightmap pixel area - // - // first create a winding for the lightmap pixel - if (ds->surfaceType == MST_PATCH) - { - mesh = test->detailMesh; - if (y-ds->lightmapY >= mesh->height-1) - _printf("y outside mesh\n"); - if (x-ds->lightmapX >= mesh->width-1) - _printf("x outside mesh\n"); - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[0]); - VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[1]); - VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[2]); - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[3]); - w.numpoints = 4; - } - else - { - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT - ds->lightmapX, ds->lightmapVecs[0], w.points[0]); - VectorMA(w.points[0], (float) y - LIGHTMAP_PIXELSHIFT - ds->lightmapY, ds->lightmapVecs[1], w.points[0]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT - ds->lightmapX, ds->lightmapVecs[0], w.points[1]); - VectorMA(w.points[1], (float) y - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapY, ds->lightmapVecs[1], w.points[1]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapX, ds->lightmapVecs[0], w.points[2]); - VectorMA(w.points[2], (float) y - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapY, ds->lightmapVecs[1], w.points[2]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapX, ds->lightmapVecs[0], w.points[3]); - VectorMA(w.points[3], (float) y - LIGHTMAP_PIXELSHIFT - ds->lightmapY, ds->lightmapVecs[1], w.points[3]); - w.numpoints = 4; - } - // - // take the visible area of the lightmap pixel into account - // - //area = WindingArea(&w); - area = lightmappixelarea[k]; - if (area <= 0) - continue; - // chop the lightmap pixel winding with the light volume - for (i = 0; i < volume->numplanes; i++) - { - //if totally on the back - if (VS_ChopWinding(&w, &volume->planes[i], 0) == SIDE_BACK) - break; - } - // if the lightmap pixel is partly inside the light volume - if (i >= volume->numplanes) - { - insidearea = WindingArea(&w); - if (insidearea <= 0) - i = 0; - add = add * insidearea / area; - } - else - { - //DebugNet_DrawWinding(&w, 2); - continue; // this shouldn't happen - } - } - // get the light filter from all the translucent surfaces the light volume went through - VS_GetFilter(light, volume, base, filter); - // - color = &lightFloats[k*3]; - color[0] += add * light->color[0] * filter[0]; - color[1] += add * light->color[1] * filter[1]; - color[2] += add * light->color[2] * filter[2]; - } - } - - MutexUnlock(test->mutex); -} - -#endif - -/* -============= -VS_SplitLightVolume -============= -*/ -int VS_SplitLightVolume(lightvolume_t *volume, lightvolume_t *back, plane_t *split, float epsilon) -{ - lightvolume_t f, b; - vec_t dists[128]; - int sides[128]; - int counts[3]; - vec_t dot; - int i, j; - vec_t *p1, *p2; - vec3_t mid; - - counts[0] = counts[1] = counts[2] = 0; - - // determine sides for each point - for (i = 0; i < volume->numplanes; i++) - { - dot = DotProduct (volume->points[i], split->normal); - dot -= split->dist; - dists[i] = dot; - if (dot > epsilon) - sides[i] = SIDE_FRONT; - else if (dot < -epsilon) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - - if (!counts[1]) - return 0; // completely on front side - - if (!counts[0]) - return 1; // completely on back side - - sides[i] = sides[0]; - dists[i] = dists[0]; - - f.numplanes = 0; - b.numplanes = 0; - - for (i = 0; i < volume->numplanes; i++) - { - p1 = volume->points[i]; - - if (f.numplanes >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VS_SplitLightVolume -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return 0; // can't chop -- fall back to original - } - if (b.numplanes >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VS_SplitLightVolume -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return 0; // can't chop -- fall back to original - } - - if (sides[i] == SIDE_ON) - { - VectorCopy(p1, f.points[f.numplanes]); - VectorCopy(p1, b.points[b.numplanes]); - if (sides[i+1] == SIDE_BACK) - { - f.planes[f.numplanes] = *split; - b.planes[b.numplanes] = volume->planes[i]; - } - else if (sides[i+1] == SIDE_FRONT) - { - f.planes[f.numplanes] = volume->planes[i]; - b.planes[b.numplanes] = *split; - VectorInverse(b.planes[b.numplanes].normal); - b.planes[b.numplanes].dist = -b.planes[b.numplanes].dist; - } - else //this shouldn't happen - { - f.planes[f.numplanes] = *split; - b.planes[b.numplanes] = *split; - VectorInverse(b.planes[b.numplanes].normal); - b.planes[b.numplanes].dist = -b.planes[b.numplanes].dist; - } - f.numplanes++; - b.numplanes++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, f.points[f.numplanes]); - f.planes[f.numplanes] = volume->planes[i]; - f.numplanes++; - } - if (sides[i] == SIDE_BACK) - { - VectorCopy (p1, b.points[b.numplanes]); - b.planes[b.numplanes] = volume->planes[i]; - b.numplanes++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - if (f.numplanes >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VS_SplitLightVolume -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return 0; // can't chop -- fall back to original - } - if (b.numplanes >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VS_SplitLightVolume -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return 0; // can't chop -- fall back to original - } - - // generate a split point - p2 = volume->points[(i+1)%volume->numplanes]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (split->normal[j] == 1) - mid[j] = split->dist; - else if (split->normal[j] == -1) - mid[j] = -split->dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, f.points[f.numplanes]); - VectorCopy(mid, b.points[b.numplanes]); - if (sides[i+1] == SIDE_BACK) - { - f.planes[f.numplanes] = *split; - b.planes[b.numplanes] = volume->planes[i]; - } - else - { - f.planes[f.numplanes] = volume->planes[i]; - b.planes[b.numplanes] = *split; - VectorInverse(b.planes[b.numplanes].normal); - b.planes[b.numplanes].dist = -b.planes[b.numplanes].dist; - } - f.numplanes++; - b.numplanes++; - } - memcpy(volume->points, f.points, sizeof(vec3_t) * f.numplanes); - memcpy(volume->planes, f.planes, sizeof(plane_t) * f.numplanes); - volume->numplanes = f.numplanes; - memcpy(back->points, b.points, sizeof(vec3_t) * b.numplanes); - memcpy(back->planes, b.planes, sizeof(plane_t) * b.numplanes); - back->numplanes = b.numplanes; - - return 2; -} - -/* -============= -VS_PlaneForEdgeToWinding -============= -*/ -void VS_PlaneForEdgeToWinding(vec3_t p1, vec3_t p2, winding_t *w, int windingonfront, plane_t *plane) -{ - int i, j; - float length, d; - vec3_t v1, v2; - - VectorSubtract(p2, p1, v1); - for (i = 0; i < w->numpoints; i++) - { - VectorSubtract (w->points[i], p1, v2); - - plane->normal[0] = v1[1]*v2[2] - v1[2]*v2[1]; - plane->normal[1] = v1[2]*v2[0] - v1[0]*v2[2]; - plane->normal[2] = v1[0]*v2[1] - v1[1]*v2[0]; - - // if points don't make a valid plane, skip it - length = plane->normal[0] * plane->normal[0] - + plane->normal[1] * plane->normal[1] - + plane->normal[2] * plane->normal[2]; - - if (length < ON_EPSILON) - continue; - - length = 1/sqrt(length); - - plane->normal[0] *= length; - plane->normal[1] *= length; - plane->normal[2] *= length; - - plane->dist = DotProduct (w->points[i], plane->normal); - // - for (j = 0; j < w->numpoints; j++) - { - if (j == i) - continue; - d = DotProduct(w->points[j], plane->normal) - plane->dist; - if (windingonfront) - { - if (d < -ON_EPSILON) - break; - } - else - { - if (d > ON_EPSILON) - break; - } - } - if (j >= w->numpoints) - return; - } -} - -/* -============= -VS_R_CastLightAtSurface -============= -*/ -void VS_R_FloodLight(vsound_t *light, lightvolume_t *volume, int cluster, int firstportal); - -void VS_R_CastLightAtSurface(vsound_t *light, lightvolume_t *volume) -{ - lsurfaceTest_t *test; - int i, n; - - // light the surface with this volume - VS_LightSurfaceWithVolume(volume->surfaceNum, volume->facetNum, light, volume); - // - test = lsurfaceTest[ volume->surfaceNum ]; - // if this is not a translucent surface - if ( !(test->shader->surfaceFlags & SURF_ALPHASHADOW) && !(test->shader->contents & CONTENTS_TRANSLUCENT)) - return; - // - if (volume->numtransFacets >= MAX_TRANSLUCENTFACETS) - Error("a light valume went through more than %d translucent facets", MAX_TRANSLUCENTFACETS); - //add this translucent surface to the list - volume->transSurfaces[volume->numtransFacets] = volume->surfaceNum; - volume->transFacets[volume->numtransFacets] = volume->facetNum; - volume->numtransFacets++; - //clear the tested facets except the translucent ones - memset(volume->facetTested, 0, sizeof(volume->facetTested)); - for (i = 0; i < volume->numtransFacets; i++) - { - test = lsurfaceTest[ volume->transSurfaces[i] ]; - n = test->facets[volume->transFacets[i]].num; - volume->facetTested[n >> 3] |= 1 << (n & 7); - } - memset(volume->clusterTested, 0, sizeof(volume->clusterTested)); - volume->endplane = volume->farplane; - volume->surfaceNum = -1; - volume->facetNum = 0; - VS_R_FloodLight(light, volume, volume->cluster, 0); - if (volume->surfaceNum >= 0) - { - VS_R_CastLightAtSurface(light, volume); - } -} - -/* -============= -VS_R_SplitLightVolume -============= -*/ -static int numvolumes = 0; - -int VS_R_SplitLightVolume(vsound_t *light, lightvolume_t *volume, plane_t *split, int cluster, int firstportal) -{ - lightvolume_t back; - int res; - - // - res = VS_SplitLightVolume(volume, &back, split, 0.1); - // if the volume was split - if (res == 2) - { - memcpy(back.clusterTested, volume->clusterTested, sizeof(back.clusterTested)); - memcpy(back.facetTested, volume->facetTested, sizeof(back.facetTested)); - back.num = numvolumes++; - back.endplane = volume->endplane; - back.surfaceNum = volume->surfaceNum; - back.facetNum = volume->facetNum; - back.type = volume->type; - back.cluster = volume->cluster; - back.farplane = volume->farplane; - if (volume->numtransFacets > 0) - { - memcpy(back.transFacets, volume->transFacets, sizeof(back.transFacets)); - memcpy(back.transSurfaces, volume->transSurfaces, sizeof(back.transSurfaces)); - } - back.numtransFacets = volume->numtransFacets; - // - // flood the volume at the back of the split plane - VS_R_FloodLight(light, &back, cluster, firstportal); - // if the back volume hit a surface - if (back.surfaceNum >= 0) - { - VS_R_CastLightAtSurface(light, &back); - } - } - return res; -} - -/* -============= -VS_R_FloodLight -============= -*/ -void VS_R_FloodLight(vsound_t *light, lightvolume_t *volume, int cluster, int firstportal) -{ - int i, j, k, res, surfaceNum, backfaceculled, testculled; - float d; - winding_t winding, tmpwinding; - lleaf_t *leaf; - lportal_t *p; - lsurfaceTest_t *test; - lFacet_t *facet; - vec3_t dir1, dir2; - plane_t plane; - - // DebugNet_RemoveAllPolys(); - // VS_DrawLightVolume(light, volume); - - // if the first portal is not zero then we've checked all occluders in this leaf already - if (firstportal == 0) - { - // check all potential occluders in this leaf - for (i = 0; i < leafs[cluster].numSurfaces; i++) - { - surfaceNum = clustersurfaces[leafs[cluster].firstSurface + i]; - // - test = lsurfaceTest[ surfaceNum ]; - if ( !test ) - continue; - // - testculled = qfalse; - // use surface as an occluder - for (j = 0; j < test->numFacets; j++) - { - // use each facet as an occluder - facet = &test->facets[j]; - // - // memcpy(winding.points, facet->points, sizeof(vec3_t) * facet->numpoints); - // winding.numpoints = facet->numpoints; - // DebugNet_DrawWinding(&winding, 5); - // - // if the facet was tested already - if ( volume->facetTested[facet->num >> 3] & (1 << (facet->num & 7)) ) - continue; - volume->facetTested[facet->num >> 3] |= 1 << (facet->num & 7); - // backface culling for planar surfaces - backfaceculled = qfalse; - if (!test->patch && !test->trisoup) - { - if (volume->type == VOLUME_NORMAL) - { - // facet backface culling - d = DotProduct(light->origin, facet->plane.normal) - facet->plane.dist; - if (d < 0) - { - // NOTE: this doesn't work too great because of sometimes very bad tesselation - // of surfaces that are supposed to be flat - // FIXME: to work around this problem we should make sure that all facets - // created from planar surfaces use the lightmapVecs normal vector - /* - if ( !test->shader->twoSided ) - { - // skip all other facets of this surface as well because they are in the same plane - for (k = 0; k < test->numFacets; k++) - { - facet = &test->facets[k]; - volume->facetTested[facet->num >> 3] |= 1 << (facet->num & 7); - } - }*/ - backfaceculled = qtrue; - } - } - else - { - // FIXME: if all light source winding points are at the back of the facet - // plane then backfaceculled = qtrue - } - } - else // backface culling per facet for patches and triangle soups - { - if (volume->type == VOLUME_NORMAL) - { - // facet backface culling - d = DotProduct(light->origin, facet->plane.normal) - facet->plane.dist; - if (d < 0) - backfaceculled = qtrue; - } - else - { - // FIXME: if all light source winding points are at the back of the facet - // plane then backfaceculled = qtrue - } - } - /* chopping does this already - // check if this facet is totally or partly in front of the volume end plane - for (k = 0; k < facet->numpoints; k++) - { - d = DotProduct(volume->endplane.normal, facet->points[k]) - volume->endplane.dist; - if (d > ON_EPSILON) - break; - } - // if this facet is outside the light volume - if (k >= facet->numpoints) - continue; - */ - // - if (backfaceculled) - { - // if the facet is not two sided - if ( !nobackfaceculling && !test->shader->twoSided ) - continue; - // flip the winding - for (k = 0; k < facet->numpoints; k++) - VectorCopy(facet->points[k], winding.points[facet->numpoints - k - 1]); - winding.numpoints = facet->numpoints; - } - else - { - memcpy(winding.points, facet->points, sizeof(vec3_t) * facet->numpoints); - winding.numpoints = facet->numpoints; - } - // - if (!testculled) - { - testculled = qtrue; - // fast check if the surface sphere is totally behind the volume end plane - d = DotProduct(volume->endplane.normal, test->origin) - volume->endplane.dist; - if (d < -test->radius) - { - for (k = 0; k < test->numFacets; k++) - { - facet = &test->facets[k]; - volume->facetTested[facet->num >> 3] |= 1 << (facet->num & 7); - } - break; - } - for (k = 0; k < volume->numplanes; k++) - { - d = DotProduct(volume->planes[k].normal, test->origin) - volume->planes[k].dist; - if (d < - test->radius) - { - for (k = 0; k < test->numFacets; k++) - { - facet = &test->facets[k]; - volume->facetTested[facet->num >> 3] |= 1 << (facet->num & 7); - } - break; - } - } - if (k < volume->numplanes) - break; - } - //NOTE: we have to chop the facet winding with the volume end plane because - // the faces in Q3 are not stitched together nicely - res = VS_ChopWinding(&winding, &volume->endplane, 0.01); - // if the facet is on or at the back of the volume end plane - if (res == SIDE_BACK || res == SIDE_ON) - continue; - // check if the facet winding is totally or partly inside the light volume - memcpy(&tmpwinding, &winding, sizeof(winding_t)); - for (k = 0; k < volume->numplanes; k++) - { - res = VS_ChopWinding(&tmpwinding, &volume->planes[k], 0.01); - if (res == SIDE_BACK || res == SIDE_ON) - break; - } - // if no part of the light volume is occluded by this facet - if (k < volume->numplanes) - continue; - // - for (k = 0; k < winding.numpoints; k++) - { - if (volume->type == VOLUME_DIRECTED) - { - VectorSubtract(winding.points[(k+1) % winding.numpoints], winding.points[k], dir1); - CrossProduct(light->normal, dir1, plane.normal); - VectorNormalize(plane.normal, plane.normal); - plane.dist = DotProduct(plane.normal, winding.points[k]); - } - else - { - VectorSubtract(winding.points[(k+1) % winding.numpoints], winding.points[k], dir1); - VectorSubtract(light->origin, winding.points[k], dir2); - CrossProduct(dir1, dir2, plane.normal); - VectorNormalize(plane.normal, plane.normal); - plane.dist = DotProduct(plane.normal, winding.points[k]); - } - res = VS_R_SplitLightVolume(light, volume, &plane, cluster, 0); - if (res == 1) - break; //the facet wasn't really inside the volume - } - if (k >= winding.numpoints) - { - volume->endplane = facet->plane; - if (backfaceculled) - { - VectorInverse(volume->endplane.normal); - volume->endplane.dist = -volume->endplane.dist; - } - volume->surfaceNum = surfaceNum; - volume->facetNum = j; - } - } - } - } - // we've tested all occluders in this cluster - volume->clusterTested[cluster >> 3] |= 1 << (cluster & 7); - // flood light through the portals of the current leaf - leaf = &leafs[cluster]; - for (i = firstportal; i < leaf->numportals; i++) - { - p = leaf->portals[i]; - // - // memcpy(&winding, p->winding, sizeof(winding_t)); - // DebugNet_DrawWinding(&winding, 5); - // if already flooded into the cluster this portal leads to - if ( volume->clusterTested[p->leaf >> 3] & (1 << (p->leaf & 7)) ) - continue; - // - if (volume->type == VOLUME_NORMAL) - { - // portal backface culling - d = DotProduct(light->origin, p->plane.normal) - p->plane.dist; - if (d > 0) // portal plane normal points into neighbour cluster - continue; - } - else - { - // FIXME: if all light source winding points are at the back of this portal - // plane then there's no need to flood through - } - // check if this portal is totally or partly in front of the volume end plane - // fast check with portal sphere - d = DotProduct(volume->endplane.normal, p->origin) - volume->endplane.dist; - if (d < -p->radius) - continue; - for (j = 0; j < p->winding->numpoints; j++) - { - d = DotProduct(volume->endplane.normal, p->winding->points[j]) - volume->endplane.dist; - if (d > -0.01) - break; - } - // if this portal is totally behind the light volume end plane - if (j >= p->winding->numpoints) - continue; - //distance from point light to portal - d = DotProduct(p->plane.normal, light->origin) - p->plane.dist; - // only check if a point light is Not *on* the portal - if (volume->type != VOLUME_NORMAL || fabs(d) > 0.1) - { - // check if the portal is partly or totally inside the light volume - memcpy(&winding, p->winding, sizeof(winding_t)); - for (j = 0; j < volume->numplanes; j++) - { - res = VS_ChopWinding(&winding, &volume->planes[j], 0.01); - if (res == SIDE_BACK || res == SIDE_ON) - break; - } - // if the light volume does not go through this portal at all - if (j < volume->numplanes) - continue; - } - // chop the light volume with the portal - for (k = 0; k < p->winding->numpoints; k++) - { - if (volume->type == VOLUME_DIRECTED) - { - VectorSubtract(p->winding->points[(k+1) % p->winding->numpoints], p->winding->points[k], dir1); - CrossProduct(light->normal, dir1, plane.normal); - VectorNormalize(plane.normal, plane.normal); - plane.dist = DotProduct(plane.normal, p->winding->points[k]); - } - else - { - VectorSubtract(p->winding->points[(k+1) % p->winding->numpoints], p->winding->points[k], dir1); - VectorSubtract(light->origin, p->winding->points[k], dir2); - CrossProduct(dir1, dir2, plane.normal); - VectorNormalize(plane.normal, plane.normal); - plane.dist = DotProduct(plane.normal, p->winding->points[k]); - } - res = VS_R_SplitLightVolume(light, volume, &plane, cluster, i+1); - if (res == 1) - break; //volume didn't really go through the portal - } - // if the light volume went through the portal - if (k >= p->winding->numpoints) - { - // flood through the portal - VS_R_FloodLight(light, volume, p->leaf, 0); - } - } -} - -/* -============= -VS_R_FloodAreaSpotLight -============= -*/ -void VS_FloodAreaSpotLight(vsound_t *light, winding_t *w, int leafnum) -{ -} - -/* -============= -VS_R_SubdivideAreaSpotLight -============= -*/ -void VS_R_SubdivideAreaSpotLight(vsound_t *light, int nodenum, winding_t *w) -{ - int leafnum, res; - dnode_t *node; - dplane_t *plane; - winding_t back; - plane_t split; - - while(nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - - VectorCopy(plane->normal, split.normal); - split.dist = plane->dist; - res = VS_SplitWinding (w, &back, &split, 0.1); - - if (res == SIDE_FRONT) - { - nodenum = node->children[0]; - } - else if (res == SIDE_BACK) - { - nodenum = node->children[1]; - } - else if (res == SIDE_ON) - { - memcpy(&back, w, sizeof(winding_t)); - VS_R_SubdivideAreaSpotLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - else - { - VS_R_SubdivideAreaSpotLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - } - leafnum = -nodenum - 1; - if (dleafs[leafnum].cluster != -1) - { - VS_FloodAreaSpotLight(light, w, leafnum); - } -} - -/* -============= -VS_R_FloodRadialAreaLight -============= -*/ -void VS_FloodRadialAreaLight(vsound_t *light, winding_t *w, int leafnum) -{ -} - -/* -============= -VS_R_SubdivideRadialAreaLight -============= -*/ -void VS_R_SubdivideRadialAreaLight(vsound_t *light, int nodenum, winding_t *w) -{ - int leafnum, res; - dnode_t *node; - dplane_t *plane; - winding_t back; - plane_t split; - - while(nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - - VectorCopy(plane->normal, split.normal); - split.dist = plane->dist; - res = VS_SplitWinding (w, &back, &split, 0.1); - - if (res == SIDE_FRONT) - { - nodenum = node->children[0]; - } - else if (res == SIDE_BACK) - { - nodenum = node->children[1]; - } - else if (res == SIDE_ON) - { - memcpy(&back, w, sizeof(winding_t)); - VS_R_SubdivideRadialAreaLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - else - { - VS_R_SubdivideRadialAreaLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - } - leafnum = -nodenum - 1; - if (dleafs[leafnum].cluster != -1) - { - VS_FloodRadialAreaLight(light, w, leafnum); - } -} - -/* -============= -VS_R_FloodDirectedLight -============= -*/ -void VS_FloodDirectedLight(vsound_t *light, winding_t *w, int leafnum) -{ - int i; - float dist; - lightvolume_t volume; - vec3_t dir; - - if (light->atten_disttype == LDAT_NOSCALE) - { - // light travels without decrease in intensity over distance - dist = MAX_WORLD_COORD; - } - else - { - if ( light->atten_disttype == LDAT_LINEAR ) - dist = light->photons * lightLinearScale; - else - dist = sqrt(light->photons); - } - - memset(&volume, 0, sizeof(lightvolume_t)); - for (i = 0; i < w->numpoints; i++) - { - VectorMA(w->points[i], dist, light->normal, volume.points[i]); - VectorSubtract(w->points[(i+1)%w->numpoints], w->points[i], dir); - CrossProduct(light->normal, dir, volume.planes[i].normal); - VectorNormalize(volume.planes[i].normal, volume.planes[i].normal); - volume.planes[i].dist = DotProduct(volume.planes[i].normal, w->points[i]); - } - volume.numplanes = w->numpoints; - VectorCopy(light->normal, volume.endplane.normal); - VectorInverse(volume.endplane.normal); - volume.endplane.dist = DotProduct(volume.endplane.normal, volume.points[0]); - volume.farplane = volume.endplane; - volume.surfaceNum = -1; - volume.type = VOLUME_DIRECTED; - volume.cluster = dleafs[leafnum].cluster; - VS_R_FloodLight(light, &volume, volume.cluster, 0); - if (volume.surfaceNum >= 0) - { - VS_R_CastLightAtSurface(light, &volume); - } -} - -/* -============= -VS_R_SubdivideDirectedAreaLight -============= -*/ -void VS_R_SubdivideDirectedAreaLight(vsound_t *light, int nodenum, winding_t *w) -{ - int leafnum, res; - dnode_t *node; - dplane_t *plane; - winding_t back; - plane_t split; - - while(nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - - VectorCopy(plane->normal, split.normal); - split.dist = plane->dist; - res = VS_SplitWinding (w, &back, &split, 0.1); - - if (res == SIDE_FRONT) - { - nodenum = node->children[0]; - } - else if (res == SIDE_BACK) - { - nodenum = node->children[1]; - } - else if (res == SIDE_ON) - { - memcpy(&back, w, sizeof(winding_t)); - VS_R_SubdivideDirectedAreaLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - else - { - VS_R_SubdivideDirectedAreaLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - } - leafnum = -nodenum - 1; - if (dleafs[leafnum].cluster != -1) - { - VS_FloodDirectedLight(light, w, leafnum); - } -} - -/* -============= -VS_FloodLight -============= -*/ -void VS_FloodLight(vsound_t *light) -{ - lightvolume_t volume; - dleaf_t *leaf; - int leafnum, i, j, k, dir[2][4] = {{1, 1, -1, -1}, {1, -1, -1, 1}}; - float a, step, dist, radius, windingdist; - vec3_t vec, r, p, temp; - winding_t winding; - - switch(light->type) - { - case LIGHT_POINTRADIAL: - { - // source is a point - // light radiates in all directions - // creates sharp shadows - // - // create 6 volumes shining in the axis directions - // what about: 4 tetrahedrons instead? - // - if ( light->atten_disttype == LDAT_LINEAR ) - dist = light->photons * lightLinearScale; - else - dist = sqrt(light->photons); - //always put the winding at a large distance to avoid epsilon issues - windingdist = MAX_WORLD_COORD; - if (dist > windingdist) - windingdist = dist; - // - leafnum = VS_LightLeafnum(light->origin); - leaf = &dleafs[leafnum]; - if (leaf->cluster == -1) - { - light->insolid = qtrue; - break; - } - // for each axis - for (i = 0; i < 3; i++) - { - // for both directions on the axis - for (j = -1; j <= 1; j += 2) - { - memset(&volume, 0, sizeof(lightvolume_t)); - volume.numplanes = 0; - for (k = 0; k < 4; k ++) - { - volume.points[volume.numplanes][i] = light->origin[i] + j * windingdist; - volume.points[volume.numplanes][(i+1)%3] = light->origin[(i+1)%3] + dir[0][k] * windingdist; - volume.points[volume.numplanes][(i+2)%3] = light->origin[(i+2)%3] + dir[1][k] * windingdist; - volume.numplanes++; - } - if (j >= 0) - { - VectorCopy(volume.points[0], temp); - VectorCopy(volume.points[2], volume.points[0]); - VectorCopy(temp, volume.points[2]); - } - for (k = 0; k < volume.numplanes; k++) - { - VS_PlaneFromPoints(&volume.planes[k], light->origin, volume.points[(k+1)%volume.numplanes], volume.points[k]); - } - VectorCopy(light->origin, temp); - temp[i] += (float) j * dist; - VectorClear(volume.endplane.normal); - volume.endplane.normal[i] = -j; - volume.endplane.dist = DotProduct(volume.endplane.normal, temp); //DotProduct(volume.endplane.normal, volume.points[0]); - volume.farplane = volume.endplane; - volume.cluster = leaf->cluster; - volume.surfaceNum = -1; - volume.type = VOLUME_NORMAL; - // - memset(volume.facetTested, 0, sizeof(volume.facetTested)); - memset(volume.clusterTested, 0, sizeof(volume.clusterTested)); - VS_R_FloodLight(light, &volume, leaf->cluster, 0); - if (volume.surfaceNum >= 0) - { - VS_R_CastLightAtSurface(light, &volume); - } - } - } - break; - } - case LIGHT_POINTSPOT: - { - // source is a point - // light is targetted - // creates sharp shadows - // - // what about using brushes to shape spot lights? that'd be pretty cool - // - if ( light->atten_disttype == LDAT_LINEAR ) - dist = light->photons * lightLinearScale; - else - dist = sqrt(light->photons); - dist *= 2; - // - windingdist = 4096; - if (dist > windingdist) - windingdist = dist; - //take 8 times the cone radius because the spotlight also lights outside the cone - radius = 8 * windingdist * light->radiusByDist; - // - memset(&volume, 0, sizeof(lightvolume_t)); - leafnum = VS_LightLeafnum(light->origin); - leaf = &dleafs[leafnum]; - if (leaf->cluster == -1) - { - light->insolid = qtrue; - break; - } - // - VectorClear(vec); - for (i = 0; i < 3; i++) - { - if (light->normal[i] > -0.9 && light->normal[i] < 0.9) - { - vec[i] = 1; - break; - } - } - CrossProduct(light->normal, vec, r); - VectorScale(r, radius, p); - volume.numplanes = 0; - step = 45; - for (a = step / 2; a < 360 + step / 2; a += step) - { - RotatePointAroundVector(volume.points[volume.numplanes], light->normal, p, a); - VectorAdd(light->origin, volume.points[volume.numplanes], volume.points[volume.numplanes]); - VectorMA(volume.points[volume.numplanes], windingdist, light->normal, volume.points[volume.numplanes]); - volume.numplanes++; - } - for (i = 0; i < volume.numplanes; i++) - { - VS_PlaneFromPoints(&volume.planes[i], light->origin, volume.points[(i+1)%volume.numplanes], volume.points[i]); - } - VectorMA(light->origin, dist, light->normal, temp); - VectorCopy(light->normal, volume.endplane.normal); - VectorInverse(volume.endplane.normal); - volume.endplane.dist = DotProduct(volume.endplane.normal, temp);//DotProduct(volume.endplane.normal, volume.points[0]); - volume.farplane = volume.endplane; - volume.cluster = leaf->cluster; - volume.surfaceNum = -1; - volume.type = VOLUME_NORMAL; - // - memset(volume.facetTested, 0, sizeof(volume.facetTested)); - memset(volume.clusterTested, 0, sizeof(volume.clusterTested)); - VS_R_FloodLight(light, &volume, leaf->cluster, 0); - if (volume.surfaceNum >= 0) - { - VS_R_CastLightAtSurface(light, &volume); - } - break; - } - case LIGHT_POINTFAKESURFACE: - { - float value; - int n, axis; - vec3_t v, vecs[2]; - - if ( light->atten_disttype == LDAT_LINEAR ) - dist = light->photons * lightLinearScale; - else - dist = sqrt(light->photons); - //always put the winding at a large distance to avoid epsilon issues - windingdist = 4096; - if (dist > windingdist) - windingdist = dist; - // - VectorMA(light->origin, 0.1, light->normal, light->origin); - // - leafnum = VS_LightLeafnum(light->origin); - leaf = &dleafs[leafnum]; - if (leaf->cluster == -1) - { - light->insolid = qtrue; - break; - } - value = 0; - for (i = 0; i < 3; i++) - { - if (fabs(light->normal[i]) > value) - { - value = fabs(light->normal[i]); - axis = i; - } - } - for (i = 0; i < 2; i++) - { - VectorClear(v); - v[(axis + 1 + i) % 3] = 1; - CrossProduct(light->normal, v, vecs[i]); - } - //cast 4 volumes at the front of the surface - for (i = -1; i <= 1; i += 2) - { - for (j = -1; j <= 1; j += 2) - { - for (n = 0; n < 2; n++) - { - memset(&volume, 0, sizeof(lightvolume_t)); - volume.numplanes = 3; - VectorMA(light->origin, i * windingdist, vecs[0], volume.points[(i == j) == n]); - VectorMA(light->origin, j * windingdist, vecs[1], volume.points[(i != j) == n]); - VectorMA(light->origin, windingdist, light->normal, volume.points[2]); - for (k = 0; k < volume.numplanes; k++) - { - VS_PlaneFromPoints(&volume.planes[k], light->origin, volume.points[(k+1)%volume.numplanes], volume.points[k]); - } - VS_PlaneFromPoints(&volume.endplane, volume.points[0], volume.points[1], volume.points[2]); - VectorMA(light->origin, dist, light->normal, temp); - volume.endplane.dist = DotProduct(volume.endplane.normal, temp); - if (DotProduct(light->origin, volume.endplane.normal) - volume.endplane.dist > 0) - break; - } - volume.farplane = volume.endplane; - volume.cluster = leaf->cluster; - volume.surfaceNum = -1; - volume.type = VOLUME_NORMAL; - // - memset(volume.facetTested, 0, sizeof(volume.facetTested)); - memset(volume.clusterTested, 0, sizeof(volume.clusterTested)); - - VS_R_FloodLight(light, &volume, leaf->cluster, 0); - if (volume.surfaceNum >= 0) - { - VS_R_CastLightAtSurface(light, &volume); - } - } - } - break; - } - case LIGHT_SURFACEDIRECTED: - { - // source is an area defined by a winding - // the light is unidirectional - // creates sharp shadows - // for instance sun light or laser light - // - memcpy(&winding, &light->w, sizeof(winding_t)); - VS_R_SubdivideDirectedAreaLight(light, 0, &winding); - break; - } - case LIGHT_SURFACERADIAL: - { - // source is an area defined by a winding - // the light radiates in all directions at the front of the winding plane - // - memcpy(&winding, &light->w, sizeof(winding_t)); - VS_R_SubdivideRadialAreaLight(light, 0, &winding); - break; - } - case LIGHT_SURFACESPOT: - { - // source is an area defined by a winding - // light is targetted but not unidirectional - // - memcpy(&winding, &light->w, sizeof(winding_t)); - VS_R_SubdivideAreaSpotLight(light, 0, &winding); - break; - } - } -} - -/* -============= -VS_FloodLightThread -============= -*/ -void VS_FloodLightThread(int num) -{ - VS_FloodLight(vsounds[num]); -} - -/* -============= -VS_TestLightLeafs -============= -*/ -void VS_TestLightLeafs(void) -{ - int leafnum, i; - vsound_t *light; - dleaf_t *leaf; - - for (i = 0; i < numvsounds; i++) - { - light = vsounds[i]; - if (light->type != LIGHT_POINTRADIAL && - light->type != LIGHT_POINTSPOT) - continue; - leafnum = VS_LightLeafnum(light->origin); - leaf = &dleafs[leafnum]; - if (leaf->cluster == -1) - if (light->type == LIGHT_POINTRADIAL) - qprintf("light in solid at %1.1f %1.1f %1.1f\n", light->origin[0], light->origin[1], light->origin[2]); - else if (light->type == LIGHT_POINTSPOT) - qprintf("spot light in solid at %1.1f %1.1f %1.1f\n", light->origin[0], light->origin[1], light->origin[2]); - } -} - - -/* -============= -VS_DoForcedTraceLight -============= -*/ -// from light.c -void TraceLtm( int num ); - -void VS_DoForcedTraceLight(int num) -{ - dsurface_t *ds; - shaderInfo_t *si; - - ds = &drawSurfaces[num]; - - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) - return; - - if ( ds->lightmapNum < 0 ) - return; - - // always light entity surfaces with the old light algorithm - if ( !entitySurface[num] ) - { - si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - - if (defaulttracelight) - { - if (si->forceVLight) - return; - } - else - { - if (!si->forceTraceLight) - return; - } - } - - TraceLtm(num); -} - -/* -============= -VS_DoForcedTraceLightSurfaces -============= -*/ -void VS_DoForcedTraceLightSurfaces(void) -{ - _printf( "forced trace light\n" ); - RunThreadsOnIndividual( numDrawSurfaces, qtrue, VS_DoForcedTraceLight ); -} - -float *oldLightFloats; - -/* -============= -VS_SurfaceRadiosity -============= -*/ -void VS_SurfaceRadiosity( int num ) { - dsurface_t *ds; - mesh_t *mesh; - shaderInfo_t *si; - lsurfaceTest_t *test; - int x, y, k; - vec3_t base, normal; - float *color, area; - vsound_t vsound; - - ds = &drawSurfaces[num]; - - if ( ds->lightmapNum < 0 ) { - return; // doesn't have a lightmap - } - - // vertex-lit triangle model - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) { - return; - } - - si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - test = lsurfaceTest[ num ]; - - if (!test) { - return; - } - - for (x = 0; x < ds->lightmapWidth; x++) { - for (y = 0; y < ds->lightmapHeight; y++) { - // - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - area = lightmappixelarea[k]; - if (area <= 0) - continue; - // - if (ds->surfaceType == MST_PATCH) - { - mesh = test->detailMesh; - VectorCopy( mesh->verts[y*mesh->width+x].xyz, base); - VectorCopy( mesh->verts[y*mesh->width+x].normal, normal); - } - else - { - VectorMA(ds->lightmapOrigin, (float) x, ds->lightmapVecs[0], base); - VectorMA(base, (float) y, ds->lightmapVecs[1], base); - VectorCopy(test->facets[0].plane.normal, normal); - } - // create ligth from base - memset(&vsound, 0, sizeof(vsound_t)); - color = &oldLightFloats[k*3]; - // a few units away from the surface - VectorMA(base, 5, normal, vsound.origin); - ColorNormalize(color, vsound.color); - // ok this is crap - vsound.photons = VectorLength(color) * 0.05 * lightPointScale / (area * radiosity_scale); - // what about using a front facing light only ? - vsound.type = LIGHT_POINTRADIAL; - // flood the light from this lightmap pixel - VS_FloodLight(&vsound); - // only one thread at a time may write to the lightmap of this surface - MutexLock(test->mutex); - // don't light the lightmap pixel itself - lightFloats[k*3] = oldLightFloats[k*3]; - lightFloats[k*3+1] = oldLightFloats[k*3+1]; - lightFloats[k*3+2] = oldLightFloats[k*3+2]; - // - MutexUnlock(test->mutex); - } - } -} - -/* -============= -VS_Radiosity - -this aint working real well but it's fun to play with. -============= -*/ -void VS_Radiosity(void) { - - oldLightFloats = lightFloats; - lightFloats = (float *) malloc(numLightBytes * sizeof(float)); - memcpy(lightFloats, oldLightFloats, numLightBytes * sizeof(float)); - _printf("%7i surfaces\n", numDrawSurfaces); - RunThreadsOnIndividual( numDrawSurfaces, qtrue, VS_SurfaceRadiosity ); - free(oldLightFloats); -} - -/* -============= -VS_LightWorld -============= -*/ -void VS_LightWorld(void) -{ - int i, numcastedvolumes, numvsoundsinsolid; - float f; - - // find the optional world ambient - GetVectorForKey( &entities[0], "_color", lightAmbientColor ); - f = FloatForKey( &entities[0], "ambient" ); - VectorScale( lightAmbientColor, f, lightAmbientColor ); - /* - _printf("\r%6d lights out of %d", 0, numvsounds); - for (i = 0; i < numvsounds; i++) - { - _printf("\r%6d", i); - VS_FloodLight(vsounds[i]); - } - _printf("\r%6d lights out of %d\n", i, numvsounds); - */ - _printf("%7i lights\n", numvsounds); - RunThreadsOnIndividual( numvsounds, qtrue, VS_FloodLightThread ); - - numcastedvolumes = 0; - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - if (lsurfaceTest[i]) - numcastedvolumes += lsurfaceTest[i]->numvolumes; - } - _printf("%7i light volumes casted\n", numcastedvolumes); - numvsoundsinsolid = 0; - for (i = 0; i < numvsounds; i++) - { - if (vsounds[i]->insolid) - numvsoundsinsolid++; - } - _printf("%7i lights in solid\n", numvsoundsinsolid); - // - radiosity_scale = 1; - for (i = 0; i < radiosity; i++) { - VS_Radiosity(); - radiosity_scale <<= 1; - } - // - VS_StoreLightmap(); - // redo surfaces with the old light algorithm when needed - VS_DoForcedTraceLightSurfaces(); -} - -/* -============= -VS_CreateEntitySpeakers -============= -*/ -entity_t *FindTargetEntity( const char *target ); - -void VS_CreateEntitySpeakers (void) -{ - int i, c_entityLights; - vsound_t *dl; - entity_t *e, *e2; - const char *name; - const char *target; - vec3_t dest; - const char *_color; - float intensity; - int spawnflags; - - // - c_entityLights = 0; - _printf("Creating entity lights...\n"); - // - for ( i = 0 ; i < num_entities ; i++ ) { - e = &entities[i]; - name = ValueForKey (e, "classname"); - if (strncmp (name, "speaker", 7)) - continue; - - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - - spawnflags = FloatForKey (e, "spawnflags"); - if ( spawnflags & 1 ) { - dl->atten_disttype = LDAT_LINEAR; - } - if ( spawnflags & 2 ) { - dl->atten_disttype = LDAT_NOSCALE; - } - if ( spawnflags & 4 ) { - dl->atten_angletype = LAAT_QUADRATIC; - } - if ( spawnflags & 8 ) { - dl->atten_angletype = LAAT_DOUBLEQUADRATIC; - } - - dl->atten_distscale = FloatForKey(e, "atten_distscale"); - dl->atten_anglescale = FloatForKey(e, "atten_anglescale"); - - GetVectorForKey (e, "origin", dl->origin); - dl->style = FloatForKey (e, "_style"); - if (!dl->style) - dl->style = FloatForKey (e, "style"); - if (dl->style < 0) - dl->style = 0; - - intensity = FloatForKey (e, "light"); - if (!intensity) - intensity = FloatForKey (e, "_light"); - if (!intensity) - intensity = 300; - _color = ValueForKey (e, "_color"); - if (_color && _color[0]) - { - sscanf (_color, "%f %f %f", &dl->color[0],&dl->color[1],&dl->color[2]); - ColorNormalize (dl->color, dl->color); - } - else - dl->color[0] = dl->color[1] = dl->color[2] = 1.0; - - intensity = intensity * lightPointScale; - dl->photons = intensity; - - dl->type = LIGHT_POINTRADIAL; - - // lights with a target will be spotlights - target = ValueForKey (e, "target"); - - if ( target[0] ) { - float radius; - float dist; - - e2 = FindTargetEntity (target); - if (!e2) { - _printf ("WARNING: light at (%i %i %i) has missing target\n", - (int)dl->origin[0], (int)dl->origin[1], (int)dl->origin[2]); - } else { - GetVectorForKey (e2, "origin", dest); - VectorSubtract (dest, dl->origin, dl->normal); - dist = VectorNormalize (dl->normal, dl->normal); - radius = FloatForKey (e, "radius"); - if ( !radius ) { - radius = 64; - } - if ( !dist ) { - dist = 64; - } - dl->radiusByDist = (radius + 16) / dist; - dl->type = LIGHT_POINTSPOT; - } - } - vsounds[numvsounds++] = dl; - c_entityLights++; - } - _printf("%7i entity lights\n", c_entityLights); -} - -/* -================== -VS_SubdivideAreaLight -================== -*/ -void VS_SubdivideAreaLight( shaderInfo_t *ls, winding_t *w, vec3_t normal, - float areaSubdivide, qboolean backsplash ) { - float area, value, intensity; - vsound_t *dl, *dl2; - vec3_t mins, maxs; - int axis; - winding_t *front, *back; - vec3_t planeNormal; - float planeDist; - - if ( !w ) { - return; - } - - WindingBounds( w, mins, maxs ); - - // check for subdivision - for ( axis = 0 ; axis < 3 ; axis++ ) { - if ( maxs[axis] - mins[axis] > areaSubdivide ) { - VectorClear( planeNormal ); - planeNormal[axis] = 1; - planeDist = ( maxs[axis] + mins[axis] ) * 0.5; - ClipWindingEpsilon ( w, planeNormal, planeDist, ON_EPSILON, &front, &back ); - VS_SubdivideAreaLight( ls, front, normal, areaSubdivide, qfalse ); - VS_SubdivideAreaLight( ls, back, normal, areaSubdivide, qfalse ); - FreeWinding( w ); - return; - } - } - - // create a light from this - area = WindingArea (w); - if ( area <= 0 || area > 20000000 ) { - return; - } - - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - dl->type = LIGHT_POINTFAKESURFACE; - - WindingCenter( w, dl->origin ); - memcpy(dl->w.points, w->points, sizeof(vec3_t) * w->numpoints); - dl->w.numpoints = w->numpoints; - VectorCopy ( normal, dl->normal); - VectorCopy ( normal, dl->plane); - dl->plane[3] = DotProduct( dl->origin, normal ); - - value = ls->value; - intensity = value * area * lightAreaScale; - VectorAdd( dl->origin, dl->normal, dl->origin ); - - VectorCopy( ls->color, dl->color ); - - dl->photons = intensity; - - // emitColor is irrespective of the area - VectorScale( ls->color, value*lightFormFactorValueScale*lightAreaScale, dl->emitColor ); - // - VectorCopy(dl->emitColor, dl->color); - - dl->si = ls; - - if ( ls->contents & CONTENTS_FOG ) { - dl->twosided = qtrue; - } - - vsounds[numvsounds++] = dl; - - // optionally create a point backsplash light - if ( backsplash && ls->backsplashFraction > 0 ) { - - dl2 = malloc(sizeof(*dl)); - memset (dl2, 0, sizeof(*dl2)); - dl2->type = LIGHT_POINTRADIAL; - - VectorMA( dl->origin, ls->backsplashDistance, normal, dl2->origin ); - - VectorCopy( ls->color, dl2->color ); - - dl2->photons = dl->photons * ls->backsplashFraction; - dl2->si = ls; - - vsounds[numvsounds++] = dl2; - } -} - -/* -================== -VS_CreateFakeSurfaceLights -================== -*/ -void VS_CreateFakeSurfaceLights( void ) { - int i, j, side; - dsurface_t *ds; - shaderInfo_t *ls; - winding_t *w; - lFacet_t *f; - vsound_t *dl; - vec3_t origin; - drawVert_t *dv; - int c_surfaceLights; - float lightSubdivide; - vec3_t normal; - - - c_surfaceLights = 0; - _printf ("Creating surface lights...\n"); - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - // see if this surface is light emiting - ds = &drawSurfaces[i]; - - ls = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - if ( ls->value == 0 ) { - continue; - } - - // determine how much we need to chop up the surface - if ( ls->lightSubdivide ) { - lightSubdivide = ls->lightSubdivide; - } else { - lightSubdivide = lightDefaultSubdivide; - } - - c_surfaceLights++; - - // an autosprite shader will become - // a point light instead of an area light - if ( ls->autosprite ) { - // autosprite geometry should only have four vertexes - if ( lsurfaceTest[i] ) { - // curve or misc_model - f = lsurfaceTest[i]->facets; - if ( lsurfaceTest[i]->numFacets != 1 || f->numpoints != 4 ) { - _printf( "WARNING: surface at (%i %i %i) has autosprite shader but isn't a quad\n", - (int)f->points[0], (int)f->points[1], (int)f->points[2] ); - } - VectorAdd( f->points[0], f->points[1], origin ); - VectorAdd( f->points[2], origin, origin ); - VectorAdd( f->points[3], origin, origin ); - VectorScale( origin, 0.25, origin ); - } else { - // normal polygon - dv = &drawVerts[ ds->firstVert ]; - if ( ds->numVerts != 4 ) { - _printf( "WARNING: surface at (%i %i %i) has autosprite shader but %i verts\n", - (int)dv->xyz[0], (int)dv->xyz[1], (int)dv->xyz[2] ); - continue; - } - - VectorAdd( dv[0].xyz, dv[1].xyz, origin ); - VectorAdd( dv[2].xyz, origin, origin ); - VectorAdd( dv[3].xyz, origin, origin ); - VectorScale( origin, 0.25, origin ); - } - - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - VectorCopy( origin, dl->origin ); - VectorCopy( ls->color, dl->color ); - dl->photons = ls->value * lightPointScale; - dl->type = LIGHT_POINTRADIAL; - vsounds[numvsounds++] = dl; - continue; - } - - // possibly create for both sides of the polygon - for ( side = 0 ; side <= ls->twoSided ; side++ ) { - // create area lights - if ( lsurfaceTest[i] ) { - // curve or misc_model - for ( j = 0 ; j < lsurfaceTest[i]->numFacets ; j++ ) { - f = lsurfaceTest[i]->facets + j; - w = AllocWinding( f->numpoints ); - w->numpoints = f->numpoints; - memcpy( w->points, f->points, f->numpoints * 12 ); - - VectorCopy( f->plane.normal, normal ); - if ( side ) { - winding_t *t; - - t = w; - w = ReverseWinding( t ); - FreeWinding( t ); - VectorSubtract( vec3_origin, normal, normal ); - } - VS_SubdivideAreaLight( ls, w, normal, lightSubdivide, qtrue ); - } - } else { - // normal polygon - - w = AllocWinding( ds->numVerts ); - w->numpoints = ds->numVerts; - for ( j = 0 ; j < ds->numVerts ; j++ ) { - VectorCopy( drawVerts[ds->firstVert+j].xyz, w->points[j] ); - } - VectorCopy( ds->lightmapVecs[2], normal ); - if ( side ) { - winding_t *t; - - t = w; - w = ReverseWinding( t ); - FreeWinding( t ); - VectorSubtract( vec3_origin, normal, normal ); - } - VS_SubdivideAreaLight( ls, w, normal, lightSubdivide, qtrue ); - } - } - } - - _printf( "%7i light emitting surfaces\n", c_surfaceLights ); -} - - -/* -================== -VS_WindingForBrushSide -================== -*/ -winding_t *VS_WindingForBrushSide(dbrush_t *brush, int side, winding_t *w) -{ - int i, res; - winding_t *tmpw; - plane_t plane; - - VectorCopy(dplanes[ dbrushsides[ brush->firstSide + side ].planeNum ].normal, plane.normal); - VectorInverse(plane.normal); - plane.dist = -dplanes[ dbrushsides[ brush->firstSide + side ].planeNum ].dist; - tmpw = BaseWindingForPlane( plane.normal, plane.dist ); - memcpy(w->points, tmpw->points, sizeof(vec3_t) * tmpw->numpoints); - w->numpoints = tmpw->numpoints; - - for (i = 0; i < brush->numSides; i++) - { - if (i == side) - continue; - VectorCopy(dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].normal, plane.normal); - VectorInverse(plane.normal); - plane.dist = -dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].dist; - res = VS_ChopWinding(w, &plane, 0.1); - if (res == SIDE_BACK) - return NULL; - } - return w; -} - -/* -================== -VS_CreateSkyLights -================== -*/ -void VS_CreateSkyLights(void) -{ - int i, j, c_skyLights; - dbrush_t *b; - shaderInfo_t *si; - dbrushside_t *s; - vsound_t *dl; - vec3_t sunColor, sunDir = { 0.45, 0.3, 0.9 }; - float d; - - VectorNormalize(sunDir, sunDir); - VectorInverse(sunDir); - - c_skyLights = 0; - _printf("Creating sky lights...\n"); - // find the sky shader - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - si = ShaderInfoForShader( dshaders[ drawSurfaces[i].shaderNum ].shader ); - if ( si->surfaceFlags & SURF_SKY ) { - VectorCopy( si->sunLight, sunColor ); - VectorCopy( si->sunDirection, sunDir ); - VectorInverse(sunDir); - break; - } - } - - // find the brushes - for ( i = 0 ; i < numbrushes ; i++ ) { - b = &dbrushes[i]; - for ( j = 0 ; j < b->numSides ; j++ ) { - s = &dbrushsides[ b->firstSide + j ]; - if ( dshaders[ s->shaderNum ].surfaceFlags & SURF_SKY ) { - //if this surface doesn't face in the same direction as the sun - d = DotProduct(dplanes[ s->planeNum ].normal, sunDir); - if (d <= 0) - continue; - // - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - VectorCopy(sunColor, dl->color); - VectorCopy(sunDir, dl->normal); - VectorCopy(dplanes[ s->planeNum ].normal, dl->plane); - dl->plane[3] = dplanes[ s->planeNum ].dist; - dl->type = LIGHT_SURFACEDIRECTED; - dl->atten_disttype = LDAT_NOSCALE; - VS_WindingForBrushSide(b, j, &dl->w); -// DebugNet_DrawWinding(&dl->w, 2); - // - vsounds[numvsounds++] = dl; - c_skyLights++; - } - } - } - _printf("%7i light emitting sky surfaces\n", c_skyLights); -} - -/* -================== -VS_SetPortalSphere -================== -*/ -void VS_SetPortalSphere (lportal_t *p) -{ - int i; - vec3_t total, dist; - winding_t *w; - float r, bestr; - - w = p->winding; - VectorCopy (vec3_origin, total); - for (i=0 ; i<w->numpoints ; i++) - { - VectorAdd (total, w->points[i], total); - } - - for (i=0 ; i<3 ; i++) - total[i] /= w->numpoints; - - bestr = 0; - for (i=0 ; i<w->numpoints ; i++) - { - VectorSubtract (w->points[i], total, dist); - r = VectorLength (dist); - if (r > bestr) - bestr = r; - } - VectorCopy (total, p->origin); - p->radius = bestr; -} - -/* -================== -VS_PlaneFromWinding -================== -*/ -void VS_PlaneFromWinding (winding_t *w, plane_t *plane) -{ - vec3_t v1, v2; - - //calc plane - VectorSubtract (w->points[2], w->points[1], v1); - VectorSubtract (w->points[0], w->points[1], v2); - CrossProduct (v2, v1, plane->normal); - VectorNormalize (plane->normal, plane->normal); - plane->dist = DotProduct (w->points[0], plane->normal); -} - -/* -================== -VS_AllocWinding -================== -*/ -winding_t *VS_AllocWinding (int points) -{ - winding_t *w; - int size; - - if (points > MAX_POINTS_ON_WINDING) - Error ("NewWinding: %i points", points); - - size = (int)((winding_t *)0)->points[points]; - w = malloc (size); - memset (w, 0, size); - - return w; -} - -/* -============ -VS_LoadPortals -============ -*/ -void VS_LoadPortals (char *name) -{ - int i, j, hint; - lportal_t *p; - lleaf_t *l; - char magic[80]; - FILE *f; - int numpoints; - winding_t *w; - int leafnums[2]; - plane_t plane; - // - - if (!strcmp(name,"-")) - f = stdin; - else - { - f = fopen(name, "r"); - if (!f) - Error ("LoadPortals: couldn't read %s\n",name); - } - - if (fscanf (f,"%79s\n%i\n%i\n%i\n",magic, &portalclusters, &numportals, &numfaces) != 4) - Error ("LoadPortals: failed to read header"); - if (strcmp(magic, PORTALFILE)) - Error ("LoadPortals: not a portal file"); - - _printf ("%6i portalclusters\n", portalclusters); - _printf ("%6i numportals\n", numportals); - _printf ("%6i numfaces\n", numfaces); - - if (portalclusters >= MAX_CLUSTERS) - Error ("more than %d clusters in portal file\n", MAX_CLUSTERS); - - // each file portal is split into two memory portals - portals = malloc(2*numportals*sizeof(lportal_t)); - memset (portals, 0, 2*numportals*sizeof(lportal_t)); - - leafs = malloc(portalclusters*sizeof(lleaf_t)); - memset (leafs, 0, portalclusters*sizeof(lleaf_t)); - - for (i=0, p=portals ; i<numportals ; i++) - { - if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1]) != 3) - Error ("LoadPortals: reading portal %i", i); - if (numpoints > MAX_POINTS_ON_WINDING) - Error ("LoadPortals: portal %i has too many points", i); - if ( (unsigned)leafnums[0] > portalclusters - || (unsigned)leafnums[1] > portalclusters) - Error ("LoadPortals: reading portal %i", i); - if (fscanf (f, "%i ", &hint) != 1) - Error ("LoadPortals: reading hint state"); - - w = p->winding = VS_AllocWinding (numpoints); - w->numpoints = numpoints; - - for (j=0 ; j<numpoints ; j++) - { - double v[3]; - int k; - - // scanf into double, then assign to vec_t - // so we don't care what size vec_t is - if (fscanf (f, "(%lf %lf %lf ) " - , &v[0], &v[1], &v[2]) != 3) - Error ("LoadPortals: reading portal %i", i); - for (k=0 ; k<3 ; k++) - w->points[j][k] = v[k]; - } - fscanf (f, "\n"); - - // calc plane - VS_PlaneFromWinding (w, &plane); - - // create forward portal - l = &leafs[leafnums[0]]; - if (l->numportals == MAX_PORTALS_ON_LEAF) - Error ("Leaf with too many portals"); - l->portals[l->numportals] = p; - l->numportals++; - - p->winding = w; - VectorSubtract (vec3_origin, plane.normal, p->plane.normal); - p->plane.dist = -plane.dist; - p->leaf = leafnums[1]; - VS_SetPortalSphere (p); - p++; - - // create backwards portal - l = &leafs[leafnums[1]]; - if (l->numportals == MAX_PORTALS_ON_LEAF) - Error ("Leaf with too many portals"); - l->portals[l->numportals] = p; - l->numportals++; - - p->winding = VS_AllocWinding(w->numpoints); - p->winding->numpoints = w->numpoints; - for (j=0 ; j<w->numpoints ; j++) - { - VectorCopy (w->points[w->numpoints-1-j], p->winding->points[j]); - } - - p->plane = plane; - p->leaf = leafnums[0]; - VS_SetPortalSphere (p); - p++; - - } - - fclose (f); -} - -/* -============ -VLightMain -============ -*/ -int VSoundMain (int argc, char **argv) { - int i; - double start, end; - const char *value; - - _printf ("----- VLighting ----\n"); - - for (i=1 ; i<argc ; i++) { - if (!strcmp(argv[i],"-v")) { - verbose = qtrue; - } else if (!strcmp(argv[i],"-threads")) { - numthreads = atoi (argv[i+1]); - _printf("num threads = %d\n", numthreads); - i++; - } else if (!strcmp(argv[i],"-area")) { - lightAreaScale *= atof(argv[i+1]); - _printf ("area light scaling at %f\n", lightAreaScale); - i++; - } else if (!strcmp(argv[i],"-point")) { - lightPointScale *= atof(argv[i+1]); - _printf ("point light scaling at %f\n", lightPointScale); - i++; - } else if (!strcmp(argv[i], "-samplesize")) { - samplesize = atoi(argv[i+1]); - if (samplesize < 1) samplesize = 1; - i++; - _printf("lightmap sample size is %dx%d units\n", samplesize, samplesize); - } else if (!strcmp(argv[i], "-nostitching")) { - nostitching = qtrue; - _printf("no stitching = true\n"); - } else if (!strcmp(argv[i], "-noalphashading")) { - noalphashading = qtrue; - _printf("no alpha shading = true\n"); - } else if (!strcmp(argv[i], "-nocolorshading")) { - nocolorshading = qtrue; - _printf("old style alpha shading = true\n"); - } else if (!strcmp(argv[i], "-nobackfaceculling")) { - nobackfaceculling = qtrue; - _printf("no backface culling = true\n"); - } else if (!strcmp(argv[i], "-tracelight")) { - defaulttracelight = qtrue; - _printf("default trace light = true\n"); - } else if (!strcmp(argv[i], "-radiosity")) { - radiosity = atoi(argv[i+1]); - _printf("radiosity = %d\n", radiosity); - i++; - } else { - break; - } - } - - ThreadSetDefault (); - - if (i != argc - 1) { - _printf("usage: q3map -vsound [-<switch> [-<switch> ...]] <mapname>\n" - "\n" - "Switches:\n" - " v = verbose output\n" - " threads <X> = set number of threads to X\n" - " area <V> = set the area light scale to V\n" - " point <W> = set the point light scale to W\n" - " novertex = don't calculate vertex lighting\n" - " nogrid = don't calculate light grid for dynamic model lighting\n" - " nostitching = no polygon stitching before lighting\n" - " noalphashading = don't use alpha shading\n" - " nocolorshading = don't use color alpha shading\n" - " tracelight = use old light algorithm by default\n" - " samplesize <N> = set the lightmap pixel size to NxN units\n"); - exit(0); - } - - SetQdirFromPath (argv[i]); - -#ifdef _WIN32 - InitPakFile(gamedir, NULL); -#endif - - strcpy (source, ExpandArg(argv[i])); - StripExtension (source); - DefaultExtension (source, ".bsp"); - - LoadShaderInfo(); - - _printf ("reading %s\n", source); - - LoadBSPFile (source); - ParseEntities(); - - value = ValueForKey( &entities[0], "gridsize" ); - if (strlen(value)) { - sscanf( value, "%f %f %f", &gridSize[0], &gridSize[1], &gridSize[2] ); - _printf("grid size = {%1.1f, %1.1f, %1.1f}\n", gridSize[0], gridSize[1], gridSize[2]); - } - - CountLightmaps(); - - StripExtension (source); - DefaultExtension (source, ".prt"); - - VS_LoadPortals(source); - - // set surfaceOrigin - SetEntityOrigins(); - - // grid and vertex lighting - GridAndVertexLighting(); - -#ifdef DEBUGNET - DebugNet_Setup(); -#endif - - start = clock(); - - lightFloats = (float *) malloc(numLightBytes * sizeof(float)); - memset(lightFloats, 0, numLightBytes * sizeof(float)); - - VS_InitSurfacesForTesting(); - - VS_CalcVisibleLightmapPixelArea(); - - numvsounds = 0; - VS_CreateEntitySpeakers(); - VS_CreateFakeSurfaceLights(); - VS_CreateSkyLights(); - - VS_TestLightLeafs(); - - VS_LightWorld(); - -#ifndef LIGHTPOLYS - StripExtension (source); - DefaultExtension (source, ".bsp"); - _printf ("writing %s\n", source); - WriteBSPFile (source); -#endif - - end = clock(); - - _printf ("%5.2f seconds elapsed\n", (end-start) / CLK_TCK); - -#ifdef LIGHTPOLYS - VS_DrawLightWindings(); -#endif - -#ifdef DEBUGNET - DebugNet_Shutdown(); -#endif - return 0; -} diff --git a/q3map/surface.c b/q3map/surface.c deleted file mode 100644 index 75daf1c..0000000 --- a/q3map/surface.c +++ /dev/null @@ -1,1158 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "qbsp.h" - - -mapDrawSurface_t mapDrawSurfs[MAX_MAP_DRAW_SURFS]; -int numMapDrawSurfs; - -/* -============================================================================= - -DRAWSURF CONSTRUCTION - -============================================================================= -*/ - -/* -================= -AllocDrawSurf -================= -*/ -mapDrawSurface_t *AllocDrawSurf( void ) { - mapDrawSurface_t *ds; - - if ( numMapDrawSurfs >= MAX_MAP_DRAW_SURFS ) { - Error( "MAX_MAP_DRAW_SURFS"); - } - ds = &mapDrawSurfs[ numMapDrawSurfs ]; - numMapDrawSurfs++; - - return ds; -} - -/* -================= -DrawSurfaceForSide -================= -*/ -#define SNAP_FLOAT_TO_INT 8 -#define SNAP_INT_TO_FLOAT (1.0/SNAP_FLOAT_TO_INT) - -mapDrawSurface_t *DrawSurfaceForSide( bspbrush_t *b, side_t *s, winding_t *w ) { - mapDrawSurface_t *ds; - int i, j; - shaderInfo_t *si; - drawVert_t *dv; - float mins[2], maxs[2]; - - // brush primitive : - // axis base - vec3_t texX,texY; - vec_t x,y; - - if ( w->numpoints > 64 ) { - Error( "DrawSurfaceForSide: w->numpoints = %i", w->numpoints ); - } - - si = s->shaderInfo; - - ds = AllocDrawSurf(); - - ds->shaderInfo = si; - ds->mapBrush = b; - ds->side = s; - ds->fogNum = -1; - ds->numVerts = w->numpoints; - ds->verts = malloc( ds->numVerts * sizeof( *ds->verts ) ); - memset( ds->verts, 0, ds->numVerts * sizeof( *ds->verts ) ); - - mins[0] = mins[1] = 99999; - maxs[0] = maxs[1] = -99999; - - // compute s/t coordinates from brush primitive texture matrix - // compute axis base - ComputeAxisBase( mapplanes[s->planenum].normal, texX, texY ); - - for ( j = 0 ; j < w->numpoints ; j++ ) { - dv = ds->verts + j; - - // round the xyz to a given precision - for ( i = 0 ; i < 3 ; i++ ) { - dv->xyz[i] = SNAP_INT_TO_FLOAT * floor( w->p[j][i] * SNAP_FLOAT_TO_INT + 0.5 ); - } - - if (g_bBrushPrimit==BPRIMIT_OLDBRUSHES) - { - // calculate texture s/t - dv->st[0] = s->vecs[0][3] + DotProduct( s->vecs[0], dv->xyz ); - dv->st[1] = s->vecs[1][3] + DotProduct( s->vecs[1], dv->xyz ); - dv->st[0] /= si->width; - dv->st[1] /= si->height; - } - else - { - // calculate texture s/t from brush primitive texture matrix - x = DotProduct( dv->xyz, texX ); - y = DotProduct( dv->xyz, texY ); - dv->st[0]=s->texMat[0][0]*x+s->texMat[0][1]*y+s->texMat[0][2]; - dv->st[1]=s->texMat[1][0]*x+s->texMat[1][1]*y+s->texMat[1][2]; - } - - for ( i = 0 ; i < 2 ; i++ ) { - if ( dv->st[i] < mins[i] ) { - mins[i] = dv->st[i]; - } - if ( dv->st[i] > maxs[i] ) { - maxs[i] = dv->st[i]; - } - } - - // copy normal - VectorCopy ( mapplanes[s->planenum].normal, dv->normal ); - } - - // adjust the texture coordinates to be as close to 0 as possible - if ( !si->globalTexture ) { - mins[0] = floor( mins[0] ); - mins[1] = floor( mins[1] ); - for ( i = 0 ; i < w->numpoints ; i++ ) { - dv = ds->verts + i; - dv->st[0] -= mins[0]; - dv->st[1] -= mins[1]; - } - } - - return ds; -} - - -//========================================================================= - - - - -typedef struct { - int planenum; - shaderInfo_t *shaderInfo; - int count; -} sideRef_t; - -#define MAX_SIDE_REFS MAX_MAP_PLANES - -sideRef_t sideRefs[MAX_SIDE_REFS]; -int numSideRefs; - -void AddSideRef( side_t *side ) { - int i; - - for ( i = 0 ; i < numSideRefs ; i++ ) { - if ( side->planenum == sideRefs[i].planenum - && side->shaderInfo == sideRefs[i].shaderInfo ) { - sideRefs[i].count++; - return; - } - } - - if ( numSideRefs == MAX_SIDE_REFS ) { - Error( "MAX_SIDE_REFS" ); - } - - sideRefs[i].planenum = side->planenum; - sideRefs[i].shaderInfo = side->shaderInfo; - sideRefs[i].count++; - numSideRefs++; -} - - -/* -===================== -MergeSides - -===================== -*/ -void MergeSides( entity_t *e, tree_t *tree ) { - int i; - - qprintf( "----- MergeSides -----\n"); - - for ( i = e->firstDrawSurf ; i < numMapDrawSurfs ; i++ ) { -// AddSideRef( side ); - } - - qprintf( "%5i siderefs\n", numSideRefs ); -} - -//===================================================================== - -/* -=================== -SubdivideDrawSurf -=================== -*/ -void SubdivideDrawSurf( mapDrawSurface_t *ds, winding_t *w, float subdivisions ) { - int i; - int axis; - vec3_t bounds[2]; - const float epsilon = 0.1; - int subFloor, subCeil; - winding_t *frontWinding, *backWinding; - mapDrawSurface_t *newds; - - if ( !w ) { - return; - } - if ( w->numpoints < 3 ) { - Error( "SubdivideDrawSurf: Bad w->numpoints" ); - } - - ClearBounds( bounds[0], bounds[1] ); - for ( i = 0 ; i < w->numpoints ; i++ ) { - AddPointToBounds( w->p[i], bounds[0], bounds[1] ); - } - - for ( axis = 0 ; axis < 3 ; axis++ ) { - vec3_t planePoint = { 0, 0, 0 }; - vec3_t planeNormal = { 0, 0, 0 }; - float d; - - subFloor = floor( bounds[0][axis] / subdivisions ) * subdivisions; - subCeil = ceil( bounds[1][axis] / subdivisions ) * subdivisions; - - planePoint[axis] = subFloor + subdivisions; - planeNormal[axis] = -1; - - d = DotProduct( planePoint, planeNormal ); - - // subdivide if necessary - if ( subCeil - subFloor > subdivisions ) { - // gotta clip polygon into two polygons - ClipWindingEpsilon( w, planeNormal, d, epsilon, &frontWinding, &backWinding ); - - // the clip may not produce two polygons if it was epsilon close - if ( !frontWinding ) { - w = backWinding; - } else if ( !backWinding ) { - w = frontWinding; - } else { - SubdivideDrawSurf( ds, frontWinding, subdivisions ); - SubdivideDrawSurf( ds, backWinding, subdivisions ); - - return; - } - } - } - - // emit this polygon - newds = DrawSurfaceForSide( ds->mapBrush, ds->side, w ); - newds->fogNum = ds->fogNum; -} - - -/* -===================== -SubdivideDrawSurfs - -Chop up surfaces that have subdivision attributes -===================== -*/ -void SubdivideDrawSurfs( entity_t *e, tree_t *tree ) { - int i; - mapDrawSurface_t *ds; - int numBaseDrawSurfs; - winding_t *w; - float subdivision; - shaderInfo_t *si; - - qprintf( "----- SubdivideDrawSurfs -----\n"); - numBaseDrawSurfs = numMapDrawSurfs; - for ( i = e->firstDrawSurf ; i < numBaseDrawSurfs ; i++ ) { - ds = &mapDrawSurfs[i]; - - // only subdivide brush sides, not patches or misc_models - if ( !ds->side ) { - continue; - } - - // check subdivision for shader - si = ds->side->shaderInfo; - if ( !si ) { - continue; - } - - if (ds->shaderInfo->autosprite || si->autosprite) { - continue; - } - - subdivision = si->subdivisions; - if ( !subdivision ) { - continue; - } - - w = WindingFromDrawSurf( ds ); - ds->numVerts = 0; // remove this reference - SubdivideDrawSurf( ds, w, subdivision ); - } - -} - - -//=================================================================================== - -/* -==================== -ClipSideIntoTree_r - -Adds non-opaque leaf fragments to the convex hull -==================== -*/ -void ClipSideIntoTree_r( winding_t *w, side_t *side, node_t *node ) { - plane_t *plane; - winding_t *front, *back; - - if ( !w ) { - return; - } - - if ( node->planenum != PLANENUM_LEAF ) { - if ( side->planenum == node->planenum ) { - ClipSideIntoTree_r( w, side, node->children[0] ); - return; - } - if ( side->planenum == ( node->planenum ^ 1) ) { - ClipSideIntoTree_r( w, side, node->children[1] ); - return; - } - - plane = &mapplanes[ node->planenum ]; - ClipWindingEpsilon ( w, plane->normal, plane->dist, - ON_EPSILON, &front, &back ); - FreeWinding( w ); - - ClipSideIntoTree_r( front, side, node->children[0] ); - ClipSideIntoTree_r( back, side, node->children[1] ); - - return; - } - - // if opaque leaf, don't add - if ( !node->opaque ) { - AddWindingToConvexHull( w, &side->visibleHull, mapplanes[ side->planenum ].normal ); - } - - FreeWinding( w ); - return; -} - - -/* -===================== -ClipSidesIntoTree - -Creates side->visibleHull for all visible sides - -The drawsurf for a side will consist of the convex hull of -all points in non-opaque clusters, which allows overlaps -to be trimmed off automatically. -===================== -*/ -void ClipSidesIntoTree( entity_t *e, tree_t *tree ) { - bspbrush_t *b; - int i; - winding_t *w; - side_t *side, *newSide; - shaderInfo_t *si; - - qprintf( "----- ClipSidesIntoTree -----\n"); - - for ( b = e->brushes ; b ; b = b->next ) { - for ( i = 0 ; i < b->numsides ; i++ ) { - side = &b->sides[i]; - if ( !side->winding) { - continue; - } - w = CopyWinding( side->winding ); - side->visibleHull = NULL; - ClipSideIntoTree_r( w, side, tree->headnode ); - - w = side->visibleHull; - if ( !w ) { - continue; - } - si = side->shaderInfo; - if ( !si ) { - continue; - } - // don't create faces for non-visible sides - if ( si->surfaceFlags & SURF_NODRAW ) { - continue; - } - - // always use the original quad winding for auto sprites - if ( side->shaderInfo->autosprite ) { - w = side->winding; - } - // - if ( side->bevel ) { - Error( "monkey tried to create draw surface for brush bevel" ); - } - // save this winding as a visible surface - DrawSurfaceForSide( b, side, w ); - - // make a back side for it if needed - if ( !(si->contents & CONTENTS_FOG) ) { - continue; - } - - // duplicate the up-facing side - w = ReverseWinding( w ); - - newSide = malloc( sizeof( *side ) ); - *newSide = *side; - newSide->visibleHull = w; - newSide->planenum ^= 1; - - // save this winding as a visible surface - DrawSurfaceForSide( b, newSide, w ); - - } - } -} - -/* -=================================================================================== - - FILTER REFERENCES DOWN THE TREE - -=================================================================================== -*/ - -/* -==================== -FilterDrawSurfIntoTree - -Place a reference to the given drawsurf in every leaf it contacts -We assume that the point mesh aproximation to the curve will get a -reference into all the leafs we need. -==================== -*/ -int FilterMapDrawSurfIntoTree( vec3_t point, mapDrawSurface_t *ds, node_t *node ) { - drawSurfRef_t *dsr; - float d; - plane_t *plane; - int c; - - if ( node->planenum != PLANENUM_LEAF ) { - plane = &mapplanes[ node->planenum ]; - d = DotProduct( point, plane->normal ) - plane->dist; - c = 0; - if ( d >= -ON_EPSILON ) { - c += FilterMapDrawSurfIntoTree( point, ds, node->children[0] ); - } - if ( d <= ON_EPSILON ) { - c += FilterMapDrawSurfIntoTree( point, ds, node->children[1] ); - } - return c; - } - - // if opaque leaf, don't add - if ( node->opaque ) { - return 0; - } - - // add the drawsurf if it hasn't been already - for ( dsr = node->drawSurfReferences ; dsr ; dsr = dsr->nextRef ) { - if ( dsr->outputNumber == numDrawSurfaces ) { - return 0; // already referenced - } - } - - dsr = malloc( sizeof( *dsr ) ); - dsr->outputNumber = numDrawSurfaces; - dsr->nextRef = node->drawSurfReferences; - node->drawSurfReferences = dsr; - return 1; -} - -/* -==================== -FilterDrawSurfIntoTree_r - -Place a reference to the given drawsurf in every leaf it is in -==================== -*/ -int FilterMapDrawSurfIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node ) { - drawSurfRef_t *dsr; - plane_t *plane; - int total; - winding_t *front, *back; - - if ( node->planenum != PLANENUM_LEAF ) { - plane = &mapplanes[ node->planenum ]; - ClipWindingEpsilon ( w, plane->normal, plane->dist, - ON_EPSILON, &front, &back ); - - total = 0; - if ( front ) { - total += FilterMapDrawSurfIntoTree_r( front, ds, node->children[0] ); - } - if ( back ) { - total += FilterMapDrawSurfIntoTree_r( back, ds, node->children[1] ); - } - - FreeWinding( w ); - return total; - } - - // if opaque leaf, don't add - if ( node->opaque ) { - return 0; - } - - // add the drawsurf if it hasn't been already - for ( dsr = node->drawSurfReferences ; dsr ; dsr = dsr->nextRef ) { - if ( dsr->outputNumber == numDrawSurfaces ) { - return 0; // already referenced - } - } - - dsr = malloc( sizeof( *dsr ) ); - dsr->outputNumber = numDrawSurfaces; - dsr->nextRef = node->drawSurfReferences; - node->drawSurfReferences = dsr; - return 1; -} - -/* -==================== -FilterSideIntoTree_r - -Place a reference to the given drawsurf in every leaf it contacts -==================== -*/ -int FilterSideIntoTree_r( winding_t *w, side_t *side, mapDrawSurface_t *ds, node_t *node ) { - drawSurfRef_t *dsr; - plane_t *plane; - winding_t *front, *back; - int total; - - if ( !w ) { - return 0; - } - - if ( node->planenum != PLANENUM_LEAF ) { - if ( side->planenum == node->planenum ) { - return FilterSideIntoTree_r( w, side, ds, node->children[0] ); - } - if ( side->planenum == ( node->planenum ^ 1) ) { - return FilterSideIntoTree_r( w, side, ds, node->children[1] ); - } - - plane = &mapplanes[ node->planenum ]; - ClipWindingEpsilon ( w, plane->normal, plane->dist, - ON_EPSILON, &front, &back ); - - total = FilterSideIntoTree_r( front, side, ds, node->children[0] ); - total += FilterSideIntoTree_r( back, side, ds, node->children[1] ); - - FreeWinding( w ); - return total; - } - - // if opaque leaf, don't add - if ( node->opaque ) { - return 0; - } - - dsr = malloc( sizeof( *dsr ) ); - dsr->outputNumber = numDrawSurfaces; - dsr->nextRef = node->drawSurfReferences; - node->drawSurfReferences = dsr; - - FreeWinding( w ); - return 1; -} - - -/* -===================== -FilterFaceIntoTree -===================== -*/ -int FilterFaceIntoTree( mapDrawSurface_t *ds, tree_t *tree ) { - int l; - winding_t *w; - - w = WindingFromDrawSurf( ds ); - l = FilterSideIntoTree_r( w, ds->side, ds, tree->headnode ); - - return l; -} - - - -/* -===================== -FilterPatchSurfIntoTree -===================== -*/ -#define SUBDIVISION_LIMIT 8.0 -int FilterPatchSurfIntoTree( mapDrawSurface_t *ds, tree_t *tree ) { - int i, j; - int l; - mesh_t baseMesh, *subdividedMesh; - winding_t *w; - - baseMesh.width = ds->patchWidth; - baseMesh.height = ds->patchHeight; - baseMesh.verts = ds->verts; - subdividedMesh = SubdivideMesh( baseMesh, SUBDIVISION_LIMIT, 32 ); - - l = 0; - for (i = 0; i < subdividedMesh->width-1; i++) { - for (j = 0; j < subdividedMesh->height-1; j++) { - w = AllocWinding(3); - VectorCopy(subdividedMesh->verts[j * subdividedMesh->width + i].xyz, w->p[0]); - VectorCopy(subdividedMesh->verts[j * subdividedMesh->width + i + 1].xyz, w->p[1]); - VectorCopy(subdividedMesh->verts[(j+1) * subdividedMesh->width + i].xyz, w->p[2]); - w->numpoints = 3; - l += FilterMapDrawSurfIntoTree_r( w, ds, tree->headnode ); - w = AllocWinding(3); - VectorCopy(subdividedMesh->verts[j * subdividedMesh->width + i + 1].xyz, w->p[0]); - VectorCopy(subdividedMesh->verts[(j+1) * subdividedMesh->width + i + 1].xyz, w->p[1]); - VectorCopy(subdividedMesh->verts[(j+1) * subdividedMesh->width + i].xyz, w->p[2]); - w->numpoints = 3; - l += FilterMapDrawSurfIntoTree_r( w, ds, tree->headnode ); - } - } - - // also use the old point filtering into the tree - for ( i = 0 ; i < subdividedMesh->width * subdividedMesh->height ; i++ ) { - l += FilterMapDrawSurfIntoTree( subdividedMesh->verts[i].xyz, ds, tree->headnode ); - } - - free(subdividedMesh); - - return l; -} - - -/* -===================== -FilterMiscModelSurfIntoTree -===================== -*/ -int FilterMiscModelSurfIntoTree( mapDrawSurface_t *ds, tree_t *tree ) { - int i; - int l; - winding_t *w; - - l = 0; - for (i = 0; i < ds->numIndexes-2; i++) { - w = AllocWinding(3); - VectorCopy(ds->verts[ds->indexes[i]].xyz, w->p[0]); - VectorCopy(ds->verts[ds->indexes[i+1]].xyz, w->p[1]); - VectorCopy(ds->verts[ds->indexes[i+2]].xyz, w->p[2]); - w->numpoints = 3; - l += FilterMapDrawSurfIntoTree_r( w, ds, tree->headnode ); - } - - // also use the old point filtering into the tree - for ( i = 0 ; i < ds->numVerts ; i++ ) { - l += FilterMapDrawSurfIntoTree( ds->verts[i].xyz, ds, tree->headnode ); - } - - return l; -} - -/* -===================== -FilterFlareSurfIntoTree -===================== -*/ -int FilterFlareSurfIntoTree( mapDrawSurface_t *ds, tree_t *tree ) { - return FilterMapDrawSurfIntoTree( ds->lightmapOrigin, ds, tree->headnode ); -} - - -//====================================================================== - -int c_stripSurfaces, c_fanSurfaces; - -/* -================== -IsTriangleDegenerate - -Returns qtrue if all three points are collinear or backwards -=================== -*/ -#define COLINEAR_AREA 10 -static qboolean IsTriangleDegenerate( drawVert_t *points, int a, int b, int c ) { - vec3_t v1, v2, v3; - float d; - - VectorSubtract( points[b].xyz, points[a].xyz, v1 ); - VectorSubtract( points[c].xyz, points[a].xyz, v2 ); - CrossProduct( v1, v2, v3 ); - d = VectorLength( v3 ); - - // assume all very small or backwards triangles will cause problems - if ( d < COLINEAR_AREA ) { - return qtrue; - } - - return qfalse; -} - -/* -=============== -SurfaceAsTriFan - -The surface can't be represented as a single tristrip without -leaving a degenerate triangle (and therefore a crack), so add -a point in the middle and create (points-1) triangles in fan order -=============== -*/ -static void SurfaceAsTriFan( dsurface_t *ds ) { - int i; - int colorSum[4]; - drawVert_t *mid, *v; - - // create a new point in the center of the face - if ( numDrawVerts == MAX_MAP_DRAW_VERTS ) { - Error( "MAX_MAP_DRAW_VERTS" ); - } - mid = &drawVerts[ numDrawVerts ]; - numDrawVerts++; - - colorSum[0] = colorSum[1] = colorSum[2] = colorSum[3] = 0; - - v = drawVerts + ds->firstVert; - for (i = 0 ; i < ds->numVerts ; i++, v++ ) { - VectorAdd( mid->xyz, v->xyz, mid->xyz ); - mid->st[0] += v->st[0]; - mid->st[1] += v->st[1]; - mid->lightmap[0] += v->lightmap[0]; - mid->lightmap[1] += v->lightmap[1]; - - colorSum[0] += v->color[0]; - colorSum[1] += v->color[1]; - colorSum[2] += v->color[2]; - colorSum[3] += v->color[3]; - } - - mid->xyz[0] /= ds->numVerts; - mid->xyz[1] /= ds->numVerts; - mid->xyz[2] /= ds->numVerts; - - mid->st[0] /= ds->numVerts; - mid->st[1] /= ds->numVerts; - - mid->lightmap[0] /= ds->numVerts; - mid->lightmap[1] /= ds->numVerts; - - mid->color[0] = colorSum[0] / ds->numVerts; - mid->color[1] = colorSum[1] / ds->numVerts; - mid->color[2] = colorSum[2] / ds->numVerts; - mid->color[3] = colorSum[3] / ds->numVerts; - - VectorCopy((drawVerts+ds->firstVert)->normal, mid->normal ); - - // fill in indices in trifan order - if ( numDrawIndexes + ds->numVerts*3 > MAX_MAP_DRAW_INDEXES ) { - Error( "MAX_MAP_DRAWINDEXES" ); - } - ds->firstIndex = numDrawIndexes; - ds->numIndexes = ds->numVerts*3; - - //FIXME - // should be: for ( i = 0 ; i < ds->numVerts ; i++ ) { - // set a break point and test this in a map - //for ( i = 0 ; i < ds->numVerts*3 ; i++ ) { - for ( i = 0 ; i < ds->numVerts ; i++ ) { - drawIndexes[numDrawIndexes++] = ds->numVerts; - drawIndexes[numDrawIndexes++] = i; - drawIndexes[numDrawIndexes++] = (i+1) % ds->numVerts; - } - - ds->numVerts++; -} - - -/* -================ -SurfaceAsTristrip - -Try to create indices that make (points-2) triangles in tristrip order -================ -*/ -#define MAX_INDICES 1024 -static void SurfaceAsTristrip( dsurface_t *ds ) { - int i; - int rotate; - int numIndices; - int ni; - int a, b, c; - int indices[MAX_INDICES]; - - // determine the triangle strip order - numIndices = ( ds->numVerts - 2 ) * 3; - if ( numIndices > MAX_INDICES ) { - Error( "MAX_INDICES exceeded for surface" ); - } - - // try all possible orderings of the points looking - // for a strip order that isn't degenerate - for ( rotate = 0 ; rotate < ds->numVerts ; rotate++ ) { - for ( ni = 0, i = 0 ; i < ds->numVerts - 2 - i ; i++ ) { - a = ( ds->numVerts - 1 - i + rotate ) % ds->numVerts; - b = ( i + rotate ) % ds->numVerts; - c = ( ds->numVerts - 2 - i + rotate ) % ds->numVerts; - - if ( IsTriangleDegenerate( drawVerts + ds->firstVert, a, b, c ) ) { - break; - } - indices[ni++] = a; - indices[ni++] = b; - indices[ni++] = c; - - if ( i + 1 != ds->numVerts - 1 - i ) { - a = ( ds->numVerts - 2 - i + rotate ) % ds->numVerts; - b = ( i + rotate ) % ds->numVerts; - c = ( i + 1 + rotate ) % ds->numVerts; - - if ( IsTriangleDegenerate( drawVerts + ds->firstVert, a, b, c ) ) { - break; - } - indices[ni++] = a; - indices[ni++] = b; - indices[ni++] = c; - } - } - if ( ni == numIndices ) { - break; // got it done without degenerate triangles - } - } - - // if any triangle in the strip is degenerate, - // render from a centered fan point instead - if ( ni < numIndices ) { - c_fanSurfaces++; - SurfaceAsTriFan( ds ); - return; - } - - // a normal tristrip - c_stripSurfaces++; - - if ( numDrawIndexes + ni > MAX_MAP_DRAW_INDEXES ) { - Error( "MAX_MAP_DRAW_INDEXES" ); - } - ds->firstIndex = numDrawIndexes; - ds->numIndexes = ni; - - memcpy( drawIndexes + numDrawIndexes, indices, ni * sizeof(int) ); - numDrawIndexes += ni; -} - -/* -=============== -EmitPlanarSurf -=============== -*/ -void EmitPlanarSurf( mapDrawSurface_t *ds ) { - int j; - dsurface_t *out; - drawVert_t *outv; - - if ( numDrawSurfaces == MAX_MAP_DRAW_SURFS ) { - Error( "MAX_MAP_DRAW_SURFS" ); - } - out = &drawSurfaces[ numDrawSurfaces ]; - numDrawSurfaces++; - - out->surfaceType = MST_PLANAR; - out->shaderNum = EmitShader( ds->shaderInfo->shader ); - out->firstVert = numDrawVerts; - out->numVerts = ds->numVerts; - out->fogNum = ds->fogNum; - out->lightmapNum = ds->lightmapNum; - out->lightmapX = ds->lightmapX; - out->lightmapY = ds->lightmapY; - out->lightmapWidth = ds->lightmapWidth; - out->lightmapHeight = ds->lightmapHeight; - - VectorCopy( ds->lightmapOrigin, out->lightmapOrigin ); - VectorCopy( ds->lightmapVecs[0], out->lightmapVecs[0] ); - VectorCopy( ds->lightmapVecs[1], out->lightmapVecs[1] ); - VectorCopy( ds->lightmapVecs[2], out->lightmapVecs[2] ); - - for ( j = 0 ; j < ds->numVerts ; j++ ) { - if ( numDrawVerts == MAX_MAP_DRAW_VERTS ) { - Error( "MAX_MAP_DRAW_VERTS" ); - } - outv = &drawVerts[ numDrawVerts ]; - numDrawVerts++; - memcpy( outv, &ds->verts[ j ], sizeof( *outv ) ); - outv->color[0] = 255; - outv->color[1] = 255; - outv->color[2] = 255; - outv->color[3] = 255; - } - - // create the indexes - SurfaceAsTristrip( out ); -} - - -/* -=============== -EmitPatchSurf -=============== -*/ -void EmitPatchSurf( mapDrawSurface_t *ds ) { - int j; - dsurface_t *out; - drawVert_t *outv; - - if ( numDrawSurfaces == MAX_MAP_DRAW_SURFS ) { - Error( "MAX_MAP_DRAW_SURFS" ); - } - out = &drawSurfaces[ numDrawSurfaces ]; - numDrawSurfaces++; - - out->surfaceType = MST_PATCH; - out->shaderNum = EmitShader( ds->shaderInfo->shader ); - out->firstVert = numDrawVerts; - out->numVerts = ds->numVerts; - out->firstIndex = numDrawIndexes; - out->numIndexes = ds->numIndexes; - out->patchWidth = ds->patchWidth; - out->patchHeight = ds->patchHeight; - out->fogNum = ds->fogNum; - out->lightmapNum = ds->lightmapNum; - out->lightmapX = ds->lightmapX; - out->lightmapY = ds->lightmapY; - out->lightmapWidth = ds->lightmapWidth; - out->lightmapHeight = ds->lightmapHeight; - - VectorCopy( ds->lightmapOrigin, out->lightmapOrigin ); - VectorCopy( ds->lightmapVecs[0], out->lightmapVecs[0] ); - VectorCopy( ds->lightmapVecs[1], out->lightmapVecs[1] ); - VectorCopy( ds->lightmapVecs[2], out->lightmapVecs[2] ); - - for ( j = 0 ; j < ds->numVerts ; j++ ) { - if ( numDrawVerts == MAX_MAP_DRAW_VERTS ) { - Error( "MAX_MAP_DRAW_VERTS" ); - } - outv = &drawVerts[ numDrawVerts ]; - numDrawVerts++; - memcpy( outv, &ds->verts[ j ], sizeof( *outv ) ); - outv->color[0] = 255; - outv->color[1] = 255; - outv->color[2] = 255; - outv->color[3] = 255; - } - - for ( j = 0 ; j < ds->numIndexes ; j++ ) { - if ( numDrawIndexes == MAX_MAP_DRAW_INDEXES ) { - Error( "MAX_MAP_DRAW_INDEXES" ); - } - drawIndexes[ numDrawIndexes ] = ds->indexes[ j ]; - numDrawIndexes++; - } -} - -/* -=============== -EmitFlareSurf -=============== -*/ -void EmitFlareSurf( mapDrawSurface_t *ds ) { - dsurface_t *out; - - if ( numDrawSurfaces == MAX_MAP_DRAW_SURFS ) { - Error( "MAX_MAP_DRAW_SURFS" ); - } - out = &drawSurfaces[ numDrawSurfaces ]; - numDrawSurfaces++; - - out->surfaceType = MST_FLARE; - out->shaderNum = EmitShader( ds->shaderInfo->shader ); - out->fogNum = ds->fogNum; - - VectorCopy( ds->lightmapOrigin, out->lightmapOrigin ); - VectorCopy( ds->lightmapVecs[0], out->lightmapVecs[0] ); // color - VectorCopy( ds->lightmapVecs[2], out->lightmapVecs[2] ); -} - - -/* -=============== -EmitModelSurf -=============== -*/ -void EmitModelSurf( mapDrawSurface_t *ds ) { - int j; - dsurface_t *out; - drawVert_t *outv; - - if ( numDrawSurfaces == MAX_MAP_DRAW_SURFS ) { - Error( "MAX_MAP_DRAW_SURFS" ); - } - out = &drawSurfaces[ numDrawSurfaces ]; - numDrawSurfaces++; - - out->surfaceType = MST_TRIANGLE_SOUP; - out->shaderNum = EmitShader( ds->shaderInfo->shader ); - out->firstVert = numDrawVerts; - out->numVerts = ds->numVerts; - out->firstIndex = numDrawIndexes; - out->numIndexes = ds->numIndexes; - out->patchWidth = ds->patchWidth; - out->patchHeight = ds->patchHeight; - out->fogNum = ds->fogNum; - out->lightmapNum = ds->lightmapNum; - out->lightmapX = ds->lightmapX; - out->lightmapY = ds->lightmapY; - out->lightmapWidth = ds->lightmapWidth; - out->lightmapHeight = ds->lightmapHeight; - - VectorCopy( ds->lightmapOrigin, out->lightmapOrigin ); - VectorCopy( ds->lightmapVecs[0], out->lightmapVecs[0] ); - VectorCopy( ds->lightmapVecs[1], out->lightmapVecs[1] ); - VectorCopy( ds->lightmapVecs[2], out->lightmapVecs[2] ); - - for ( j = 0 ; j < ds->numVerts ; j++ ) { - if ( numDrawVerts == MAX_MAP_DRAW_VERTS ) { - Error( "MAX_MAP_DRAW_VERTS" ); - } - outv = &drawVerts[ numDrawVerts ]; - numDrawVerts++; - memcpy( outv, &ds->verts[ j ], sizeof( *outv ) ); - outv->color[0] = 255; - outv->color[1] = 255; - outv->color[2] = 255; - } - - for ( j = 0 ; j < ds->numIndexes ; j++ ) { - if ( numDrawIndexes == MAX_MAP_DRAW_INDEXES ) { - Error( "MAX_MAP_DRAW_INDEXES" ); - } - drawIndexes[ numDrawIndexes ] = ds->indexes[ j ]; - numDrawIndexes++; - } -} - -//====================================================================== - -/* -================== -CreateFlareSurface - -Light flares from surface lights become -================== -*/ -void CreateFlareSurface( mapDrawSurface_t *faceDs ) { - mapDrawSurface_t *ds; - int i; - - ds = AllocDrawSurf(); - - if ( faceDs->shaderInfo->flareShader[0] ) { - ds->shaderInfo = ShaderInfoForShader( faceDs->shaderInfo->flareShader ); - } else { - ds->shaderInfo = ShaderInfoForShader( "flareshader" ); - } - ds->flareSurface = qtrue; - VectorCopy( faceDs->lightmapVecs[2], ds->lightmapVecs[2] ); - - // find midpoint - VectorClear( ds->lightmapOrigin ); - for ( i = 0 ; i < faceDs->numVerts ; i++ ) { - VectorAdd( ds->lightmapOrigin, faceDs->verts[i].xyz, ds->lightmapOrigin ); - } - VectorScale( ds->lightmapOrigin, 1.0/faceDs->numVerts, ds->lightmapOrigin ); - - VectorMA( ds->lightmapOrigin, 2, ds->lightmapVecs[2], ds->lightmapOrigin ); - - VectorCopy( faceDs->shaderInfo->color, ds->lightmapVecs[0] ); - - // FIXME: fog -} - -/* -===================== -FilterDrawsurfsIntoTree - -Upon completion, all drawsurfs that actually generate a reference -will have been emited to the bspfile arrays, and the references -will have valid final indexes -===================== -*/ -void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree ) { - int i; - mapDrawSurface_t *ds; - int refs; - int c_surfs, c_refs; - - qprintf( "----- FilterDrawsurfsIntoTree -----\n"); - - c_surfs = 0; - c_refs = 0; - for ( i = e->firstDrawSurf ; i < numMapDrawSurfs ; i++ ) { - ds = &mapDrawSurfs[i]; - - if ( !ds->numVerts && !ds->flareSurface ) { - continue; - } - if ( ds->miscModel ) { - refs = FilterMiscModelSurfIntoTree( ds, tree ); - EmitModelSurf( ds ); - } else if ( ds->patch ) { - refs = FilterPatchSurfIntoTree( ds, tree ); - EmitPatchSurf( ds ); - } else if ( ds->flareSurface ) { - refs = FilterFlareSurfIntoTree( ds, tree ); - EmitFlareSurf( ds ); - } else { - refs = FilterFaceIntoTree( ds, tree ); -// if ( ds->shaderInfo->value >= 1000 ) { // ds->shaderInfo->flareShader[0] ) { - if ( ds->shaderInfo->flareShader[0] ) { - CreateFlareSurface( ds ); - } - EmitPlanarSurf( ds ); - } - if ( refs > 0 ) { - c_surfs++; - c_refs += refs; - } - } - qprintf( "%5i emited drawsurfs\n", c_surfs ); - qprintf( "%5i references\n", c_refs ); - qprintf( "%5i stripfaces\n", c_stripSurfaces ); - qprintf( "%5i fanfaces\n", c_fanSurfaces ); -} - - - diff --git a/q3map/terrain.c b/q3map/terrain.c deleted file mode 100644 index 129ac08..0000000 --- a/q3map/terrain.c +++ /dev/null @@ -1,1255 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#include "qbsp.h" -#include <assert.h> - -#define SURF_WIDTH 2048 -#define SURF_HEIGHT 2048 - -#define GROW_VERTS 512 -#define GROW_INDICES 512 -#define GROW_SURFACES 128 - -#define VectorSet(v, x, y, z) v[0] = x;v[1] = y;v[2] = z; - -void QuakeTextureVecs( plane_t *plane, vec_t shift[2], vec_t rotate, vec_t scale[2], vec_t mappingVecs[2][4] ); - -typedef struct { - shaderInfo_t *shader; - int x, y; - - int maxVerts; - int numVerts; - drawVert_t *verts; - - int maxIndexes; - int numIndexes; - int *indexes; -} terrainSurf_t; - -static terrainSurf_t *surfaces = NULL; -static terrainSurf_t *lastSurface = NULL; -static int numsurfaces = 0; -static int maxsurfaces = 0; - -/* -================ -ShaderForLayer -================ -*/ -shaderInfo_t *ShaderForLayer( int minlayer, int maxlayer, const char *shadername ) { - char shader[ MAX_QPATH ]; - - if ( minlayer == maxlayer ) { - sprintf( shader, "textures/%s_%d", shadername, maxlayer ); - } else { - sprintf( shader, "textures/%s_%dto%d", shadername, minlayer, maxlayer ); - } - - return ShaderInfoForShader( shader ); -} - -/* -================ -CompareVert -================ -*/ -qboolean CompareVert( drawVert_t *v1, drawVert_t *v2, qboolean checkst ) { - int i; - - for( i = 0; i < 3; i++ ) { - if ( floor( v1->xyz[ i ] + 0.1 ) != floor( v2->xyz[ i ] + 0.1 ) ) { - return qfalse; - } - if ( checkst && ( ( v1->st[ 0 ] != v2->st[ 0 ] ) || ( v1->st[ 1 ] != v2->st[ 1 ] ) ) ) { - return qfalse; - } - } - - return qtrue; -} - -/* -================ -LoadAlphaMap -================ -*/ -byte *LoadAlphaMap( int *num_layers, int *alphawidth, int *alphaheight ) { - int *alphamap32; - byte *alphamap; - const char *alphamapname; - char ext[ 128 ]; - int width; - int height; - int layers; - int size; - int i; - - assert( alphawidth ); - assert( alphaheight ); - assert( num_layers ); - - layers = atoi( ValueForKey( mapent, "layers" ) ); - if ( layers < 1 ) { - Error ("SetTerrainTextures: invalid value for 'layers' (%d)", layers ); - } - - alphamapname = ValueForKey( mapent, "alphamap" ); - if ( !alphamapname[ 0 ] ) { - Error ("LoadAlphaMap: No alphamap specified on terrain" ); - } - - ExtractFileExtension( alphamapname, ext); - if ( !Q_stricmp( ext, "tga" ) ) { - Load32BitImage( ExpandGamePath( alphamapname ), &alphamap32, &width, &height ); - - size = width * height; - alphamap = malloc( size ); - for( i = 0; i < size; i++ ) { - alphamap[ i ] = ( ( alphamap32[ i ] & 0xff ) * layers ) / 256; - if ( alphamap[ i ] >= layers ) { - alphamap[ i ] = layers - 1; - } - } - } else { - Load256Image( ExpandGamePath( alphamapname ), &alphamap, NULL, &width, &height ); - size = width * height; - for( i = 0; i < size; i++ ) { - if ( alphamap[ i ] >= layers ) { - alphamap[ i ] = layers - 1; - } - } - } - - if ( ( width < 2 ) || ( height < 2 ) ) { - Error ("LoadAlphaMap: alphamap width/height must be at least 2x2." ); - } - - *num_layers = layers; - *alphawidth = width; - *alphaheight = height; - - return alphamap; -} - -/* -================ -CalcTerrainSize -================ -*/ -void CalcTerrainSize( vec3_t mins, vec3_t maxs, vec3_t size ) { - bspbrush_t *brush; - int i; - const char *key; - - // calculate the size of the terrain - ClearBounds( mins, maxs ); - for( brush = mapent->brushes; brush != NULL; brush = brush->next ) { - AddPointToBounds( brush->mins, mins, maxs ); - AddPointToBounds( brush->maxs, mins, maxs ); - } - - key = ValueForKey( mapent, "min" ); - if ( key[ 0 ] ) { - GetVectorForKey( mapent, "min", mins ); - } - - key = ValueForKey( mapent, "max" ); - if ( key[ 0 ] ) { - GetVectorForKey( mapent, "max", maxs ); - } - - for( i = 0; i < 3; i++ ) { - mins[ i ] = floor( mins[ i ] + 0.1 ); - maxs[ i ] = floor( maxs[ i ] + 0.1 ); - } - - VectorSubtract( maxs, mins, size ); - - if ( ( size[ 0 ] <= 0 ) || ( size[ 1 ] <= 0 ) ) { - Error ("CalcTerrainSize: Invalid terrain size: %fx%f", size[ 0 ], size[ 1 ] ); - } -} - -/* -================== -IsTriangleDegenerate - -Returns qtrue if all three points are collinear or backwards -=================== -*/ -#define COLINEAR_AREA 10 -static qboolean IsTriangleDegenerate( drawVert_t *points, int a, int b, int c ) { - vec3_t v1, v2, v3; - float d; - - VectorSubtract( points[b].xyz, points[a].xyz, v1 ); - VectorSubtract( points[c].xyz, points[a].xyz, v2 ); - CrossProduct( v1, v2, v3 ); - d = VectorLength( v3 ); - - // assume all very small or backwards triangles will cause problems - if ( d < COLINEAR_AREA ) { - return qtrue; - } - - return qfalse; -} - -/* -=============== -SideAsTriFan - -The surface can't be represented as a single tristrip without -leaving a degenerate triangle (and therefore a crack), so add -a point in the middle and create (points-1) triangles in fan order -=============== -*/ -static void SideAsTriFan( terrainSurf_t *surf, int *index, int num ) { - int i; - int colorSum[4]; - drawVert_t *mid, *v; - - // make sure we have enough space for a new vert - if ( surf->numVerts >= surf->maxVerts ) { - surf->maxVerts += GROW_VERTS; - surf->verts = realloc( surf->verts, surf->maxVerts * sizeof( *surf->verts ) ); - } - - // create a new point in the center of the face - mid = &surf->verts[ surf->numVerts ]; - surf->numVerts++; - - colorSum[0] = colorSum[1] = colorSum[2] = colorSum[3] = 0; - - for (i = 0 ; i < num; i++ ) { - v = &surf->verts[ index[ i ] ]; - VectorAdd( mid->xyz, v->xyz, mid->xyz ); - mid->st[0] += v->st[0]; - mid->st[1] += v->st[1]; - mid->lightmap[0] += v->lightmap[0]; - mid->lightmap[1] += v->lightmap[1]; - - colorSum[0] += v->color[0]; - colorSum[1] += v->color[1]; - colorSum[2] += v->color[2]; - colorSum[3] += v->color[3]; - } - - mid->xyz[0] /= num; - mid->xyz[1] /= num; - mid->xyz[2] /= num; - - mid->st[0] /= num; - mid->st[1] /= num; - - mid->lightmap[0] /= num; - mid->lightmap[1] /= num; - - mid->color[0] = colorSum[0] / num; - mid->color[1] = colorSum[1] / num; - mid->color[2] = colorSum[2] / num; - mid->color[3] = colorSum[3] / num; - - // fill in indices in trifan order - if ( surf->numIndexes + num * 3 > surf->maxIndexes ) { - surf->maxIndexes = surf->numIndexes + num * 3; - surf->indexes = realloc( surf->indexes, surf->maxIndexes * sizeof( *surf->indexes ) ); - } - - - for ( i = 0 ; i < num; i++ ) { - surf->indexes[ surf->numIndexes++ ] = surf->numVerts - 1; - surf->indexes[ surf->numIndexes++ ] = index[ i ]; - surf->indexes[ surf->numIndexes++ ] = index[ (i+1) % ( surf->numVerts - 1 ) ]; - } -} -/* -================ -SideAsTristrip - -Try to create indices that make (points-2) triangles in tristrip order -================ -*/ -#define MAX_INDICES 1024 -static void SideAsTristrip( terrainSurf_t *surf, int *index, int num ) { - int i; - int rotate; - int numIndices; - int ni; - int a, b, c; - int indices[ MAX_INDICES ]; - - // determine the triangle strip order - numIndices = ( num - 2 ) * 3; - if ( numIndices > MAX_INDICES ) { - Error( "MAX_INDICES exceeded for surface" ); - } - - // try all possible orderings of the points looking - // for a strip order that isn't degenerate - for ( rotate = 0 ; rotate < num; rotate++ ) { - for ( ni = 0, i = 0 ; i < num - 2 - i ; i++ ) { - a = index[ ( num - 1 - i + rotate ) % num ]; - b = index[ ( i + rotate ) % num ]; - c = index[ ( num - 2 - i + rotate ) % num ]; - - if ( IsTriangleDegenerate( surf->verts, a, b, c ) ) { - break; - } - indices[ni++] = a; - indices[ni++] = b; - indices[ni++] = c; - - if ( i + 1 != num - 1 - i ) { - a = index[ ( num - 2 - i + rotate ) % num ]; - b = index[ ( i + rotate ) % num ]; - c = index[ ( i + 1 + rotate ) % num ]; - - if ( IsTriangleDegenerate( surf->verts, a, b, c ) ) { - break; - } - indices[ni++] = a; - indices[ni++] = b; - indices[ni++] = c; - } - } - if ( ni == numIndices ) { - break; // got it done without degenerate triangles - } - } - - // if any triangle in the strip is degenerate, - // render from a centered fan point instead - if ( ni < numIndices ) { - SideAsTriFan( surf, index, num ); - return; - } - - // a normal tristrip - if ( surf->numIndexes + ni > surf->maxIndexes ) { - surf->maxIndexes = surf->numIndexes + ni; - surf->indexes = realloc( surf->indexes, surf->maxIndexes * sizeof( *surf->indexes ) ); - } - - memcpy( surf->indexes + surf->numIndexes, indices, ni * sizeof( *surf->indexes ) ); - surf->numIndexes += ni; -} - -/* -================ -CreateTerrainSurface -================ -*/ -void CreateTerrainSurface( terrainSurf_t *surf, shaderInfo_t *shader ) { - int i, j, k; - drawVert_t *out; - drawVert_t *in; - mapDrawSurface_t *newsurf; - - newsurf = AllocDrawSurf(); - - newsurf->miscModel = qtrue; - newsurf->shaderInfo = shader; - newsurf->lightmapNum = -1; - newsurf->fogNum = -1; - newsurf->numIndexes = surf->numIndexes; - newsurf->numVerts = surf->numVerts; - - // copy the indices - newsurf->indexes = malloc( surf->numIndexes * sizeof( *newsurf->indexes ) ); - memcpy( newsurf->indexes, surf->indexes, surf->numIndexes * sizeof( *newsurf->indexes ) ); - - // allocate the vertices - newsurf->verts = malloc( surf->numVerts * sizeof( *newsurf->verts ) ); - memset( newsurf->verts, 0, surf->numVerts * sizeof( *newsurf->verts ) ); - - // calculate the surface verts - out = newsurf->verts; - for( i = 0; i < newsurf->numVerts; i++, out++ ) { - VectorCopy( surf->verts[ i ].xyz, out->xyz ); - - // set the texture coordinates - out->st[ 0 ] = surf->verts[ i ].st[ 0 ]; - out->st[ 1 ] = surf->verts[ i ].st[ 1 ]; - - // the colors will be set by the lighting pass - out->color[0] = 255; - out->color[1] = 255; - out->color[2] = 255; - out->color[3] = surf->verts[ i ].color[ 3 ]; - - // calculate the vertex normal - VectorClear( out->normal ); - for( j = 0; j < numsurfaces; j++ ) { - in = surfaces[ j ].verts; - for( k = 0; k < surfaces[ j ].numVerts; k++, in++ ) { - if ( CompareVert( out, in, qfalse ) ) { - VectorAdd( out->normal, in->normal, out->normal ); - } - } - } - - VectorNormalize( out->normal, out->normal ); - } -} - -/* -================ -EmitTerrainVerts -================ -*/ -void EmitTerrainVerts( side_t *side, terrainSurf_t *surf, int maxlayer, int alpha[ MAX_POINTS_ON_WINDING ], qboolean projecttexture ) { - int i; - int j; - drawVert_t *vert; - int *indices; - int numindices; - int maxindices; - int xyplane; - vec3_t xynorm = { 0, 0, 1 }; - vec_t shift[ 2 ] = { 0, 0 }; - vec_t scale[ 2 ] = { 0.5, 0.5 }; - float vecs[ 2 ][ 4 ]; - static int numtimes = 0; - - numtimes++; - - if ( !surf->verts ) { - surf->numVerts = 0; - surf->maxVerts = GROW_VERTS; - surf->verts = malloc( surf->maxVerts * sizeof( *surf->verts ) ); - - surf->numIndexes = 0; - surf->maxIndexes = GROW_INDICES; - surf->indexes = malloc( surf->maxIndexes * sizeof( *surf->indexes ) ); - } - - // calculate the texture coordinate vectors - xyplane = FindFloatPlane( xynorm, 0 ); - QuakeTextureVecs( &mapplanes[ xyplane ], shift, 0, scale, vecs ); - - // emit the vertexes - numindices = 0; - maxindices = surf->maxIndexes; - indices = malloc ( maxindices * sizeof( *indices ) ); - - for ( i = 0; i < side->winding->numpoints; i++ ) { - vert = &surf->verts[ surf->numVerts ]; - - // set the final alpha value--0 for texture 1, 255 for texture 2 - if ( alpha[ i ] < maxlayer ) { - vert->color[3] = 0; - } else { - vert->color[3] = 255; - } - - vert->xyz[ 0 ] = floor( side->winding->p[ i ][ 0 ] + 0.1f ); - vert->xyz[ 1 ] = floor( side->winding->p[ i ][ 1 ] + 0.1f ); - vert->xyz[ 2 ] = floor( side->winding->p[ i ][ 2 ] + 0.1f ); - - // set the texture coordinates - if ( projecttexture ) { - vert->st[0] = ( vecs[0][3] + DotProduct( vecs[ 0 ], vert->xyz ) ) / surf->shader->width; - vert->st[1] = ( vecs[1][3] + DotProduct( vecs[ 1 ], vert->xyz ) ) / surf->shader->height; - } else { - vert->st[0] = ( side->vecs[0][3] + DotProduct( side->vecs[ 0 ], vert->xyz ) ) / surf->shader->width; - vert->st[1] = ( side->vecs[1][3] + DotProduct( side->vecs[ 1 ], vert->xyz ) ) / surf->shader->height; - } - - VectorCopy( mapplanes[ side->planenum ].normal, vert->normal ); - - for( j = 0; j < surf->numVerts; j++ ) { - if ( CompareVert( vert, &surf->verts[ j ], qtrue ) ) { - break; - } - } - - if ( numindices >= maxindices ) { - maxindices += GROW_INDICES; - indices = realloc( indices, maxindices * sizeof( *indices ) ); - } - - if ( j != surf->numVerts ) { - indices[ numindices++ ] = j; - } else { - indices[ numindices++ ] = surf->numVerts; - surf->numVerts++; - if ( surf->numVerts >= surf->maxVerts ) { - surf->maxVerts += GROW_VERTS; - surf->verts = realloc( surf->verts, surf->maxVerts * sizeof( *surf->verts ) ); - } - } - } - - SideAsTristrip( surf, indices, numindices ); - - free( indices ); -} - -/* -================ -SurfaceForShader -================ -*/ -terrainSurf_t *SurfaceForShader( shaderInfo_t *shader, int x, int y ) { - int i; - - if ( lastSurface && ( lastSurface->shader == shader ) && ( lastSurface->x == x ) && ( lastSurface->y == y ) ) { - return lastSurface; - } - - lastSurface = surfaces; - for( i = 0; i < numsurfaces; i++, lastSurface++ ) { - if ( ( lastSurface->shader == shader ) && ( lastSurface->x == x ) && ( lastSurface->y == y ) ) { - return lastSurface; - } - } - - if ( numsurfaces >= maxsurfaces ) { - maxsurfaces += GROW_SURFACES; - surfaces = realloc( surfaces, maxsurfaces * sizeof( *surfaces ) ); - memset( surfaces + numsurfaces + 1, 0, ( maxsurfaces - numsurfaces - 1 ) * sizeof( *surfaces ) ); - } - - lastSurface= &surfaces[ numsurfaces++ ]; - lastSurface->shader = shader; - lastSurface->x = x; - lastSurface->y = y; - - return lastSurface; -} - -/* -================ -SetTerrainTextures -================ -*/ -void SetTerrainTextures( void ) { - int i; - int x, y; - int layer; - int minlayer, maxlayer; - float s, t; - float min_s, min_t; - int alpha[ MAX_POINTS_ON_WINDING ]; - shaderInfo_t *si, *terrainShader; - bspbrush_t *brush; - side_t *side; - const char *shadername; - vec3_t mins, maxs; - vec3_t size; - int surfwidth, surfheight, surfsize; - terrainSurf_t *surf; - byte *alphamap; - int alphawidth, alphaheight; - int num_layers; - extern qboolean onlyents; - - if ( onlyents ) { - return; - } - - shadername = ValueForKey( mapent, "shader" ); - if ( !shadername[ 0 ] ) { - Error ("SetTerrainTextures: shader not specified" ); - } - - alphamap = LoadAlphaMap( &num_layers, &alphawidth, &alphaheight ); - - mapent->firstDrawSurf = numMapDrawSurfs; - - // calculate the size of the terrain - CalcTerrainSize( mins, maxs, size ); - - surfwidth = ( size[ 0 ] + SURF_WIDTH - 1 ) / SURF_WIDTH; - surfheight = ( size[ 1 ] + SURF_HEIGHT - 1 ) / SURF_HEIGHT; - surfsize = surfwidth * surfheight; - - lastSurface = NULL; - numsurfaces = 0; - maxsurfaces = 0; - for( i = num_layers; i > 0; i-- ) { - maxsurfaces += i * surfsize; - } - surfaces = malloc( maxsurfaces * sizeof( *surfaces ) ); - memset( surfaces, 0, maxsurfaces * sizeof( *surfaces ) ); - - terrainShader = ShaderInfoForShader( "textures/common/terrain" ); - - for( brush = mapent->brushes; brush != NULL; brush = brush->next ) { - // only create surfaces for sides marked as terrain - for( side = brush->sides; side < &brush->sides[ brush->numsides ]; side++ ) { - if ( !side->shaderInfo ) { - continue; - } - - if ( ( ( side->surfaceFlags | side->shaderInfo->surfaceFlags ) & SURF_NODRAW ) && !strstr( side->shaderInfo->shader, "terrain" ) ) { - continue; - } - - minlayer = num_layers; - maxlayer = 0; - - // project each point of the winding onto the alphamap to determine which - // textures to blend - min_s = 1.0; - min_t = 1.0; - for( i = 0; i < side->winding->numpoints; i++ ) { - s = floor( side->winding->p[ i ][ 0 ] + 0.1f - mins[ 0 ] ) / size[ 0 ]; - t = floor( side->winding->p[ i ][ 1 ] + 0.1f - mins[ 0 ] ) / size[ 1 ]; - - if ( s < 0 ) { - s = 0; - } - - if ( t < 0 ) { - t = 0; - } - - if ( s >= 1.0 ) { - s = 1.0; - } - - if ( t >= 1.0 ) { - t = 1.0; - } - - if ( s < min_s ) { - min_s = s; - } - - if ( t < min_t ) { - min_t = t; - } - - x = ( alphawidth - 1 ) * s; - y = ( alphaheight - 1 ) * t; - - layer = alphamap[ x + y * alphawidth ]; - if ( layer < minlayer ) { - minlayer = layer; - } - - if ( layer > maxlayer ) { - maxlayer = layer; - } - - alpha[ i ] = layer; - } - - x = min_s * surfwidth; - if ( x >= surfwidth ) { - x = surfwidth - 1; - } - - y = min_t * surfheight; - if ( y >= surfheight ) { - y = surfheight - 1; - } - - if ( strstr( side->shaderInfo->shader, "terrain" ) ) { - si = ShaderForLayer( minlayer, maxlayer, shadername ); - if ( showseams ) { - for( i = 0; i < side->winding->numpoints; i++ ) { - if ( ( alpha[ i ] != minlayer ) && ( alpha[ i ] != maxlayer ) ) { - si = ShaderInfoForShader( "textures/common/white" ); - break; - } - } - } - surf = SurfaceForShader( si, x, y ); - EmitTerrainVerts( side, surf, maxlayer, alpha, qtrue ); - } else { - si = side->shaderInfo; - side->shaderInfo = terrainShader; - surf = SurfaceForShader( si, x, y ); - EmitTerrainVerts( side, surf, maxlayer, alpha, qfalse ); - } - } - } - - // create the final surfaces - for( surf = surfaces, i = 0; i < numsurfaces; i++, surf++ ) { - if ( surf->numVerts ) { - CreateTerrainSurface( surf, surf->shader ); - } - } - - // - // clean up any allocated memory - // - for( surf = surfaces, i = 0; i < numsurfaces; i++, surf++ ) { - if ( surf->verts ) { - free( surf->verts ); - free( surf->indexes ); - } - } - free( alphamap ); - free( surfaces ); - - surfaces = NULL; - lastSurface = NULL; - numsurfaces = 0; - maxsurfaces = 0; -} - -/***************************************************************************** - - New terrain code - -******************************************************************************/ - -typedef struct terrainFace_s { - shaderInfo_t *shaderInfo; - //texdef_t texdef; - - float vecs[ 2 ][ 4 ]; // texture coordinate mapping -} terrainFace_t; - -typedef struct terrainVert_s { - vec3_t xyz; - terrainFace_t tri; -} terrainVert_t; - -typedef struct terrainMesh_s { - float scale_x; - float scale_y; - vec3_t origin; - - int width, height; - terrainVert_t *map; -} terrainMesh_t; - -terrainVert_t *Terrain_GetVert( terrainMesh_t *pm, int x, int y ) { - return &pm->map[ x + y * pm->width ]; -} - -void Terrain_GetTriangles( terrainMesh_t *pm, int x, int y, terrainVert_t **verts ) { - if ( ( x + y ) & 1 ) { - // first tri - verts[ 0 ] = Terrain_GetVert( pm, x, y ); - verts[ 1 ] = Terrain_GetVert( pm, x, y + 1 ); - verts[ 2 ] = Terrain_GetVert( pm, x + 1, y + 1 ); - - // second tri - verts[ 3 ] = verts[ 2 ]; - verts[ 4 ] = Terrain_GetVert( pm, x + 1, y ); - verts[ 5 ] = verts[ 0 ]; - } else { - // first tri - verts[ 0 ] = Terrain_GetVert( pm, x, y ); - verts[ 1 ] = Terrain_GetVert( pm, x, y + 1 ); - verts[ 2 ] = Terrain_GetVert( pm, x + 1, y ); - - // second tri - verts[ 3 ] = verts[ 2 ]; - verts[ 4 ] = verts[ 1 ]; - verts[ 5 ] = Terrain_GetVert( pm, x + 1, y + 1 ); - } -} - -/* -================ -EmitTerrainVerts2 -================ -*/ -void EmitTerrainVerts2( terrainSurf_t *surf, terrainVert_t **verts, int alpha[ 3 ] ) { - int i; - int j; - drawVert_t *vert; - int *indices; - int numindices; - int maxindices; - int xyplane; - vec3_t xynorm = { 0, 0, 1 }; - vec_t shift[ 2 ] = { 0, 0 }; - vec_t scale[ 2 ] = { 0.5, 0.5 }; - float vecs[ 2 ][ 4 ]; - vec4_t plane; - - if ( !surf->verts ) { - surf->numVerts = 0; - surf->maxVerts = GROW_VERTS; - surf->verts = malloc( surf->maxVerts * sizeof( *surf->verts ) ); - - surf->numIndexes = 0; - surf->maxIndexes = GROW_INDICES; - surf->indexes = malloc( surf->maxIndexes * sizeof( *surf->indexes ) ); - } - - // calculate the texture coordinate vectors - xyplane = FindFloatPlane( xynorm, 0 ); - QuakeTextureVecs( &mapplanes[ xyplane ], shift, 0, scale, vecs ); - - // emit the vertexes - numindices = 0; - maxindices = surf->maxIndexes; - assert( maxindices >= 0 ); - indices = malloc ( maxindices * sizeof( *indices ) ); - - PlaneFromPoints( plane, verts[ 0 ]->xyz, verts[ 1 ]->xyz, verts[ 2 ]->xyz ); - - for ( i = 0; i < 3; i++ ) { - vert = &surf->verts[ surf->numVerts ]; - - if ( alpha[ i ] ) { - vert->color[3] = 255; - } else { - vert->color[3] = 0; - } - - vert->xyz[ 0 ] = floor( verts[ i ]->xyz[ 0 ] + 0.1f ); - vert->xyz[ 1 ] = floor( verts[ i ]->xyz[ 1 ] + 0.1f ); - vert->xyz[ 2 ] = floor( verts[ i ]->xyz[ 2 ] + 0.1f ); - - // set the texture coordinates - vert->st[0] = ( vecs[0][3] + DotProduct( vecs[ 0 ], vert->xyz ) ) / surf->shader->width; - vert->st[1] = ( vecs[1][3] + DotProduct( vecs[ 1 ], vert->xyz ) ) / surf->shader->height; - - VectorCopy( plane, vert->normal ); - - for( j = 0; j < surf->numVerts; j++ ) { - if ( CompareVert( vert, &surf->verts[ j ], qtrue ) ) { - break; - } - } - - if ( numindices >= maxindices ) { - maxindices += GROW_INDICES; - indices = realloc( indices, maxindices * sizeof( *indices ) ); - } - - if ( j != surf->numVerts ) { - indices[ numindices++ ] = j; - } else { - indices[ numindices++ ] = surf->numVerts; - surf->numVerts++; - if ( surf->numVerts >= surf->maxVerts ) { - surf->maxVerts += GROW_VERTS; - surf->verts = realloc( surf->verts, surf->maxVerts * sizeof( *surf->verts ) ); - } - } - } - - SideAsTristrip( surf, indices, numindices ); - - free( indices ); -} - -int MapPlaneFromPoints( vec3_t p0, vec3_t p1, vec3_t p2 ); -void QuakeTextureVecs( plane_t *plane, vec_t shift[2], vec_t rotate, vec_t scale[2], vec_t mappingVecs[2][4] ); -qboolean RemoveDuplicateBrushPlanes( bspbrush_t *b ); -void SetBrushContents( bspbrush_t *b ); - -void AddBrushSide( vec3_t v1, vec3_t v2, vec3_t v3, shaderInfo_t *terrainShader ) { - side_t *side; - int planenum; - - side = &buildBrush->sides[ buildBrush->numsides ]; - memset( side, 0, sizeof( *side ) ); - buildBrush->numsides++; - - side->shaderInfo = terrainShader; - - // find the plane number - planenum = MapPlaneFromPoints( v1, v2, v3 ); - side->planenum = planenum; -} - -void MakeBrushFromTriangle( vec3_t v1, vec3_t v2, vec3_t v3, shaderInfo_t *terrainShader ) { - bspbrush_t *b; - vec3_t d1; - vec3_t d2; - vec3_t d3; - - VectorSet( d1, v1[ 0 ], v1[ 1 ], MIN_WORLD_COORD + 10 ); //FIXME - VectorSet( d2, v2[ 0 ], v2[ 1 ], MIN_WORLD_COORD + 10 ); - VectorSet( d3, v3[ 0 ], v3[ 1 ], MIN_WORLD_COORD + 10 ); - - buildBrush->numsides = 0; - buildBrush->detail = qfalse; - - AddBrushSide( v1, v2, v3, terrainShader ); - AddBrushSide( v1, d1, v2, terrainShader ); - AddBrushSide( v2, d2, v3, terrainShader ); - AddBrushSide( v3, d3, v1, terrainShader ); - AddBrushSide( d3, d2, d1, terrainShader ); - - buildBrush->portalareas[0] = -1; - buildBrush->portalareas[1] = -1; - buildBrush->entitynum = num_entities-1; - buildBrush->brushnum = entitySourceBrushes; - - // if there are mirrored planes, the entire brush is invalid - if ( !RemoveDuplicateBrushPlanes( buildBrush ) ) { - return; - } - - // get the content for the entire brush - SetBrushContents( buildBrush ); - buildBrush->contents |= CONTENTS_DETAIL; - - b = FinishBrush(); - if ( !b ) { - return; - } -} - -void MakeTerrainIntoBrushes( terrainMesh_t *tm ) { - int index[ 6 ]; - int y; - int x; - terrainVert_t *verts; - shaderInfo_t *terrainShader; - - terrainShader = ShaderInfoForShader( "textures/common/terrain" ); - - verts = tm->map; - for( y = 0; y < tm->height - 1; y++ ) { - for( x = 0; x < tm->width - 1; x++ ) { - if ( ( x + y ) & 1 ) { - // first tri - index[ 0 ] = x + y * tm->width; - index[ 1 ] = x + ( y + 1 ) * tm->width; - index[ 2 ] = ( x + 1 ) + ( y + 1 ) * tm->width; - index[ 3 ] = ( x + 1 ) + ( y + 1 ) * tm->width; - index[ 4 ] = ( x + 1 ) + y * tm->width; - index[ 5 ] = x + y * tm->width; - } else { - // first tri - index[ 0 ] = x + y * tm->width; - index[ 1 ] = x + ( y + 1 ) * tm->width; - index[ 2 ] = ( x + 1 ) + y * tm->width; - index[ 3 ] = ( x + 1 ) + y * tm->width; - index[ 4 ] = x + ( y + 1 ) * tm->width; - index[ 5 ] = ( x + 1 ) + ( y + 1 ) * tm->width; - } - - MakeBrushFromTriangle( verts[ index[ 0 ] ].xyz, verts[ index[ 1 ] ].xyz, verts[ index[ 2 ] ].xyz, terrainShader ); - MakeBrushFromTriangle( verts[ index[ 3 ] ].xyz, verts[ index[ 4 ] ].xyz, verts[ index[ 5 ] ].xyz, terrainShader ); - } - } -} - -void Terrain_ParseFace( terrainFace_t *face ) { - shaderInfo_t *si; - vec_t shift[ 2 ]; - vec_t rotate; - vec_t scale[ 2 ]; - char name[ MAX_QPATH ]; - char shader[ MAX_QPATH ]; - plane_t p; - - // read the texturedef - GetToken( qfalse ); - strcpy( name, token ); - - GetToken( qfalse ); - shift[ 0 ] = atof(token); - GetToken( qfalse ); - shift[ 1 ] = atof( token ); - GetToken( qfalse ); - rotate = atof( token ); - GetToken( qfalse ); - scale[ 0 ] = atof( token ); - GetToken( qfalse ); - scale[ 1 ] = atof( token ); - - // find default flags and values - sprintf( shader, "textures/%s", name ); - si = ShaderInfoForShader( shader ); - face->shaderInfo = si; - //face->texdef = si->texdef; - - // skip over old contents - GetToken( qfalse ); - - // skip over old flags - GetToken( qfalse ); - - // skip over old value - GetToken( qfalse ); - - //Surface_Parse( &face->texdef ); - //Surface_BuildTexdef( &face->texdef ); - - // make a fake horizontal plane - VectorSet( p.normal, 0, 0, 1 ); - p.dist = 0; - p.type = PlaneTypeForNormal( p.normal ); - - QuakeTextureVecs( &p, shift, rotate, scale, face->vecs ); -} - -#define MAX_TERRAIN_TEXTURES 128 -static int numtextures = 0;; -static shaderInfo_t *textures[ MAX_TERRAIN_TEXTURES ]; - -void Terrain_AddTexture( shaderInfo_t *texture ) { - int i; - - if ( !texture ) { - return; - } - - for( i = 0; i < numtextures; i++ ) { - if ( textures[ i ] == texture ) { - return; - } - } - - if ( numtextures >= MAX_TERRAIN_TEXTURES ) { - Error( "Too many textures on terrain" ); - return; - } - - textures[ numtextures++ ] = texture; -} - -int LayerForShader( shaderInfo_t *shader ) { - int i; - int l; - - l = strlen( shader->shader ); - for( i = l - 1; i >= 0; i-- ) { - if ( shader->shader[ i ] == '_' ) { - return atoi( &shader->shader[ i + 1 ] ); - break; - } - } - - return 0; -} - -/* -================= -ParseTerrain - -Creates a mapDrawSurface_t from the terrain text -================= -*/ - -void ParseTerrain( void ) { - int i, j; - int x, y; - int x1, y1; - terrainMesh_t t; - int index; - terrainVert_t *verts[ 6 ]; - int num_layers; - int layer, minlayer, maxlayer; - int alpha[ 6 ]; - shaderInfo_t *si, *terrainShader; - int surfwidth, surfheight, surfsize; - terrainSurf_t *surf; - char shadername[ MAX_QPATH ]; - - mapent->firstDrawSurf = numMapDrawSurfs; - - memset( &t, 0, sizeof( t ) ); - - MatchToken( "{" ); - - // get width - GetToken( qtrue ); - t.width = atoi( token ); - - // get height - GetToken( qfalse ); - t.height = atoi( token ); - - // get scale_x - GetToken( qfalse ); - t.scale_x = atof( token ); - - // get scale_y - GetToken( qfalse ); - t.scale_y = atof( token ); - - // get origin - GetToken( qtrue ); - t.origin[ 0 ] = atof( token ); - GetToken( qfalse ); - t.origin[ 1 ] = atof( token ); - GetToken( qfalse ); - t.origin[ 2 ] = atof( token ); - - t.map = malloc( t.width * t.height * sizeof( t.map[ 0 ] ) ); - - if ( t.width <= 0 || t.height <= 0 ) { - Error( "ParseTerrain: bad size" ); - } - - numtextures = 0; - index = 0; - for ( i = 0; i < t.height; i++ ) { - for( j = 0; j < t.width; j++, index++ ) { - // get height - GetToken( qtrue ); - t.map[ index ].xyz[ 0 ] = t.origin[ 0 ] + t.scale_x * ( float )j; - t.map[ index ].xyz[ 1 ] = t.origin[ 1 ] + t.scale_y * ( float )i; - t.map[ index ].xyz[ 2 ] = t.origin[ 2 ] + atof( token ); - - Terrain_ParseFace( &t.map[ index ].tri ); - Terrain_AddTexture( t.map[ index ].tri.shaderInfo ); - } - } - - MatchToken( "}" ); - MatchToken( "}" ); - - MakeTerrainIntoBrushes( &t ); - - surfwidth = ( ( t.scale_x * t.width ) + SURF_WIDTH - 1 ) / SURF_WIDTH; - surfheight = ( ( t.scale_y * t.height ) + SURF_HEIGHT - 1 ) / SURF_HEIGHT; - surfsize = surfwidth * surfheight; - - //FIXME - num_layers = 0; - for( i = 0; i < numtextures; i++ ) { - layer = LayerForShader( textures[ i ] ) + 1; - if ( layer > num_layers ) { - num_layers = layer; - } - } - num_layers = 4; - - memset( alpha, 0, sizeof( alpha ) ); - - lastSurface = NULL; - numsurfaces = 0; - maxsurfaces = 0; - for( i = num_layers; i > 0; i-- ) { - maxsurfaces += i * surfsize; - } - - surfaces = malloc( maxsurfaces * sizeof( *surfaces ) ); - memset( surfaces, 0, maxsurfaces * sizeof( *surfaces ) ); - - terrainShader = ShaderInfoForShader( "textures/common/terrain" ); - - // get the shadername - if ( Q_strncasecmp( textures[ 0 ]->shader, "textures/", 9 ) == 0 ) { - strcpy( shadername, &textures[ 0 ]->shader[ 9 ] ); - } else { - strcpy( shadername, textures[ 0 ]->shader ); - } - j = strlen( shadername ); - for( i = j - 1; i >= 0; i-- ) { - if ( shadername[ i ] == '_' ) { - shadername[ i ] = 0; - break; - } - } - - for( y = 0; y < t.height - 1; y++ ) { - for( x = 0; x < t.width - 1; x++ ) { - Terrain_GetTriangles( &t, x, y, verts ); - - x1 = ( ( float )x / ( float )( t.width - 1 ) ) * surfwidth; - if ( x1 >= surfwidth ) { - x1 = surfwidth - 1; - } - - y1 = ( ( float )y / ( float )( t.height - 1 ) ) * surfheight; - if ( y1 >= surfheight ) { - y1 = surfheight - 1; - } - - maxlayer = minlayer = LayerForShader( verts[ 0 ]->tri.shaderInfo ); - for( i = 0; i < 3; i++ ) { - layer = LayerForShader( verts[ i ]->tri.shaderInfo ); - if ( layer < minlayer ) { - minlayer = layer; - } - if ( layer > maxlayer ) { - maxlayer = layer; - } - } - - for( i = 0; i < 3; i++ ) { - layer = LayerForShader( verts[ i ]->tri.shaderInfo ); - if ( layer > minlayer ) { - alpha[ i ] = 1.0f; - } else { - alpha[ i ] = 0.0f; - } - } - - si = ShaderForLayer( minlayer, maxlayer, shadername ); - surf = SurfaceForShader( si, x1, y1 ); - EmitTerrainVerts2( surf, &verts[ 0 ], &alpha[ 0 ] ); - - // second triangle - maxlayer = minlayer = LayerForShader( verts[ 3 ]->tri.shaderInfo ); - for( i = 3; i < 6; i++ ) { - layer = LayerForShader( verts[ i ]->tri.shaderInfo ); - if ( layer < minlayer ) { - minlayer = layer; - } - if ( layer > maxlayer ) { - maxlayer = layer; - } - } - - for( i = 3; i < 6; i++ ) { - layer = LayerForShader( verts[ i ]->tri.shaderInfo ); - if ( layer > minlayer ) { - alpha[ i ] = 1.0f; - } else { - alpha[ i ] = 0.0f; - } - } - - si = ShaderForLayer( minlayer, maxlayer, shadername ); - surf = SurfaceForShader( si, x1, y1 ); - EmitTerrainVerts2( surf, &verts[ 3 ], &alpha[ 3 ] ); - } - } - - // create the final surfaces - for( surf = surfaces, i = 0; i < numsurfaces; i++, surf++ ) { - if ( surf->numVerts ) { - CreateTerrainSurface( surf, surf->shader ); - } - } - - // - // clean up any allocated memory - // - for( surf = surfaces, i = 0; i < numsurfaces; i++, surf++ ) { - if ( surf->verts ) { - free( surf->verts ); - free( surf->indexes ); - } - } - free( surfaces ); - - surfaces = NULL; - lastSurface = NULL; - numsurfaces = 0; - maxsurfaces = 0; - - free( t.map ); -} - diff --git a/q3map/tjunction.c b/q3map/tjunction.c deleted file mode 100644 index a1acabe..0000000 --- a/q3map/tjunction.c +++ /dev/null @@ -1,551 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#include "qbsp.h" - -typedef struct edgePoint_s { - float intercept; - vec3_t xyz; - struct edgePoint_s *prev, *next; -} edgePoint_t; - -typedef struct edgeLine_s { - vec3_t normal1; - float dist1; - - vec3_t normal2; - float dist2; - - vec3_t origin; - vec3_t dir; - - edgePoint_t chain; // unused element of doubly linked list -} edgeLine_t; - -typedef struct { - float length; - drawVert_t *dv[2]; -} originalEdge_t; - -#define MAX_ORIGINAL_EDGES 0x10000 -originalEdge_t originalEdges[MAX_ORIGINAL_EDGES]; -int numOriginalEdges; - - -#define MAX_EDGE_LINES 0x10000 -edgeLine_t edgeLines[MAX_EDGE_LINES]; -int numEdgeLines; - -int c_degenerateEdges; -int c_addedVerts; -int c_totalVerts; - -int c_natural, c_rotate, c_cant; - -// these should be whatever epsilon we actually expect, -// plus SNAP_INT_TO_FLOAT -#define LINE_POSITION_EPSILON 0.25 -#define POINT_ON_LINE_EPSILON 0.25 - -/* -==================== -InsertPointOnEdge -==================== -*/ -void InsertPointOnEdge( vec3_t v, edgeLine_t *e ) { - vec3_t delta; - float d; - edgePoint_t *p, *scan; - - VectorSubtract( v, e->origin, delta ); - d = DotProduct( delta, e->dir ); - - p = malloc( sizeof(edgePoint_t) ); - p->intercept = d; - VectorCopy( v, p->xyz ); - - if ( e->chain.next == &e->chain ) { - e->chain.next = e->chain.prev = p; - p->next = p->prev = &e->chain; - return; - } - - scan = e->chain.next; - for ( ; scan != &e->chain ; scan = scan->next ) { - d = p->intercept - scan->intercept; - if ( d > -LINE_POSITION_EPSILON && d < LINE_POSITION_EPSILON ) { - free( p ); - return; // the point is already set - } - - if ( p->intercept < scan->intercept ) { - // insert here - p->prev = scan->prev; - p->next = scan; - scan->prev->next = p; - scan->prev = p; - return; - } - } - - // add at the end - p->prev = scan->prev; - p->next = scan; - scan->prev->next = p; - scan->prev = p; -} - - -/* -==================== -AddEdge -==================== -*/ -int AddEdge( vec3_t v1, vec3_t v2, qboolean createNonAxial ) { - int i; - edgeLine_t *e; - float d; - vec3_t dir; - - VectorSubtract( v2, v1, dir ); - d = VectorNormalize( dir, dir ); - if ( d < 0.1 ) { - // if we added a 0 length vector, it would make degenerate planes - c_degenerateEdges++; - return -1; - } - - if ( !createNonAxial ) { - if ( fabs( dir[0] + dir[1] + dir[2] ) != 1.0 ) { - if ( numOriginalEdges == MAX_ORIGINAL_EDGES ) { - Error( "MAX_ORIGINAL_EDGES" ); - } - originalEdges[ numOriginalEdges ].dv[0] = (drawVert_t *)v1; - originalEdges[ numOriginalEdges ].dv[1] = (drawVert_t *)v2; - originalEdges[ numOriginalEdges ].length = d; - numOriginalEdges++; - return -1; - } - } - - for ( i = 0 ; i < numEdgeLines ; i++ ) { - e = &edgeLines[i]; - - d = DotProduct( v1, e->normal1 ) - e->dist1; - if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) { - continue; - } - d = DotProduct( v1, e->normal2 ) - e->dist2; - if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) { - continue; - } - - d = DotProduct( v2, e->normal1 ) - e->dist1; - if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) { - continue; - } - d = DotProduct( v2, e->normal2 ) - e->dist2; - if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) { - continue; - } - - // this is the edge - InsertPointOnEdge( v1, e ); - InsertPointOnEdge( v2, e ); - return i; - } - - // create a new edge - if ( numEdgeLines >= MAX_EDGE_LINES ) { - Error( "MAX_EDGE_LINES" ); - } - - e = &edgeLines[ numEdgeLines ]; - numEdgeLines++; - - e->chain.next = e->chain.prev = &e->chain; - - VectorCopy( v1, e->origin ); - VectorCopy( dir, e->dir ); - - MakeNormalVectors( e->dir, e->normal1, e->normal2 ); - e->dist1 = DotProduct( e->origin, e->normal1 ); - e->dist2 = DotProduct( e->origin, e->normal2 ); - - InsertPointOnEdge( v1, e ); - InsertPointOnEdge( v2, e ); - - return numEdgeLines - 1; -} - -/* -==================== -AddSurfaceEdges -==================== -*/ -void AddSurfaceEdges( mapDrawSurface_t *ds ) { - int i; - - for ( i = 0 ; i < ds->numVerts ; i++ ) { - // save the edge number in the lightmap field - // so we don't need to look it up again - ds->verts[i].lightmap[0] = - AddEdge( ds->verts[i].xyz, ds->verts[(i+1) % ds->numVerts].xyz, qfalse ); - } -} - -/* -================ -ColinearEdge -================ -*/ -qboolean ColinearEdge( vec3_t v1, vec3_t v2, vec3_t v3 ) { - vec3_t midpoint, dir, offset, on; - float d; - - VectorSubtract( v2, v1, midpoint ); - VectorSubtract( v3, v1, dir ); - d = VectorNormalize( dir, dir ); - if ( d == 0 ) { - return qfalse; // degenerate - } - - d = DotProduct( midpoint, dir ); - VectorScale( dir, d, on ); - VectorSubtract( midpoint, on, offset ); - d = VectorLength ( offset ); - - if ( d < 0.1 ) { - return qtrue; - } - - return qfalse; -} - -/* -==================== -AddPatchEdges - -Add colinear border edges, which will fix some classes of patch to -brush tjunctions -==================== -*/ -void AddPatchEdges( mapDrawSurface_t *ds ) { - int i; - float *v1, *v2, *v3; - - for ( i = 0 ; i < ds->patchWidth - 2; i+=2 ) { - v1 = ds->verts[ i ].xyz; - v2 = ds->verts[ i + 1 ].xyz; - v3 = ds->verts[ i + 2 ].xyz; - - // if v2 is the midpoint of v1 to v3, add an edge from v1 to v3 - if ( ColinearEdge( v1, v2, v3 ) ) { - AddEdge( v1, v3, qfalse ); - } - - v1 = ds->verts[ ( ds->patchHeight - 1 ) * ds->patchWidth + i ].xyz; - v2 = ds->verts[ ( ds->patchHeight - 1 ) * ds->patchWidth + i + 1 ].xyz; - v3 = ds->verts[ ( ds->patchHeight - 1 ) * ds->patchWidth + i + 2 ].xyz; - - // if v2 is on the v1 to v3 line, add an edge from v1 to v3 - if ( ColinearEdge( v1, v2, v3 ) ) { - AddEdge( v1, v3, qfalse ); - } - } - - for ( i = 0 ; i < ds->patchHeight - 2 ; i+=2 ) { - v1 = ds->verts[ i * ds->patchWidth ].xyz; - v2 = ds->verts[ ( i + 1 ) * ds->patchWidth ].xyz; - v3 = ds->verts[ ( i + 2 ) * ds->patchWidth ].xyz; - - // if v2 is the midpoint of v1 to v3, add an edge from v1 to v3 - if ( ColinearEdge( v1, v2, v3 ) ) { - AddEdge( v1, v3, qfalse ); - } - - v1 = ds->verts[ ( ds->patchWidth - 1 ) + i * ds->patchWidth ].xyz; - v2 = ds->verts[ ( ds->patchWidth - 1 ) + ( i + 1 ) * ds->patchWidth ].xyz; - v3 = ds->verts[ ( ds->patchWidth - 1 ) + ( i + 2 ) * ds->patchWidth ].xyz; - - // if v2 is the midpoint of v1 to v3, add an edge from v1 to v3 - if ( ColinearEdge( v1, v2, v3 ) ) { - AddEdge( v1, v3, qfalse ); - } - } - - -} - - -/* -==================== -FixSurfaceJunctions -==================== -*/ -#define MAX_SURFACE_VERTS 256 -void FixSurfaceJunctions( mapDrawSurface_t *ds ) { - int i, j, k; - edgeLine_t *e; - edgePoint_t *p; - int originalVerts; - int counts[MAX_SURFACE_VERTS]; - int originals[MAX_SURFACE_VERTS]; - int firstVert[MAX_SURFACE_VERTS]; - drawVert_t verts[MAX_SURFACE_VERTS], *v1, *v2; - int numVerts; - float start, end, frac; - vec3_t delta; - - originalVerts = ds->numVerts; - - numVerts = 0; - for ( i = 0 ; i < ds->numVerts ; i++ ) { - counts[i] = 0; - firstVert[i] = numVerts; - - // copy first vert - if ( numVerts == MAX_SURFACE_VERTS ) { - Error( "MAX_SURFACE_VERTS" ); - } - verts[numVerts] = ds->verts[i]; - originals[numVerts] = i; - numVerts++; - - // check to see if there are any t junctions before the next vert - v1 = &ds->verts[i]; - v2 = &ds->verts[ (i+1) % ds->numVerts ]; - - j = (int)ds->verts[i].lightmap[0]; - if ( j == -1 ) { - continue; // degenerate edge - } - e = &edgeLines[ j ]; - - VectorSubtract( v1->xyz, e->origin, delta ); - start = DotProduct( delta, e->dir ); - - VectorSubtract( v2->xyz, e->origin, delta ); - end = DotProduct( delta, e->dir ); - - - if ( start < end ) { - p = e->chain.next; - } else { - p = e->chain.prev; - } - - for ( ; p != &e->chain ; ) { - if ( start < end ) { - if ( p->intercept > end - ON_EPSILON ) { - break; - } - } else { - if ( p->intercept < end + ON_EPSILON ) { - break; - } - } - - if ( - ( start < end && p->intercept > start + ON_EPSILON ) || - ( start > end && p->intercept < start - ON_EPSILON ) ) { - // insert this point - if ( numVerts == MAX_SURFACE_VERTS ) { - Error( "MAX_SURFACE_VERTS" ); - } - - // take the exact intercept point - VectorCopy( p->xyz, verts[ numVerts ].xyz ); - - // copy the normal - VectorCopy( v1->normal, verts[ numVerts ].normal ); - - // interpolate the texture coordinates - frac = ( p->intercept - start ) / ( end - start ); - for ( j = 0 ; j < 2 ; j++ ) { - verts[ numVerts ].st[j] = v1->st[j] + - frac * ( v2->st[j] - v1->st[j] ); - } - originals[numVerts] = i; - numVerts++; - counts[i]++; - } - - if ( start < end ) { - p = p->next; - } else { - p = p->prev; - } - } - } - - c_addedVerts += numVerts - ds->numVerts; - c_totalVerts += numVerts; - - - // FIXME: check to see if the entire surface degenerated - // after snapping - - // rotate the points so that the initial vertex is between - // two non-subdivided edges - for ( i = 0 ; i < numVerts ; i++ ) { - if ( originals[ (i+1) % numVerts ] == originals[ i ] ) { - continue; - } - j = (i + numVerts - 1 ) % numVerts; - k = (i + numVerts - 2 ) % numVerts; - if ( originals[ j ] == originals[ k ] ) { - continue; - } - break; - } - - if ( i == 0 ) { - // fine the way it is - c_natural++; - - ds->numVerts = numVerts; - ds->verts = malloc( numVerts * sizeof( *ds->verts ) ); - memcpy( ds->verts, verts, numVerts * sizeof( *ds->verts ) ); - - return; - } - if ( i == numVerts ) { - // create a vertex in the middle to start the fan - c_cant++; - -/* - memset ( &verts[numVerts], 0, sizeof( verts[numVerts] ) ); - for ( i = 0 ; i < numVerts ; i++ ) { - for ( j = 0 ; j < 10 ; j++ ) { - verts[numVerts].xyz[j] += verts[i].xyz[j]; - } - } - for ( j = 0 ; j < 10 ; j++ ) { - verts[numVerts].xyz[j] /= numVerts; - } - - i = numVerts; - numVerts++; -*/ - } else { - // just rotate the vertexes - c_rotate++; - - } - - ds->numVerts = numVerts; - ds->verts = malloc( numVerts * sizeof( *ds->verts ) ); - - for ( j = 0 ; j < ds->numVerts ; j++ ) { - ds->verts[j] = verts[ ( j + i ) % ds->numVerts ]; - } -} - -/* -================ -EdgeCompare -================ -*/ -int EdgeCompare( const void *elem1, const void *elem2 ) { - float d1, d2; - - d1 = ((originalEdge_t *)elem1)->length; - d2 = ((originalEdge_t *)elem2)->length; - - if ( d1 < d2 ) { - return -1; - } - if ( d2 > d1 ) { - return 1; - } - return 0; -} - - -/* -================ -FixTJunctions - -Call after the surface list has been pruned, but before lightmap allocation -================ -*/ -void FixTJunctions( entity_t *ent ) { - int i; - mapDrawSurface_t *ds; - int axialEdgeLines; - originalEdge_t *e; - - qprintf("----- FixTJunctions -----\n"); - - numEdgeLines = 0; - numOriginalEdges = 0; - - // add all the edges - // this actually creates axial edges, but it - // only creates originalEdge_t structures - // for non-axial edges - for ( i = ent->firstDrawSurf ; i < numMapDrawSurfs ; i++ ) { - ds = &mapDrawSurfs[i]; - if ( ds->patch ) { - AddPatchEdges( ds ); - } else if ( ds->shaderInfo->autosprite || ds->shaderInfo->notjunc || ds->miscModel ) { - // miscModels don't add tjunctions - } else { - AddSurfaceEdges( ds ); - } - } - - axialEdgeLines = numEdgeLines; - - // sort the non-axial edges by length - qsort( originalEdges, numOriginalEdges, sizeof(originalEdges[0]), EdgeCompare ); - - // add the non-axial edges, longest first - // this gives the most accurate edge description - for ( i = 0 ; i < numOriginalEdges ; i++ ) { - e = &originalEdges[i]; - e->dv[0]->lightmap[0] = AddEdge( e->dv[0]->xyz, e->dv[1]->xyz, qtrue ); - } - - qprintf( "%6i axial edge lines\n", axialEdgeLines ); - qprintf( "%6i non-axial edge lines\n", numEdgeLines - axialEdgeLines ); - qprintf( "%6i degenerate edges\n", c_degenerateEdges ); - - // insert any needed vertexes - for ( i = ent->firstDrawSurf ; i < numMapDrawSurfs ; i++ ) { - ds = &mapDrawSurfs[i]; - if ( ds->patch ) { - continue; - } - if ( ds->shaderInfo->autosprite || ds->shaderInfo->notjunc || ds->miscModel ) { - continue; - } - - FixSurfaceJunctions( ds ); - } - - qprintf( "%6i verts added for tjunctions\n", c_addedVerts ); - qprintf( "%6i total verts\n", c_totalVerts ); - qprintf( "%6i naturally ordered\n", c_natural ); - qprintf( "%6i rotated orders\n", c_rotate ); - qprintf( "%6i can't order\n", c_cant ); -} diff --git a/q3map/tree.c b/q3map/tree.c deleted file mode 100644 index f400db1..0000000 --- a/q3map/tree.c +++ /dev/null @@ -1,146 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#include "qbsp.h" - - -extern int c_nodes; - -void RemovePortalFromNode (portal_t *portal, node_t *l); - -node_t *NodeForPoint (node_t *node, vec3_t origin) -{ - plane_t *plane; - vec_t d; - - while (node->planenum != PLANENUM_LEAF) - { - plane = &mapplanes[node->planenum]; - d = DotProduct (origin, plane->normal) - plane->dist; - if (d >= 0) - node = node->children[0]; - else - node = node->children[1]; - } - - return node; -} - - - -/* -============= -FreeTreePortals_r -============= -*/ -void FreeTreePortals_r (node_t *node) -{ - portal_t *p, *nextp; - int s; - - // free children - if (node->planenum != PLANENUM_LEAF) - { - FreeTreePortals_r (node->children[0]); - FreeTreePortals_r (node->children[1]); - } - - // free portals - for (p=node->portals ; p ; p=nextp) - { - s = (p->nodes[1] == node); - nextp = p->next[s]; - - RemovePortalFromNode (p, p->nodes[!s]); - FreePortal (p); - } - node->portals = NULL; -} - -/* -============= -FreeTree_r -============= -*/ -void FreeTree_r (node_t *node) -{ - // free children - if (node->planenum != PLANENUM_LEAF) - { - FreeTree_r (node->children[0]); - FreeTree_r (node->children[1]); - } - - // free bspbrushes - FreeBrushList (node->brushlist); - - // free the node - if (node->volume) - FreeBrush (node->volume); - - if (numthreads == 1) - c_nodes--; - free (node); -} - - -/* -============= -FreeTree -============= -*/ -void FreeTree (tree_t *tree) -{ - FreeTreePortals_r (tree->headnode); - FreeTree_r (tree->headnode); - free (tree); -} - -//=============================================================== - -void PrintTree_r (node_t *node, int depth) -{ - int i; - plane_t *plane; - bspbrush_t *bb; - - for (i=0 ; i<depth ; i++) - _printf (" "); - if (node->planenum == PLANENUM_LEAF) - { - if (!node->brushlist) - _printf ("NULL\n"); - else - { - for (bb=node->brushlist ; bb ; bb=bb->next) - _printf ("%i ", bb->original->brushnum); - _printf ("\n"); - } - return; - } - - plane = &mapplanes[node->planenum]; - _printf ("#%i (%5.2f %5.2f %5.2f):%5.2f\n", node->planenum, - plane->normal[0], plane->normal[1], plane->normal[2], - plane->dist); - PrintTree_r (node->children[0], depth+1); - PrintTree_r (node->children[1], depth+1); -} diff --git a/q3map/vis.c b/q3map/vis.c deleted file mode 100644 index 329d192..0000000 --- a/q3map/vis.c +++ /dev/null @@ -1,1197 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// vis.c - -#include "vis.h" -#include "threads.h" -#include "stdlib.h" -#ifdef _WIN32 -#include "../libs/pakstuff.h" -#endif - - -#define VIS_HEADER_SIZE 8 - -extern char outbase[32]; - -int numportals; -int portalclusters; -int numfaces; - -char inbase[32]; - -vportal_t *portals; -leaf_t *leafs; - -vportal_t *faces; -leaf_t *faceleafs; - -int c_portaltest, c_portalpass, c_portalcheck; - -int leafbytes; // (portalclusters+63)>>3 -int leaflongs; - -int portalbytes, portallongs; - -qboolean fastvis; -qboolean noPassageVis; -qboolean passageVisOnly; -qboolean mergevis; -qboolean nosort; -qboolean saveprt; - -int testlevel = 2; - -int totalvis; - -vportal_t *sorted_portals[MAX_MAP_PORTALS*2]; - -void PassageMemory(void); - - -//============================================================================= - -void PlaneFromWinding (winding_t *w, plane_t *plane) -{ - vec3_t v1, v2; - -// calc plane - VectorSubtract (w->points[2], w->points[1], v1); - VectorSubtract (w->points[0], w->points[1], v2); - CrossProduct (v2, v1, plane->normal); - VectorNormalize (plane->normal, plane->normal); - plane->dist = DotProduct (w->points[0], plane->normal); -} - - -/* -================== -NewWinding -================== -*/ -winding_t *NewWinding (int points) -{ - winding_t *w; - int size; - - if (points > MAX_POINTS_ON_WINDING) - Error ("NewWinding: %i points", points); - - size = (int)((winding_t *)0)->points[points]; - w = malloc (size); - memset (w, 0, size); - - return w; -} - - - -void prl(leaf_t *l) -{ - int i; - vportal_t *p; - plane_t pl; - - for (i=0 ; i<l->numportals ; i++) - { - p = l->portals[i]; - pl = p->plane; - _printf ("portal %4i to leaf %4i : %7.1f : (%4.1f, %4.1f, %4.1f)\n",(int)(p-portals),p->leaf,pl.dist, pl.normal[0], pl.normal[1], pl.normal[2]); - } -} - - -//============================================================================= - -/* -============= -SortPortals - -Sorts the portals from the least complex, so the later ones can reuse -the earlier information. -============= -*/ -int PComp (const void *a, const void *b) -{ - if ( (*(vportal_t **)a)->nummightsee == (*(vportal_t **)b)->nummightsee) - return 0; - if ( (*(vportal_t **)a)->nummightsee < (*(vportal_t **)b)->nummightsee) - return -1; - return 1; -} -void SortPortals (void) -{ - int i; - - for (i=0 ; i<numportals*2 ; i++) - sorted_portals[i] = &portals[i]; - - if (nosort) - return; - qsort (sorted_portals, numportals*2, sizeof(sorted_portals[0]), PComp); -} - - -/* -============== -LeafVectorFromPortalVector -============== -*/ -int LeafVectorFromPortalVector (byte *portalbits, byte *leafbits) -{ - int i, j, leafnum; - vportal_t *p; - int c_leafs; - - - for (i=0 ; i<numportals*2 ; i++) - { - if (portalbits[i>>3] & (1<<(i&7)) ) - { - p = portals+i; - leafbits[p->leaf>>3] |= (1<<(p->leaf&7)); - } - } - - for (j = 0; j < portalclusters; j++) - { - leafnum = j; - while (leafs[leafnum].merged >= 0) - leafnum = leafs[leafnum].merged; - //if the merged leaf is visible then the original leaf is visible - if (leafbits[leafnum>>3] & (1<<(leafnum&7))) - { - leafbits[j>>3] |= (1<<(j&7)); - } - } - - c_leafs = CountBits (leafbits, portalclusters); - - return c_leafs; -} - - -/* -=============== -ClusterMerge - -Merges the portal visibility for a leaf -=============== -*/ -void ClusterMerge (int leafnum) -{ - leaf_t *leaf; - byte portalvector[MAX_PORTALS/8]; - byte uncompressed[MAX_MAP_LEAFS/8]; - int i, j; - int numvis, mergedleafnum; - vportal_t *p; - int pnum; - - // OR together all the portalvis bits - - mergedleafnum = leafnum; - while(leafs[mergedleafnum].merged >= 0) - mergedleafnum = leafs[mergedleafnum].merged; - - memset (portalvector, 0, portalbytes); - leaf = &leafs[mergedleafnum]; - for (i = 0; i < leaf->numportals; i++) - { - p = leaf->portals[i]; - if (p->removed) - continue; - - if (p->status != stat_done) - Error ("portal not done"); - for (j=0 ; j<portallongs ; j++) - ((long *)portalvector)[j] |= ((long *)p->portalvis)[j]; - pnum = p - portals; - portalvector[pnum>>3] |= 1<<(pnum&7); - } - - memset (uncompressed, 0, leafbytes); - - uncompressed[mergedleafnum>>3] |= (1<<(mergedleafnum&7)); - // convert portal bits to leaf bits - numvis = LeafVectorFromPortalVector (portalvector, uncompressed); - -// if (uncompressed[leafnum>>3] & (1<<(leafnum&7))) -// _printf ("WARNING: Leaf portals saw into leaf\n"); - -// uncompressed[leafnum>>3] |= (1<<(leafnum&7)); - - numvis++; // count the leaf itself - - totalvis += numvis; - - qprintf ("cluster %4i : %4i visible\n", leafnum, numvis); - - memcpy (visBytes + VIS_HEADER_SIZE + leafnum*leafbytes, uncompressed, leafbytes); -} - -/* -================== -CalcPortalVis -================== -*/ -void CalcPortalVis (void) -{ -#ifdef MREDEBUG - _printf("%6d portals out of %d", 0, numportals*2); - //get rid of the counter - RunThreadsOnIndividual (numportals*2, qfalse, PortalFlow); -#else - RunThreadsOnIndividual (numportals*2, qtrue, PortalFlow); -#endif - -} - -/* -================== -CalcPassageVis -================== -*/ -void CalcPassageVis(void) -{ - PassageMemory(); - -#ifdef MREDEBUG - _printf("%6d portals out of %d", 0, numportals*2); - RunThreadsOnIndividual (numportals*2, qfalse, CreatePassages); - _printf("\n"); - _printf("%6d portals out of %d", 0, numportals*2); - RunThreadsOnIndividual (numportals*2, qfalse, PassageFlow); - _printf("\n"); -#else - RunThreadsOnIndividual (numportals*2, qtrue, CreatePassages); - RunThreadsOnIndividual (numportals*2, qtrue, PassageFlow); -#endif -} - -/* -================== -CalcPassagePortalVis -================== -*/ -void CalcPassagePortalVis(void) -{ - PassageMemory(); - -#ifdef MREDEBUG - _printf("%6d portals out of %d", 0, numportals*2); - RunThreadsOnIndividual (numportals*2, qfalse, CreatePassages); - _printf("\n"); - _printf("%6d portals out of %d", 0, numportals*2); - RunThreadsOnIndividual (numportals*2, qfalse, PassagePortalFlow); - _printf("\n"); -#else - RunThreadsOnIndividual (numportals*2, qtrue, CreatePassages); - RunThreadsOnIndividual (numportals*2, qtrue, PassagePortalFlow); -#endif -} - -/* -================== -CalcFastVis -================== -*/ -void CalcFastVis(void) -{ - int i; - - // fastvis just uses mightsee for a very loose bound - for (i=0 ; i<numportals*2 ; i++) - { - portals[i].portalvis = portals[i].portalflood; - portals[i].status = stat_done; - } -} - -/* -================== -CalcVis -================== -*/ -void CalcVis (void) -{ - int i; - - RunThreadsOnIndividual (numportals*2, qtrue, BasePortalVis); - -// RunThreadsOnIndividual (numportals*2, qtrue, BetterPortalVis); - - SortPortals (); - - if (fastvis) { - CalcFastVis(); - } - else if ( noPassageVis ) { - CalcPortalVis(); - } - else if ( passageVisOnly ) { - CalcPassageVis(); - } - else { - CalcPassagePortalVis(); - } - // - // assemble the leaf vis lists by oring and compressing the portal lists - // - _printf("creating leaf vis...\n"); - for (i=0 ; i<portalclusters ; i++) - ClusterMerge (i); - - _printf( "Total visible clusters: %i\n", totalvis ); - _printf( "Average clusters visible: %i\n", totalvis / portalclusters ); -} - -/* -================== -SetPortalSphere -================== -*/ -void SetPortalSphere (vportal_t *p) -{ - int i; - vec3_t total, dist; - winding_t *w; - float r, bestr; - - w = p->winding; - VectorCopy (vec3_origin, total); - for (i=0 ; i<w->numpoints ; i++) - { - VectorAdd (total, w->points[i], total); - } - - for (i=0 ; i<3 ; i++) - total[i] /= w->numpoints; - - bestr = 0; - for (i=0 ; i<w->numpoints ; i++) - { - VectorSubtract (w->points[i], total, dist); - r = VectorLength (dist); - if (r > bestr) - bestr = r; - } - VectorCopy (total, p->origin); - p->radius = bestr; -} - -/* -============= -Winding_PlanesConcave -============= -*/ -#define WCONVEX_EPSILON 0.2 - -int Winding_PlanesConcave(winding_t *w1, winding_t *w2, - vec3_t normal1, vec3_t normal2, - float dist1, float dist2) -{ - int i; - - if (!w1 || !w2) return qfalse; - - // check if one of the points of winding 1 is at the front of the plane of winding 2 - for (i = 0; i < w1->numpoints; i++) - { - if (DotProduct(normal2, w1->points[i]) - dist2 > WCONVEX_EPSILON) return qtrue; - } - // check if one of the points of winding 2 is at the front of the plane of winding 1 - for (i = 0; i < w2->numpoints; i++) - { - if (DotProduct(normal1, w2->points[i]) - dist1 > WCONVEX_EPSILON) return qtrue; - } - - return qfalse; -} - -/* -============ -TryMergeLeaves -============ -*/ -int TryMergeLeaves(int l1num, int l2num) -{ - int i, j, k, n, numportals; - plane_t plane1, plane2; - leaf_t *l1, *l2; - vportal_t *p1, *p2; - vportal_t *portals[MAX_PORTALS_ON_LEAF]; - - for (k = 0; k < 2; k++) - { - if (k) l1 = &leafs[l1num]; - else l1 = &faceleafs[l1num]; - for (i = 0; i < l1->numportals; i++) - { - p1 = l1->portals[i]; - if (p1->leaf == l2num) continue; - for (n = 0; n < 2; n++) - { - if (n) l2 = &leafs[l2num]; - else l2 = &faceleafs[l2num]; - for (j = 0; j < l2->numportals; j++) - { - p2 = l2->portals[j]; - if (p2->leaf == l1num) continue; - // - plane1 = p1->plane; - plane2 = p2->plane; - if (Winding_PlanesConcave(p1->winding, p2->winding, plane1.normal, plane2.normal, plane1.dist, plane2.dist)) - return qfalse; - } - } - } - } - for (k = 0; k < 2; k++) - { - if (k) - { - l1 = &leafs[l1num]; - l2 = &leafs[l2num]; - } - else - { - l1 = &faceleafs[l1num]; - l2 = &faceleafs[l2num]; - } - numportals = 0; - //the leaves can be merged now - for (i = 0; i < l1->numportals; i++) - { - p1 = l1->portals[i]; - if (p1->leaf == l2num) - { - p1->removed = qtrue; - continue; - } - portals[numportals++] = p1; - } - for (j = 0; j < l2->numportals; j++) - { - p2 = l2->portals[j]; - if (p2->leaf == l1num) - { - p2->removed = qtrue; - continue; - } - portals[numportals++] = p2; - } - for (i = 0; i < numportals; i++) - { - l2->portals[i] = portals[i]; - } - l2->numportals = numportals; - l1->merged = l2num; - } - return qtrue; -} - -/* -============ -UpdatePortals -============ -*/ -void UpdatePortals(void) -{ - int i; - vportal_t *p; - - for (i = 0; i < numportals * 2; i++) - { - p = &portals[i]; - if (p->removed) - continue; - while(leafs[p->leaf].merged >= 0) - p->leaf = leafs[p->leaf].merged; - } -} - -/* -============ -MergeLeaves - -try to merge leaves but don't merge through hint splitters -============ -*/ -void MergeLeaves(void) -{ - int i, j, nummerges, totalnummerges; - leaf_t *leaf; - vportal_t *p; - - totalnummerges = 0; - do - { - nummerges = 0; - for (i = 0; i < portalclusters; i++) - { - leaf = &leafs[i]; - //if this leaf is merged already - if (leaf->merged >= 0) - continue; - // - for (j = 0; j < leaf->numportals; j++) - { - p = leaf->portals[j]; - // - if (p->removed) - continue; - //never merge through hint portals - if (p->hint) - continue; - if (TryMergeLeaves(i, p->leaf)) - { - UpdatePortals(); - nummerges++; - break; - } - } - } - totalnummerges += nummerges; - } while (nummerges); - _printf("%6d leaves merged\n", totalnummerges); -} - -/* -============ -TryMergeWinding -============ -*/ -#define CONTINUOUS_EPSILON 0.005 - -winding_t *TryMergeWinding (winding_t *f1, winding_t *f2, vec3_t planenormal) -{ - vec_t *p1, *p2, *p3, *p4, *back; - winding_t *newf; - int i, j, k, l; - vec3_t normal, delta; - vec_t dot; - qboolean keep1, keep2; - - - // - // find a common edge - // - p1 = p2 = NULL; // stop compiler warning - j = 0; // - - for (i = 0; i < f1->numpoints; i++) - { - p1 = f1->points[i]; - p2 = f1->points[(i+1) % f1->numpoints]; - for (j = 0; j < f2->numpoints; j++) - { - p3 = f2->points[j]; - p4 = f2->points[(j+1) % f2->numpoints]; - for (k = 0; k < 3; k++) - { - if (fabs(p1[k] - p4[k]) > 0.1)//EQUAL_EPSILON) //ME - break; - if (fabs(p2[k] - p3[k]) > 0.1)//EQUAL_EPSILON) //ME - break; - } //end for - if (k==3) - break; - } //end for - if (j < f2->numpoints) - break; - } //end for - - if (i == f1->numpoints) - return NULL; // no matching edges - - // - // check slope of connected lines - // if the slopes are colinear, the point can be removed - // - back = f1->points[(i+f1->numpoints-1)%f1->numpoints]; - VectorSubtract (p1, back, delta); - CrossProduct (planenormal, delta, normal); - VectorNormalize (normal, normal); - - back = f2->points[(j+2)%f2->numpoints]; - VectorSubtract (back, p1, delta); - dot = DotProduct (delta, normal); - if (dot > CONTINUOUS_EPSILON) - return NULL; // not a convex polygon - keep1 = (qboolean)(dot < -CONTINUOUS_EPSILON); - - back = f1->points[(i+2)%f1->numpoints]; - VectorSubtract (back, p2, delta); - CrossProduct (planenormal, delta, normal); - VectorNormalize (normal, normal); - - back = f2->points[(j+f2->numpoints-1)%f2->numpoints]; - VectorSubtract (back, p2, delta); - dot = DotProduct (delta, normal); - if (dot > CONTINUOUS_EPSILON) - return NULL; // not a convex polygon - keep2 = (qboolean)(dot < -CONTINUOUS_EPSILON); - - // - // build the new polygon - // - newf = NewWinding (f1->numpoints + f2->numpoints); - - // copy first polygon - for (k=(i+1)%f1->numpoints ; k != i ; k=(k+1)%f1->numpoints) - { - if (k==(i+1)%f1->numpoints && !keep2) - continue; - - VectorCopy (f1->points[k], newf->points[newf->numpoints]); - newf->numpoints++; - } - - // copy second polygon - for (l= (j+1)%f2->numpoints ; l != j ; l=(l+1)%f2->numpoints) - { - if (l==(j+1)%f2->numpoints && !keep1) - continue; - VectorCopy (f2->points[l], newf->points[newf->numpoints]); - newf->numpoints++; - } - - return newf; -} - -/* -============ -MergeLeafPortals -============ -*/ -void MergeLeafPortals(void) -{ - int i, j, k, nummerges, hintsmerged; - leaf_t *leaf; - vportal_t *p1, *p2; - winding_t *w; - - nummerges = 0; - hintsmerged = 0; - for (i = 0; i < portalclusters; i++) - { - leaf = &leafs[i]; - if (leaf->merged >= 0) continue; - for (j = 0; j < leaf->numportals; j++) - { - p1 = leaf->portals[j]; - if (p1->removed) - continue; - for (k = j+1; k < leaf->numportals; k++) - { - p2 = leaf->portals[k]; - if (p2->removed) - continue; - if (p1->leaf == p2->leaf) - { - w = TryMergeWinding(p1->winding, p2->winding, p1->plane.normal); - if (w) - { - FreeWinding(p1->winding); - p1->winding = w; - if (p1->hint && p2->hint) - hintsmerged++; - p1->hint |= p2->hint; - SetPortalSphere(p1); - p2->removed = qtrue; - nummerges++; - i--; - break; - } - } - } - if (k < leaf->numportals) - break; - } - } - _printf("%6d portals merged\n", nummerges); - _printf("%6d hint portals merged\n", hintsmerged); -} - - -/* -============ -WritePortals -============ -*/ -int CountActivePortals(void) -{ - int num, hints, j; - vportal_t *p; - - num = 0; - hints = 0; - for (j = 0; j < numportals * 2; j++) - { - p = portals + j; - if (p->removed) - continue; - if (p->hint) - hints++; - num++; - } - _printf("%6d active portals\n", num); - _printf("%6d hint portals\n", hints); - return num; -} - -/* -============ -WritePortals -============ -*/ -void WriteFloat (FILE *f, vec_t v); - -void WritePortals(char *filename) -{ - int i, j, num; - FILE *pf; - vportal_t *p; - winding_t *w; - - // write the file - pf = fopen (filename, "w"); - if (!pf) - Error ("Error opening %s", filename); - - num = 0; - for (j = 0; j < numportals * 2; j++) - { - p = portals + j; - if (p->removed) - continue; -// if (!p->hint) -// continue; - num++; - } - - fprintf (pf, "%s\n", PORTALFILE); - fprintf (pf, "%i\n", 0); - fprintf (pf, "%i\n", num);// + numfaces); - fprintf (pf, "%i\n", 0); - - for (j = 0; j < numportals * 2; j++) - { - p = portals + j; - if (p->removed) - continue; -// if (!p->hint) -// continue; - w = p->winding; - fprintf (pf,"%i %i %i ",w->numpoints, 0, 0); - fprintf (pf, "%d ", p->hint); - for (i=0 ; i<w->numpoints ; i++) - { - fprintf (pf,"("); - WriteFloat (pf, w->points[i][0]); - WriteFloat (pf, w->points[i][1]); - WriteFloat (pf, w->points[i][2]); - fprintf (pf,") "); - } - fprintf (pf,"\n"); - } - - /* - for (j = 0; j < numfaces; j++) - { - p = faces + j; - w = p->winding; - fprintf (pf,"%i %i %i ",w->numpoints, 0, 0); - fprintf (pf, "0 "); - for (i=0 ; i<w->numpoints ; i++) - { - fprintf (pf,"("); - WriteFloat (pf, w->points[i][0]); - WriteFloat (pf, w->points[i][1]); - WriteFloat (pf, w->points[i][2]); - fprintf (pf,") "); - } - fprintf (pf,"\n"); - }*/ - - fclose (pf); -} - -/* -============ -LoadPortals -============ -*/ -void LoadPortals (char *name) -{ - int i, j, hint; - vportal_t *p; - leaf_t *l; - char magic[80]; - FILE *f; - int numpoints; - winding_t *w; - int leafnums[2]; - plane_t plane; - - if (!strcmp(name,"-")) - f = stdin; - else - { - f = fopen(name, "r"); - if (!f) - Error ("LoadPortals: couldn't read %s\n",name); - } - - if (fscanf (f,"%79s\n%i\n%i\n%i\n",magic, &portalclusters, &numportals, &numfaces) != 4) - Error ("LoadPortals: failed to read header"); - if (strcmp(magic,PORTALFILE)) - Error ("LoadPortals: not a portal file"); - - _printf ("%6i portalclusters\n", portalclusters); - _printf ("%6i numportals\n", numportals); - _printf ("%6i numfaces\n", numfaces); - - // these counts should take advantage of 64 bit systems automatically - leafbytes = ((portalclusters+63)&~63)>>3; - leaflongs = leafbytes/sizeof(long); - - portalbytes = ((numportals*2+63)&~63)>>3; - portallongs = portalbytes/sizeof(long); - - // each file portal is split into two memory portals - portals = malloc(2*numportals*sizeof(vportal_t)); - memset (portals, 0, 2*numportals*sizeof(vportal_t)); - - leafs = malloc(portalclusters*sizeof(leaf_t)); - memset (leafs, 0, portalclusters*sizeof(leaf_t)); - - for (i = 0; i < portalclusters; i++) - leafs[i].merged = -1; - - numVisBytes = VIS_HEADER_SIZE + portalclusters*leafbytes; - - ((int *)visBytes)[0] = portalclusters; - ((int *)visBytes)[1] = leafbytes; - - for (i=0, p=portals ; i<numportals ; i++) - { - if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1]) != 3) - Error ("LoadPortals: reading portal %i", i); - if (numpoints > MAX_POINTS_ON_WINDING) - Error ("LoadPortals: portal %i has too many points", i); - if ( (unsigned)leafnums[0] > portalclusters - || (unsigned)leafnums[1] > portalclusters) - Error ("LoadPortals: reading portal %i", i); - if (fscanf (f, "%i ", &hint) != 1) - Error ("LoadPortals: reading hint state"); - - w = p->winding = NewWinding (numpoints); - w->numpoints = numpoints; - - for (j=0 ; j<numpoints ; j++) - { - double v[3]; - int k; - - // scanf into double, then assign to vec_t - // so we don't care what size vec_t is - if (fscanf (f, "(%lf %lf %lf ) " - , &v[0], &v[1], &v[2]) != 3) - Error ("LoadPortals: reading portal %i", i); - for (k=0 ; k<3 ; k++) - w->points[j][k] = v[k]; - } - fscanf (f, "\n"); - - // calc plane - PlaneFromWinding (w, &plane); - - // create forward portal - l = &leafs[leafnums[0]]; - if (l->numportals == MAX_PORTALS_ON_LEAF) - Error ("Leaf with too many portals"); - l->portals[l->numportals] = p; - l->numportals++; - - p->num = i+1; - p->hint = hint; - p->winding = w; - VectorSubtract (vec3_origin, plane.normal, p->plane.normal); - p->plane.dist = -plane.dist; - p->leaf = leafnums[1]; - SetPortalSphere (p); - p++; - - // create backwards portal - l = &leafs[leafnums[1]]; - if (l->numportals == MAX_PORTALS_ON_LEAF) - Error ("Leaf with too many portals"); - l->portals[l->numportals] = p; - l->numportals++; - - p->num = i+1; - p->hint = hint; - p->winding = NewWinding(w->numpoints); - p->winding->numpoints = w->numpoints; - for (j=0 ; j<w->numpoints ; j++) - { - VectorCopy (w->points[w->numpoints-1-j], p->winding->points[j]); - } - - p->plane = plane; - p->leaf = leafnums[0]; - SetPortalSphere (p); - p++; - - } - - faces = malloc(2*numfaces*sizeof(vportal_t)); - memset (faces, 0, 2*numfaces*sizeof(vportal_t)); - - faceleafs = malloc(portalclusters*sizeof(leaf_t)); - memset(faceleafs, 0, portalclusters*sizeof(leaf_t)); - - for (i = 0, p = faces; i < numfaces; i++) - { - if (fscanf (f, "%i %i ", &numpoints, &leafnums[0]) != 2) - Error ("LoadPortals: reading portal %i", i); - - w = p->winding = NewWinding (numpoints); - w->numpoints = numpoints; - - for (j=0 ; j<numpoints ; j++) - { - double v[3]; - int k; - - // scanf into double, then assign to vec_t - // so we don't care what size vec_t is - if (fscanf (f, "(%lf %lf %lf ) " - , &v[0], &v[1], &v[2]) != 3) - Error ("LoadPortals: reading portal %i", i); - for (k=0 ; k<3 ; k++) - w->points[j][k] = v[k]; - } - fscanf (f, "\n"); - - // calc plane - PlaneFromWinding (w, &plane); - - l = &faceleafs[leafnums[0]]; - l->merged = -1; - if (l->numportals == MAX_PORTALS_ON_LEAF) - Error ("Leaf with too many faces"); - l->portals[l->numportals] = p; - l->numportals++; - - p->num = i+1; - p->winding = w; - // normal pointing out of the leaf - VectorSubtract (vec3_origin, plane.normal, p->plane.normal); - p->plane.dist = -plane.dist; - p->leaf = -1; - SetPortalSphere (p); - p++; - } - - fclose (f); -} - - -/* -================ -CalcPHS - -Calculate the PHS (Potentially Hearable Set) -by ORing together all the PVS visible from a leaf -================ -*/ -void CalcPHS (void) -{ - int i, j, k, l, index; - int bitbyte; - long *dest, *src; - byte *scan; - int count; - byte uncompressed[MAX_MAP_LEAFS/8]; - - _printf ("Building PHS...\n"); - - count = 0; - for (i=0 ; i<portalclusters ; i++) - { - scan = visBytes + i*leafbytes; - memcpy (uncompressed, scan, leafbytes); - for (j=0 ; j<leafbytes ; j++) - { - bitbyte = scan[j]; - if (!bitbyte) - continue; - for (k=0 ; k<8 ; k++) - { - if (! (bitbyte & (1<<k)) ) - continue; - // OR this pvs row into the phs - index = ((j<<3)+k); - if (index >= portalclusters) - Error ("Bad bit in PVS"); // pad bits should be 0 - src = (long *)(visBytes + index*leafbytes); - dest = (long *)uncompressed; - for (l=0 ; l<leaflongs ; l++) - ((long *)uncompressed)[l] |= src[l]; - } - } - for (j=0 ; j<portalclusters ; j++) - if (uncompressed[j>>3] & (1<<(j&7)) ) - count++; - - // FIXME: copy it off - } - - _printf ("Average clusters hearable: %i\n", count/portalclusters); -} - -/* -=========== -VisMain -=========== -*/ -int VisMain (int argc, char **argv) -{ - char portalfile[1024]; - char name[1024]; - int i; - double start, end; - - _printf ("---- vis ----\n"); - - verbose = qfalse; - for (i=1 ; i<argc ; i++) { - if (!strcmp(argv[i],"-threads")) { - numthreads = atoi (argv[i+1]); - i++; - } else if (!strcmp(argv[i],"-threads")) { - numthreads = atoi (argv[i+1]); - i++; - } else if (!strcmp(argv[i], "-fast")) { - _printf ("fastvis = true\n"); - fastvis = qtrue; - } else if (!strcmp(argv[i], "-merge")) { - _printf ("merge = true\n"); - mergevis = qtrue; - } else if (!strcmp(argv[i], "-nopassage")) { - _printf ("nopassage = true\n"); - noPassageVis = qtrue; - } else if (!strcmp(argv[i], "-passageOnly")) { - _printf("passageOnly = true\n"); - passageVisOnly = qtrue; - } else if (!strcmp(argv[i], "-level")) { - testlevel = atoi(argv[i+1]); - _printf ("testlevel = %i\n", testlevel); - i++; - } else if (!strcmp(argv[i], "-v")) { - _printf ("verbose = true\n"); - verbose = qtrue; - } else if (!strcmp (argv[i],"-nosort")) { - _printf ("nosort = true\n"); - nosort = qtrue; - } else if (!strcmp (argv[i],"-saveprt")) { - _printf ("saveprt = true\n"); - saveprt = qtrue; - } else if (!strcmp (argv[i],"-tmpin")) { - strcpy (inbase, "/tmp"); - } else if (!strcmp (argv[i],"-tmpout")) { - strcpy (outbase, "/tmp"); - } else if (argv[i][0] == '-') { - Error ("Unknown option \"%s\"", argv[i]); - } else { - break; - } - } - - if (i != argc - 1) - Error ("usage: vis [-threads #] [-level 0-4] [-fast] [-v] bspfile"); - -#ifdef MREDEBUG - start = clock(); -#else - start = I_FloatTime (); -#endif - - ThreadSetDefault (); - - SetQdirFromPath (argv[i]); - -#ifdef _WIN32 - InitPakFile(gamedir, NULL); -#endif - - // load the bsp - sprintf (name, "%s%s", inbase, ExpandArg(argv[i])); - StripExtension (name); - strcat (name, ".bsp"); - _printf ("reading %s\n", name); - LoadBSPFile (name); - - // load the portal file - sprintf (portalfile, "%s%s", inbase, ExpandArg(argv[i])); - StripExtension (portalfile); - strcat (portalfile, ".prt"); - _printf ("reading %s\n", portalfile); - LoadPortals (portalfile); - - if (mergevis) - { - MergeLeaves(); - MergeLeafPortals(); - } - - CountActivePortals(); -// WritePortals("maps/hints.prs"); - - _printf ("visdatasize:%i\n", numVisBytes); - - CalcVis (); - -// CalcPHS (); - - // delete the prt file - if ( !saveprt ) { - remove( portalfile ); - } - - // write the bsp file - _printf ("writing %s\n", name); - WriteBSPFile (name); - -#ifdef MREDEBUG - end = clock(); - _printf ("%5.2f seconds elapsed\n", (end-start) / CLK_TCK); -#else - end = I_FloatTime (); - _printf ("%5.2f seconds elapsed\n", end-start); -#endif - return 0; -} - diff --git a/q3map/vis.h b/q3map/vis.h deleted file mode 100644 index 8eed728..0000000 --- a/q3map/vis.h +++ /dev/null @@ -1,162 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// vis.h - -#include "cmdlib.h" -#include "mathlib.h" -#include "bspfile.h" - -#define MAX_PORTALS 32768 - -#define PORTALFILE "PRT1" - -#define ON_EPSILON 0.1 - -//#define MREDEBUG - -// seperator caching helps a bit -#define SEPERATORCACHE - -// can't have more seperators than the max number of points on a winding -#define MAX_SEPERATORS 64 - -typedef struct -{ - vec3_t normal; - float dist; -} plane_t; - -#define MAX_POINTS_ON_WINDING 64 -#define MAX_POINTS_ON_FIXED_WINDING 12 - -typedef struct -{ - int numpoints; - vec3_t points[MAX_POINTS_ON_FIXED_WINDING]; // variable sized -} winding_t; - -winding_t *NewWinding (int points); -void FreeWinding (winding_t *w); -winding_t *CopyWinding (winding_t *w); - - -typedef struct passage_s -{ - struct passage_s *next; - byte cansee[1]; //all portals that can be seen through this passage -} passage_t; - -typedef enum {stat_none, stat_working, stat_done} vstatus_t; -typedef struct -{ - int num; - qboolean hint; // true if this portal was created from a hint splitter - qboolean removed; - plane_t plane; // normal pointing into neighbor - int leaf; // neighbor - - vec3_t origin; // for fast clip testing - float radius; - - winding_t *winding; - vstatus_t status; - byte *portalfront; // [portals], preliminary - byte *portalflood; // [portals], intermediate - byte *portalvis; // [portals], final - - int nummightsee; // bit count on portalflood for sort - passage_t *passages; // there are just as many passages as there - // are portals in the leaf this portal leads to -} vportal_t; - -#define MAX_PORTALS_ON_LEAF 128 -typedef struct leaf_s -{ - int numportals; - int merged; - vportal_t *portals[MAX_PORTALS_ON_LEAF]; -} leaf_t; - - -typedef struct pstack_s -{ - byte mightsee[MAX_PORTALS/8]; // bit string - struct pstack_s *next; - leaf_t *leaf; - vportal_t *portal; // portal exiting - winding_t *source; - winding_t *pass; - - winding_t windings[3]; // source, pass, temp in any order - int freewindings[3]; - - plane_t portalplane; - int depth; -#ifdef SEPERATORCACHE - plane_t seperators[2][MAX_SEPERATORS]; - int numseperators[2]; -#endif -} pstack_t; - -typedef struct -{ - vportal_t *base; - int c_chains; - pstack_t pstack_head; -} threaddata_t; - - - -extern int numportals; -extern int portalclusters; - -extern vportal_t *portals; -extern leaf_t *leafs; - -extern int c_portaltest, c_portalpass, c_portalcheck; -extern int c_portalskip, c_leafskip; -extern int c_vistest, c_mighttest; -extern int c_chains; - -extern byte *vismap, *vismap_p, *vismap_end; // past visfile - -extern int testlevel; - -extern byte *uncompressed; - -extern int leafbytes, leaflongs; -extern int portalbytes, portallongs; - - -void LeafFlow (int leafnum); - - -void BasePortalVis(int portalnum); -void BetterPortalVis(int portalnum); -void PortalFlow(int portalnum); -void PassagePortalFlow(int portalnum); -void CreatePassages(int portalnum); -void PassageFlow(int portalnum); - -extern vportal_t *sorted_portals[MAX_MAP_PORTALS*2]; - -int CountBits (byte *bits, int numbits); diff --git a/q3map/visflow.c b/q3map/visflow.c deleted file mode 100644 index 5948b08..0000000 --- a/q3map/visflow.c +++ /dev/null @@ -1,1657 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#include "vis.h" - -/* - - each portal will have a list of all possible to see from first portal - - if (!thread->portalmightsee[portalnum]) - - portal mightsee - - for p2 = all other portals in leaf - get sperating planes - for all portals that might be seen by p2 - mark as unseen if not present in seperating plane - flood fill a new mightsee - save as passagemightsee - - - void CalcMightSee (leaf_t *leaf, -*/ - -int CountBits (byte *bits, int numbits) -{ - int i; - int c; - - c = 0; - for (i=0 ; i<numbits ; i++) - if (bits[i>>3] & (1<<(i&7)) ) - c++; - - return c; -} - -int c_fullskip; -int c_portalskip, c_leafskip; -int c_vistest, c_mighttest; - -int c_chop, c_nochop; - -int active; - -void CheckStack (leaf_t *leaf, threaddata_t *thread) -{ - pstack_t *p, *p2; - - for (p=thread->pstack_head.next ; p ; p=p->next) - { -// _printf ("="); - if (p->leaf == leaf) - Error ("CheckStack: leaf recursion"); - for (p2=thread->pstack_head.next ; p2 != p ; p2=p2->next) - if (p2->leaf == p->leaf) - Error ("CheckStack: late leaf recursion"); - } -// _printf ("\n"); -} - - -winding_t *AllocStackWinding (pstack_t *stack) -{ - int i; - - for (i=0 ; i<3 ; i++) - { - if (stack->freewindings[i]) - { - stack->freewindings[i] = 0; - return &stack->windings[i]; - } - } - - Error ("AllocStackWinding: failed"); - - return NULL; -} - -void FreeStackWinding (winding_t *w, pstack_t *stack) -{ - int i; - - i = w - stack->windings; - - if (i<0 || i>2) - return; // not from local - - if (stack->freewindings[i]) - Error ("FreeStackWinding: allready free"); - stack->freewindings[i] = 1; -} - -/* -============== -VisChopWinding - -============== -*/ -winding_t *VisChopWinding (winding_t *in, pstack_t *stack, plane_t *split) -{ - vec_t dists[128]; - int sides[128]; - int counts[3]; - vec_t dot; - int i, j; - vec_t *p1, *p2; - vec3_t mid; - winding_t *neww; - - counts[0] = counts[1] = counts[2] = 0; - - // determine sides for each point - for (i=0 ; i<in->numpoints ; i++) - { - dot = DotProduct (in->points[i], split->normal); - dot -= split->dist; - dists[i] = dot; - if (dot > ON_EPSILON) - sides[i] = SIDE_FRONT; - else if (dot < -ON_EPSILON) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - - if (!counts[1]) - return in; // completely on front side - - if (!counts[0]) - { - FreeStackWinding (in, stack); - return NULL; - } - - sides[i] = sides[0]; - dists[i] = dists[0]; - - neww = AllocStackWinding (stack); - - neww->numpoints = 0; - - for (i=0 ; i<in->numpoints ; i++) - { - p1 = in->points[i]; - - if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING) - { - FreeStackWinding (neww, stack); - return in; // can't chop -- fall back to original - } - - if (sides[i] == SIDE_ON) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING) - { - FreeStackWinding (neww, stack); - return in; // can't chop -- fall back to original - } - - // generate a split point - p2 = in->points[(i+1)%in->numpoints]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (split->normal[j] == 1) - mid[j] = split->dist; - else if (split->normal[j] == -1) - mid[j] = -split->dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, neww->points[neww->numpoints]); - neww->numpoints++; - } - - // free the original winding - FreeStackWinding (in, stack); - - return neww; -} - -/* -============== -ClipToSeperators - -Source, pass, and target are an ordering of portals. - -Generates seperating planes canidates by taking two points from source and one -point from pass, and clips target by them. - -If target is totally clipped away, that portal can not be seen through. - -Normal clip keeps target on the same side as pass, which is correct if the -order goes source, pass, target. If the order goes pass, source, target then -flipclip should be set. -============== -*/ -winding_t *ClipToSeperators (winding_t *source, winding_t *pass, winding_t *target, qboolean flipclip, pstack_t *stack) -{ - int i, j, k, l; - plane_t plane; - vec3_t v1, v2; - float d; - vec_t length; - int counts[3]; - qboolean fliptest; - - // check all combinations - for (i=0 ; i<source->numpoints ; i++) - { - l = (i+1)%source->numpoints; - VectorSubtract (source->points[l] , source->points[i], v1); - - // find a vertex of pass that makes a plane that puts all of the - // vertexes of pass on the front side and all of the vertexes of - // source on the back side - for (j=0 ; j<pass->numpoints ; j++) - { - VectorSubtract (pass->points[j], source->points[i], v2); - - plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1]; - plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2]; - plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0]; - - // if points don't make a valid plane, skip it - - length = plane.normal[0] * plane.normal[0] - + plane.normal[1] * plane.normal[1] - + plane.normal[2] * plane.normal[2]; - - if (length < ON_EPSILON) - continue; - - length = 1/sqrt(length); - - plane.normal[0] *= length; - plane.normal[1] *= length; - plane.normal[2] *= length; - - plane.dist = DotProduct (pass->points[j], plane.normal); - - // - // find out which side of the generated seperating plane has the - // source portal - // -#if 1 - fliptest = qfalse; - for (k=0 ; k<source->numpoints ; k++) - { - if (k == i || k == l) - continue; - d = DotProduct (source->points[k], plane.normal) - plane.dist; - if (d < -ON_EPSILON) - { // source is on the negative side, so we want all - // pass and target on the positive side - fliptest = qfalse; - break; - } - else if (d > ON_EPSILON) - { // source is on the positive side, so we want all - // pass and target on the negative side - fliptest = qtrue; - break; - } - } - if (k == source->numpoints) - continue; // planar with source portal -#else - fliptest = flipclip; -#endif - // - // flip the normal if the source portal is backwards - // - if (fliptest) - { - VectorSubtract (vec3_origin, plane.normal, plane.normal); - plane.dist = -plane.dist; - } -#if 1 - // - // if all of the pass portal points are now on the positive side, - // this is the seperating plane - // - counts[0] = counts[1] = counts[2] = 0; - for (k=0 ; k<pass->numpoints ; k++) - { - if (k==j) - continue; - d = DotProduct (pass->points[k], plane.normal) - plane.dist; - if (d < -ON_EPSILON) - break; - else if (d > ON_EPSILON) - counts[0]++; - else - counts[2]++; - } - if (k != pass->numpoints) - continue; // points on negative side, not a seperating plane - - if (!counts[0]) - continue; // planar with seperating plane -#else - k = (j+1)%pass->numpoints; - d = DotProduct (pass->points[k], plane.normal) - plane.dist; - if (d < -ON_EPSILON) - continue; - k = (j+pass->numpoints-1)%pass->numpoints; - d = DotProduct (pass->points[k], plane.normal) - plane.dist; - if (d < -ON_EPSILON) - continue; -#endif - // - // flip the normal if we want the back side - // - if (flipclip) - { - VectorSubtract (vec3_origin, plane.normal, plane.normal); - plane.dist = -plane.dist; - } - -#ifdef SEPERATORCACHE - stack->seperators[flipclip][stack->numseperators[flipclip]] = plane; - if (++stack->numseperators[flipclip] >= MAX_SEPERATORS) - Error("MAX_SEPERATORS"); -#endif - //MrE: fast check first - d = DotProduct (stack->portal->origin, plane.normal) - plane.dist; - //if completely at the back of the seperator plane - if (d < -stack->portal->radius) - return NULL; - //if completely on the front of the seperator plane - if (d > stack->portal->radius) - break; - - // - // clip target by the seperating plane - // - target = VisChopWinding (target, stack, &plane); - if (!target) - return NULL; // target is not visible - - break; // optimization by Antony Suter - } - } - - return target; -} - -/* -================== -RecursiveLeafFlow - -Flood fill through the leafs -If src_portal is NULL, this is the originating leaf -================== -*/ -void RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack) -{ - pstack_t stack; - vportal_t *p; - plane_t backplane; - leaf_t *leaf; - int i, j, n; - long *test, *might, *prevmight, *vis, more; - int pnum; - - thread->c_chains++; - - leaf = &leafs[leafnum]; -// CheckStack (leaf, thread); - - prevstack->next = &stack; - - stack.next = NULL; - stack.leaf = leaf; - stack.portal = NULL; - stack.depth = prevstack->depth + 1; - -#ifdef SEPERATORCACHE - stack.numseperators[0] = 0; - stack.numseperators[1] = 0; -#endif - - might = (long *)stack.mightsee; - vis = (long *)thread->base->portalvis; - - // check all portals for flowing into other leafs - for (i = 0; i < leaf->numportals; i++) - { - p = leaf->portals[i]; - if (p->removed) - continue; - pnum = p - portals; - - /* MrE: portal trace debug code - { - int portaltrace[] = {13, 16, 17, 37}; - pstack_t *s; - - s = &thread->pstack_head; - for (j = 0; s->next && j < sizeof(portaltrace)/sizeof(int) - 1; j++, s = s->next) - { - if (s->portal->num != portaltrace[j]) - break; - } - if (j >= sizeof(portaltrace)/sizeof(int) - 1) - { - if (p->num == portaltrace[j]) - n = 0; //traced through all the portals - } - } - */ - - if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) ) - { - continue; // can't possibly see it - } - - // if the portal can't see anything we haven't allready seen, skip it - if (p->status == stat_done) - { - test = (long *)p->portalvis; - } - else - { - test = (long *)p->portalflood; - } - - more = 0; - prevmight = (long *)prevstack->mightsee; - for (j=0 ; j<portallongs ; j++) - { - might[j] = prevmight[j] & test[j]; - more |= (might[j] & ~vis[j]); - } - - if (!more && - (thread->base->portalvis[pnum>>3] & (1<<(pnum&7))) ) - { // can't see anything new - continue; - } - - // get plane of portal, point normal into the neighbor leaf - stack.portalplane = p->plane; - VectorSubtract (vec3_origin, p->plane.normal, backplane.normal); - backplane.dist = -p->plane.dist; - -// c_portalcheck++; - - stack.portal = p; - stack.next = NULL; - stack.freewindings[0] = 1; - stack.freewindings[1] = 1; - stack.freewindings[2] = 1; - -#if 1 - { - float d; - - d = DotProduct (p->origin, thread->pstack_head.portalplane.normal); - d -= thread->pstack_head.portalplane.dist; - if (d < -p->radius) - { - continue; - } - else if (d > p->radius) - { - stack.pass = p->winding; - } - else - { - stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane); - if (!stack.pass) - continue; - } - } -#else - stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane); - if (!stack.pass) - continue; -#endif - - -#if 1 - { - float d; - - d = DotProduct (thread->base->origin, p->plane.normal); - d -= p->plane.dist; - //MrE: vis-bug fix - //if (d > p->radius) - if (d > thread->base->radius) - { - continue; - } - //MrE: vis-bug fix - //if (d < -p->radius) - else if (d < -thread->base->radius) - { - stack.source = prevstack->source; - } - else - { - stack.source = VisChopWinding (prevstack->source, &stack, &backplane); - //FIXME: shouldn't we create a new source origin and radius for fast checks? - if (!stack.source) - continue; - } - } -#else - stack.source = VisChopWinding (prevstack->source, &stack, &backplane); - if (!stack.source) - continue; -#endif - - if (!prevstack->pass) - { // the second leaf can only be blocked if coplanar - - // mark the portal as visible - thread->base->portalvis[pnum>>3] |= (1<<(pnum&7)); - - RecursiveLeafFlow (p->leaf, thread, &stack); - continue; - } - -#ifdef SEPERATORCACHE - if (stack.numseperators[0]) - { - for (n = 0; n < stack.numseperators[0]; n++) - { - stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[0][n]); - if (!stack.pass) - break; // target is not visible - } - if (n < stack.numseperators[0]) - continue; - } - else - { - stack.pass = ClipToSeperators (prevstack->source, prevstack->pass, stack.pass, qfalse, &stack); - } -#else - stack.pass = ClipToSeperators (stack.source, prevstack->pass, stack.pass, qfalse, &stack); -#endif - if (!stack.pass) - continue; - -#ifdef SEPERATORCACHE - if (stack.numseperators[1]) - { - for (n = 0; n < stack.numseperators[1]; n++) - { - stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[1][n]); - if (!stack.pass) - break; // target is not visible - } - } - else - { - stack.pass = ClipToSeperators (prevstack->pass, prevstack->source, stack.pass, qtrue, &stack); - } -#else - stack.pass = ClipToSeperators (prevstack->pass, stack.source, stack.pass, qtrue, &stack); -#endif - if (!stack.pass) - continue; - - // mark the portal as visible - thread->base->portalvis[pnum>>3] |= (1<<(pnum&7)); - - // flow through it for real - RecursiveLeafFlow (p->leaf, thread, &stack); - // - stack.next = NULL; - } -} - -/* -=============== -PortalFlow - -generates the portalvis bit vector -=============== -*/ -void PortalFlow (int portalnum) -{ - threaddata_t data; - int i; - vportal_t *p; - int c_might, c_can; - -#ifdef MREDEBUG - _printf("\r%6d", portalnum); -#endif - - p = sorted_portals[portalnum]; - - if (p->removed) - { - p->status = stat_done; - return; - } - - p->status = stat_working; - - c_might = CountBits (p->portalflood, numportals*2); - - memset (&data, 0, sizeof(data)); - data.base = p; - - data.pstack_head.portal = p; - data.pstack_head.source = p->winding; - data.pstack_head.portalplane = p->plane; - data.pstack_head.depth = 0; - for (i=0 ; i<portallongs ; i++) - ((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i]; - - RecursiveLeafFlow (p->leaf, &data, &data.pstack_head); - - p->status = stat_done; - - c_can = CountBits (p->portalvis, numportals*2); - - qprintf ("portal:%4i mightsee:%4i cansee:%4i (%i chains)\n", - (int)(p - portals), c_might, c_can, data.c_chains); -} - -/* -================== -RecursivePassageFlow -================== -*/ -void RecursivePassageFlow (vportal_t *portal, threaddata_t *thread, pstack_t *prevstack) -{ - pstack_t stack; - vportal_t *p; - leaf_t *leaf; - passage_t *passage, *nextpassage; - int i, j; - long *might, *vis, *prevmight, *cansee, *portalvis, more; - int pnum; - - leaf = &leafs[portal->leaf]; - - prevstack->next = &stack; - - stack.next = NULL; - stack.depth = prevstack->depth + 1; - - vis = (long *)thread->base->portalvis; - - passage = portal->passages; - nextpassage = passage; - // check all portals for flowing into other leafs - for (i = 0; i < leaf->numportals; i++, passage = nextpassage) - { - p = leaf->portals[i]; - if ( p->removed ) { - continue; - } - nextpassage = passage->next; - pnum = p - portals; - - if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) ) { - continue; // can't possibly see it - } - - // mark the portal as visible - thread->base->portalvis[pnum>>3] |= (1<<(pnum&7)); - - prevmight = (long *)prevstack->mightsee; - cansee = (long *)passage->cansee; - might = (long *)stack.mightsee; - memcpy(might, prevmight, portalbytes); - if (p->status == stat_done) - portalvis = (long *) p->portalvis; - else - portalvis = (long *) p->portalflood; - more = 0; - for (j = 0; j < portallongs; j++) - { - if (*might) - { - *might &= *cansee++ & *portalvis++; - more |= (*might & ~vis[j]); - } - else - { - cansee++; - portalvis++; - } - might++; - } - - if ( !more ) { - // can't see anything new - continue; - } - - // flow through it for real - RecursivePassageFlow(p, thread, &stack); - - stack.next = NULL; - } -} - -/* -=============== -PassageFlow -=============== -*/ -void PassageFlow (int portalnum) -{ - threaddata_t data; - int i; - vportal_t *p; -// int c_might, c_can; - -#ifdef MREDEBUG - _printf("\r%6d", portalnum); -#endif - - p = sorted_portals[portalnum]; - - if (p->removed) - { - p->status = stat_done; - return; - } - - p->status = stat_working; - -// c_might = CountBits (p->portalflood, numportals*2); - - memset (&data, 0, sizeof(data)); - data.base = p; - - data.pstack_head.portal = p; - data.pstack_head.source = p->winding; - data.pstack_head.portalplane = p->plane; - data.pstack_head.depth = 0; - for (i=0 ; i<portallongs ; i++) - ((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i]; - - RecursivePassageFlow (p, &data, &data.pstack_head); - - p->status = stat_done; - - /* - c_can = CountBits (p->portalvis, numportals*2); - - qprintf ("portal:%4i mightsee:%4i cansee:%4i (%i chains)\n", - (int)(p - portals), c_might, c_can, data.c_chains); - */ -} - -/* -================== -RecursivePassagePortalFlow -================== -*/ -void RecursivePassagePortalFlow (vportal_t *portal, threaddata_t *thread, pstack_t *prevstack) -{ - pstack_t stack; - vportal_t *p; - leaf_t *leaf; - plane_t backplane; - passage_t *passage, *nextpassage; - int i, j, n; - long *might, *vis, *prevmight, *cansee, *portalvis, more; - int pnum; - -// thread->c_chains++; - - leaf = &leafs[portal->leaf]; -// CheckStack (leaf, thread); - - prevstack->next = &stack; - - stack.next = NULL; - stack.leaf = leaf; - stack.portal = NULL; - stack.depth = prevstack->depth + 1; - -#ifdef SEPERATORCACHE - stack.numseperators[0] = 0; - stack.numseperators[1] = 0; -#endif - - vis = (long *)thread->base->portalvis; - - passage = portal->passages; - nextpassage = passage; - // check all portals for flowing into other leafs - for (i = 0; i < leaf->numportals; i++, passage = nextpassage) - { - p = leaf->portals[i]; - if (p->removed) - continue; - nextpassage = passage->next; - pnum = p - portals; - - if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) ) - continue; // can't possibly see it - - prevmight = (long *)prevstack->mightsee; - cansee = (long *)passage->cansee; - might = (long *)stack.mightsee; - memcpy(might, prevmight, portalbytes); - if (p->status == stat_done) - portalvis = (long *) p->portalvis; - else - portalvis = (long *) p->portalflood; - more = 0; - for (j = 0; j < portallongs; j++) - { - if (*might) - { - *might &= *cansee++ & *portalvis++; - more |= (*might & ~vis[j]); - } - else - { - cansee++; - portalvis++; - } - might++; - } - - if (!more && (thread->base->portalvis[pnum>>3] & (1<<(pnum&7))) ) - { // can't see anything new - continue; - } - - // get plane of portal, point normal into the neighbor leaf - stack.portalplane = p->plane; - VectorSubtract (vec3_origin, p->plane.normal, backplane.normal); - backplane.dist = -p->plane.dist; - -// c_portalcheck++; - - stack.portal = p; - stack.next = NULL; - stack.freewindings[0] = 1; - stack.freewindings[1] = 1; - stack.freewindings[2] = 1; - -#if 1 - { - float d; - - d = DotProduct (p->origin, thread->pstack_head.portalplane.normal); - d -= thread->pstack_head.portalplane.dist; - if (d < -p->radius) - { - continue; - } - else if (d > p->radius) - { - stack.pass = p->winding; - } - else - { - stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane); - if (!stack.pass) - continue; - } - } -#else - stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane); - if (!stack.pass) - continue; -#endif - - -#if 1 - { - float d; - - d = DotProduct (thread->base->origin, p->plane.normal); - d -= p->plane.dist; - //MrE: vis-bug fix - //if (d > p->radius) - if (d > thread->base->radius) - { - continue; - } - //MrE: vis-bug fix - //if (d < -p->radius) - else if (d < -thread->base->radius) - { - stack.source = prevstack->source; - } - else - { - stack.source = VisChopWinding (prevstack->source, &stack, &backplane); - //FIXME: shouldn't we create a new source origin and radius for fast checks? - if (!stack.source) - continue; - } - } -#else - stack.source = VisChopWinding (prevstack->source, &stack, &backplane); - if (!stack.source) - continue; -#endif - - if (!prevstack->pass) - { // the second leaf can only be blocked if coplanar - - // mark the portal as visible - thread->base->portalvis[pnum>>3] |= (1<<(pnum&7)); - - RecursivePassagePortalFlow (p, thread, &stack); - continue; - } - -#ifdef SEPERATORCACHE - if (stack.numseperators[0]) - { - for (n = 0; n < stack.numseperators[0]; n++) - { - stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[0][n]); - if (!stack.pass) - break; // target is not visible - } - if (n < stack.numseperators[0]) - continue; - } - else - { - stack.pass = ClipToSeperators (prevstack->source, prevstack->pass, stack.pass, qfalse, &stack); - } -#else - stack.pass = ClipToSeperators (stack.source, prevstack->pass, stack.pass, qfalse, &stack); -#endif - if (!stack.pass) - continue; - -#ifdef SEPERATORCACHE - if (stack.numseperators[1]) - { - for (n = 0; n < stack.numseperators[1]; n++) - { - stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[1][n]); - if (!stack.pass) - break; // target is not visible - } - } - else - { - stack.pass = ClipToSeperators (prevstack->pass, prevstack->source, stack.pass, qtrue, &stack); - } -#else - stack.pass = ClipToSeperators (prevstack->pass, stack.source, stack.pass, qtrue, &stack); -#endif - if (!stack.pass) - continue; - - // mark the portal as visible - thread->base->portalvis[pnum>>3] |= (1<<(pnum&7)); - - // flow through it for real - RecursivePassagePortalFlow(p, thread, &stack); - // - stack.next = NULL; - } -} - -/* -=============== -PassagePortalFlow -=============== -*/ -void PassagePortalFlow (int portalnum) -{ - threaddata_t data; - int i; - vportal_t *p; -// int c_might, c_can; - -#ifdef MREDEBUG - _printf("\r%6d", portalnum); -#endif - - p = sorted_portals[portalnum]; - - if (p->removed) - { - p->status = stat_done; - return; - } - - p->status = stat_working; - -// c_might = CountBits (p->portalflood, numportals*2); - - memset (&data, 0, sizeof(data)); - data.base = p; - - data.pstack_head.portal = p; - data.pstack_head.source = p->winding; - data.pstack_head.portalplane = p->plane; - data.pstack_head.depth = 0; - for (i=0 ; i<portallongs ; i++) - ((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i]; - - RecursivePassagePortalFlow (p, &data, &data.pstack_head); - - p->status = stat_done; - - /* - c_can = CountBits (p->portalvis, numportals*2); - - qprintf ("portal:%4i mightsee:%4i cansee:%4i (%i chains)\n", - (int)(p - portals), c_might, c_can, data.c_chains); - */ -} - -winding_t *PassageChopWinding (winding_t *in, winding_t *out, plane_t *split) -{ - vec_t dists[128]; - int sides[128]; - int counts[3]; - vec_t dot; - int i, j; - vec_t *p1, *p2; - vec3_t mid; - winding_t *neww; - - counts[0] = counts[1] = counts[2] = 0; - - // determine sides for each point - for (i=0 ; i<in->numpoints ; i++) - { - dot = DotProduct (in->points[i], split->normal); - dot -= split->dist; - dists[i] = dot; - if (dot > ON_EPSILON) - sides[i] = SIDE_FRONT; - else if (dot < -ON_EPSILON) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - - if (!counts[1]) - return in; // completely on front side - - if (!counts[0]) - { - return NULL; - } - - sides[i] = sides[0]; - dists[i] = dists[0]; - - neww = out; - - neww->numpoints = 0; - - for (i=0 ; i<in->numpoints ; i++) - { - p1 = in->points[i]; - - if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING) - { - return in; // can't chop -- fall back to original - } - - if (sides[i] == SIDE_ON) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING) - { - return in; // can't chop -- fall back to original - } - - // generate a split point - p2 = in->points[(i+1)%in->numpoints]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (split->normal[j] == 1) - mid[j] = split->dist; - else if (split->normal[j] == -1) - mid[j] = -split->dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, neww->points[neww->numpoints]); - neww->numpoints++; - } - - return neww; -} - -/* -=============== -AddSeperators -=============== -*/ -int AddSeperators (winding_t *source, winding_t *pass, qboolean flipclip, plane_t *seperators, int maxseperators) -{ - int i, j, k, l; - plane_t plane; - vec3_t v1, v2; - float d; - vec_t length; - int counts[3], numseperators; - qboolean fliptest; - - numseperators = 0; - // check all combinations - for (i=0 ; i<source->numpoints ; i++) - { - l = (i+1)%source->numpoints; - VectorSubtract (source->points[l] , source->points[i], v1); - - // find a vertex of pass that makes a plane that puts all of the - // vertexes of pass on the front side and all of the vertexes of - // source on the back side - for (j=0 ; j<pass->numpoints ; j++) - { - VectorSubtract (pass->points[j], source->points[i], v2); - - plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1]; - plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2]; - plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0]; - - // if points don't make a valid plane, skip it - - length = plane.normal[0] * plane.normal[0] - + plane.normal[1] * plane.normal[1] - + plane.normal[2] * plane.normal[2]; - - if (length < ON_EPSILON) - continue; - - length = 1/sqrt(length); - - plane.normal[0] *= length; - plane.normal[1] *= length; - plane.normal[2] *= length; - - plane.dist = DotProduct (pass->points[j], plane.normal); - - // - // find out which side of the generated seperating plane has the - // source portal - // -#if 1 - fliptest = qfalse; - for (k=0 ; k<source->numpoints ; k++) - { - if (k == i || k == l) - continue; - d = DotProduct (source->points[k], plane.normal) - plane.dist; - if (d < -ON_EPSILON) - { // source is on the negative side, so we want all - // pass and target on the positive side - fliptest = qfalse; - break; - } - else if (d > ON_EPSILON) - { // source is on the positive side, so we want all - // pass and target on the negative side - fliptest = qtrue; - break; - } - } - if (k == source->numpoints) - continue; // planar with source portal -#else - fliptest = flipclip; -#endif - // - // flip the normal if the source portal is backwards - // - if (fliptest) - { - VectorSubtract (vec3_origin, plane.normal, plane.normal); - plane.dist = -plane.dist; - } -#if 1 - // - // if all of the pass portal points are now on the positive side, - // this is the seperating plane - // - counts[0] = counts[1] = counts[2] = 0; - for (k=0 ; k<pass->numpoints ; k++) - { - if (k==j) - continue; - d = DotProduct (pass->points[k], plane.normal) - plane.dist; - if (d < -ON_EPSILON) - break; - else if (d > ON_EPSILON) - counts[0]++; - else - counts[2]++; - } - if (k != pass->numpoints) - continue; // points on negative side, not a seperating plane - - if (!counts[0]) - continue; // planar with seperating plane -#else - k = (j+1)%pass->numpoints; - d = DotProduct (pass->points[k], plane.normal) - plane.dist; - if (d < -ON_EPSILON) - continue; - k = (j+pass->numpoints-1)%pass->numpoints; - d = DotProduct (pass->points[k], plane.normal) - plane.dist; - if (d < -ON_EPSILON) - continue; -#endif - // - // flip the normal if we want the back side - // - if (flipclip) - { - VectorSubtract (vec3_origin, plane.normal, plane.normal); - plane.dist = -plane.dist; - } - - if (numseperators >= maxseperators) - Error("max seperators"); - seperators[numseperators] = plane; - numseperators++; - break; - } - } - return numseperators; -} - -/* -=============== -CreatePassages - -MrE: create passages from one portal to all the portals in the leaf the portal leads to - every passage has a cansee bit string with all the portals that can be - seen through the passage -=============== -*/ -void CreatePassages(int portalnum) -{ - int i, j, k, n, numseperators, numsee; - float d; - vportal_t *portal, *p, *target; - leaf_t *leaf; - passage_t *passage, *lastpassage; - plane_t seperators[MAX_SEPERATORS*2]; - winding_t *w; - winding_t in, out, *res; - -#ifdef MREDEBUG - _printf("\r%6d", portalnum); -#endif - - portal = sorted_portals[portalnum]; - - if (portal->removed) - { - portal->status = stat_done; - return; - } - - lastpassage = NULL; - leaf = &leafs[portal->leaf]; - for (i = 0; i < leaf->numportals; i++) - { - target = leaf->portals[i]; - if (target->removed) - continue; - - passage = (passage_t *) malloc(sizeof(passage_t) + portalbytes); - memset(passage, 0, sizeof(passage_t) + portalbytes); - numseperators = AddSeperators(portal->winding, target->winding, qfalse, seperators, MAX_SEPERATORS*2); - numseperators += AddSeperators(target->winding, portal->winding, qtrue, &seperators[numseperators], MAX_SEPERATORS*2-numseperators); - - passage->next = NULL; - if (lastpassage) - lastpassage->next = passage; - else - portal->passages = passage; - lastpassage = passage; - - numsee = 0; - //create the passage->cansee - for (j = 0; j < numportals * 2; j++) - { - p = &portals[j]; - if (p->removed) - continue; - if ( ! (target->portalflood[j >> 3] & (1<<(j&7)) ) ) - continue; - if ( ! (portal->portalflood[j >> 3] & (1<<(j&7)) ) ) - continue; - for (k = 0; k < numseperators; k++) - { - // - d = DotProduct (p->origin, seperators[k].normal) - seperators[k].dist; - //if completely at the back of the seperator plane - if (d < -p->radius + ON_EPSILON) - break; - w = p->winding; - for (n = 0; n < w->numpoints; n++) - { - d = DotProduct (w->points[n], seperators[k].normal) - seperators[k].dist; - //if at the front of the seperator - if (d > ON_EPSILON) - break; - } - //if no points are at the front of the seperator - if (n >= w->numpoints) - break; - } - if (k < numseperators) - continue; - memcpy(&in, p->winding, sizeof(winding_t)); - for (k = 0; k < numseperators; k++) - { - res = PassageChopWinding(&in, &out, &seperators[k]); - if (res == &out) - memcpy(&in, &out, sizeof(winding_t)); - if (res == NULL) - break; - } - if (k < numseperators) - continue; - passage->cansee[j >> 3] |= (1<<(j&7)); - numsee++; - } - } -} - -void PassageMemory(void) -{ - int i, j, totalmem, totalportals; - vportal_t *portal, *target; - leaf_t *leaf; - - totalmem = 0; - totalportals = 0; - for (i = 0; i < numportals; i++) - { - portal = sorted_portals[i]; - if (portal->removed) - continue; - leaf = &leafs[portal->leaf]; - for (j = 0; j < leaf->numportals; j++) - { - target = leaf->portals[j]; - if (target->removed) - continue; - totalmem += sizeof(passage_t) + portalbytes; - totalportals++; - } - } - _printf("%7i average number of passages per leaf\n", totalportals / numportals); - _printf("%7i MB required passage memory\n", totalmem >> 10 >> 10); -} - -/* -=============================================================================== - -This is a rough first-order aproximation that is used to trivially reject some -of the final calculations. - - -Calculates portalfront and portalflood bit vectors - -thinking about: - -typedef struct passage_s -{ - struct passage_s *next; - struct portal_s *to; - stryct sep_s *seperators; - byte *mightsee; -} passage_t; - -typedef struct portal_s -{ - struct passage_s *passages; - int leaf; // leaf portal faces into -} portal_s; - -leaf = portal->leaf -clear -for all portals - - -calc portal visibility - clear bit vector - for all passages - passage visibility - - -for a portal to be visible to a passage, it must be on the front of -all seperating planes, and both portals must be behind the new portal - -=============================================================================== -*/ - -int c_flood, c_vis; - - -/* -================== -SimpleFlood - -================== -*/ -void SimpleFlood (vportal_t *srcportal, int leafnum) -{ - int i; - leaf_t *leaf; - vportal_t *p; - int pnum; - - leaf = &leafs[leafnum]; - - for (i=0 ; i<leaf->numportals ; i++) - { - p = leaf->portals[i]; - if (p->removed) - continue; - pnum = p - portals; - if ( ! (srcportal->portalfront[pnum>>3] & (1<<(pnum&7)) ) ) - continue; - - if (srcportal->portalflood[pnum>>3] & (1<<(pnum&7)) ) - continue; - - srcportal->portalflood[pnum>>3] |= (1<<(pnum&7)); - - SimpleFlood (srcportal, p->leaf); - } -} - -/* -============== -BasePortalVis -============== -*/ -void BasePortalVis (int portalnum) -{ - int j, k; - vportal_t *tp, *p; - float d; - winding_t *w; - - p = portals+portalnum; - - if (p->removed) - return; - - p->portalfront = malloc (portalbytes); - memset (p->portalfront, 0, portalbytes); - - p->portalflood = malloc (portalbytes); - memset (p->portalflood, 0, portalbytes); - - p->portalvis = malloc (portalbytes); - memset (p->portalvis, 0, portalbytes); - - for (j=0, tp = portals ; j<numportals*2 ; j++, tp++) - { - if (j == portalnum) - continue; - if (tp->removed) - continue; - /* - if (farplanedist >= 0) - { - vec3_t dir; - VectorSubtract(p->origin, tp->origin, dir); - if (VectorLength(dir) > farplanedist - p->radius - tp->radius) - continue; - } - */ - w = tp->winding; - for (k=0 ; k<w->numpoints ; k++) - { - d = DotProduct (w->points[k], p->plane.normal) - - p->plane.dist; - if (d > ON_EPSILON) - break; - } - if (k == w->numpoints) - continue; // no points on front - - w = p->winding; - for (k=0 ; k<w->numpoints ; k++) - { - d = DotProduct (w->points[k], tp->plane.normal) - - tp->plane.dist; - if (d < -ON_EPSILON) - break; - } - if (k == w->numpoints) - continue; // no points on front - - p->portalfront[j>>3] |= (1<<(j&7)); - } - - SimpleFlood (p, p->leaf); - - p->nummightsee = CountBits (p->portalflood, numportals*2); -// _printf ("portal %i: %i mightsee\n", portalnum, p->nummightsee); - c_flood += p->nummightsee; -} - - - - - -/* -=============================================================================== - -This is a second order aproximation - -Calculates portalvis bit vector - -WAAAAAAY too slow. - -=============================================================================== -*/ - -/* -================== -RecursiveLeafBitFlow - -================== -*/ -void RecursiveLeafBitFlow (int leafnum, byte *mightsee, byte *cansee) -{ - vportal_t *p; - leaf_t *leaf; - int i, j; - long more; - int pnum; - byte newmight[MAX_PORTALS/8]; - - leaf = &leafs[leafnum]; - - // check all portals for flowing into other leafs - for (i=0 ; i<leaf->numportals ; i++) - { - p = leaf->portals[i]; - if (p->removed) - continue; - pnum = p - portals; - - // if some previous portal can't see it, skip - if (! (mightsee[pnum>>3] & (1<<(pnum&7)) ) ) - continue; - - // if this portal can see some portals we mightsee, recurse - more = 0; - for (j=0 ; j<portallongs ; j++) - { - ((long *)newmight)[j] = ((long *)mightsee)[j] - & ((long *)p->portalflood)[j]; - more |= ((long *)newmight)[j] & ~((long *)cansee)[j]; - } - - if (!more) - continue; // can't see anything new - - cansee[pnum>>3] |= (1<<(pnum&7)); - - RecursiveLeafBitFlow (p->leaf, newmight, cansee); - } -} - -/* -============== -BetterPortalVis -============== -*/ -void BetterPortalVis (int portalnum) -{ - vportal_t *p; - - p = portals+portalnum; - - if (p->removed) - return; - - RecursiveLeafBitFlow (p->leaf, p->portalflood, p->portalvis); - - // build leaf vis information - p->nummightsee = CountBits (p->portalvis, numportals*2); - c_vis += p->nummightsee; -} - - diff --git a/q3map/writebsp.c b/q3map/writebsp.c deleted file mode 100644 index 7b9e3ff..0000000 --- a/q3map/writebsp.c +++ /dev/null @@ -1,418 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#include "qbsp.h" - -/* -============ -EmitShader -============ -*/ -int EmitShader( const char *shader ) { - int i; - shaderInfo_t *si; - - if ( !shader ) { - shader = "noshader"; - } - - for ( i = 0 ; i < numShaders ; i++ ) { - if ( !Q_stricmp( shader, dshaders[i].shader ) ) { - return i; - } - } - - if ( i == MAX_MAP_SHADERS ) { - Error( "MAX_MAP_SHADERS" ); - } - numShaders++; - strcpy( dshaders[i].shader, shader ); - - si = ShaderInfoForShader( shader ); - dshaders[i].surfaceFlags = si->surfaceFlags; - dshaders[i].contentFlags = si->contents; - - return i; -} - - -/* -============ -EmitPlanes - -There is no oportunity to discard planes, because all of the original -brushes will be saved in the map. -============ -*/ -void EmitPlanes (void) -{ - int i; - dplane_t *dp; - plane_t *mp; - - mp = mapplanes; - for (i=0 ; i<nummapplanes ; i++, mp++) - { - dp = &dplanes[numplanes]; - VectorCopy ( mp->normal, dp->normal); - dp->dist = mp->dist; - numplanes++; - } -} - - - -/* -================== -EmitLeaf -================== -*/ -void EmitLeaf (node_t *node) -{ - dleaf_t *leaf_p; - bspbrush_t *b; - drawSurfRef_t *dsr; - - // emit a leaf - if (numleafs >= MAX_MAP_LEAFS) - Error ("MAX_MAP_LEAFS"); - - leaf_p = &dleafs[numleafs]; - numleafs++; - - leaf_p->cluster = node->cluster; - leaf_p->area = node->area; - - // - // write bounding box info - // - VectorCopy (node->mins, leaf_p->mins); - VectorCopy (node->maxs, leaf_p->maxs); - - // - // write the leafbrushes - // - leaf_p->firstLeafBrush = numleafbrushes; - for ( b = node->brushlist ; b ; b = b->next ) { - if ( numleafbrushes >= MAX_MAP_LEAFBRUSHES ) { - Error( "MAX_MAP_LEAFBRUSHES" ); - } - dleafbrushes[numleafbrushes] = b->original->outputNumber; - numleafbrushes++; - } - leaf_p->numLeafBrushes = numleafbrushes - leaf_p->firstLeafBrush; - - // - // write the surfaces visible in this leaf - // - if ( node->opaque ) { - return; // no leaffaces in solids - } - - // add the drawSurfRef_t drawsurfs - leaf_p->firstLeafSurface = numleafsurfaces; - for ( dsr = node->drawSurfReferences ; dsr ; dsr = dsr->nextRef ) { - if ( numleafsurfaces >= MAX_MAP_LEAFFACES) - Error ("MAX_MAP_LEAFFACES"); - dleafsurfaces[numleafsurfaces] = dsr->outputNumber; - numleafsurfaces++; - } - - - leaf_p->numLeafSurfaces = numleafsurfaces - leaf_p->firstLeafSurface; -} - - -/* -============ -EmitDrawNode_r -============ -*/ -int EmitDrawNode_r (node_t *node) -{ - dnode_t *n; - int i; - - if (node->planenum == PLANENUM_LEAF) - { - EmitLeaf (node); - return -numleafs; - } - - // emit a node - if (numnodes == MAX_MAP_NODES) - Error ("MAX_MAP_NODES"); - n = &dnodes[numnodes]; - numnodes++; - - VectorCopy (node->mins, n->mins); - VectorCopy (node->maxs, n->maxs); - - if (node->planenum & 1) - Error ("WriteDrawNodes_r: odd planenum"); - n->planeNum = node->planenum; - - // - // recursively output the other nodes - // - for (i=0 ; i<2 ; i++) - { - if (node->children[i]->planenum == PLANENUM_LEAF) - { - n->children[i] = -(numleafs + 1); - EmitLeaf (node->children[i]); - } - else - { - n->children[i] = numnodes; - EmitDrawNode_r (node->children[i]); - } - } - - return n - dnodes; -} - -//========================================================= - - - -/* -============ -SetModelNumbers -============ -*/ -void SetModelNumbers (void) -{ - int i; - int models; - char value[10]; - - models = 1; - for ( i=1 ; i<num_entities ; i++ ) { - if ( entities[i].brushes || entities[i].patches ) { - sprintf ( value, "*%i", models ); - models++; - SetKeyValue (&entities[i], "model", value); - } - } - -} - -/* -============ -SetLightStyles -============ -*/ -#define MAX_SWITCHED_LIGHTS 32 -void SetLightStyles (void) -{ - int stylenum; - const char *t; - entity_t *e; - int i, j; - char value[10]; - char lighttargets[MAX_SWITCHED_LIGHTS][64]; - - - // any light that is controlled (has a targetname) - // must have a unique style number generated for it - - stylenum = 0; - for (i=1 ; i<num_entities ; i++) - { - e = &entities[i]; - - t = ValueForKey (e, "classname"); - if (Q_strncasecmp (t, "light", 5)) - continue; - t = ValueForKey (e, "targetname"); - if (!t[0]) - continue; - - // find this targetname - for (j=0 ; j<stylenum ; j++) - if (!strcmp (lighttargets[j], t)) - break; - if (j == stylenum) - { - if (stylenum == MAX_SWITCHED_LIGHTS) - Error ("stylenum == MAX_SWITCHED_LIGHTS"); - strcpy (lighttargets[j], t); - stylenum++; - } - sprintf (value, "%i", 32 + j); - SetKeyValue (e, "style", value); - } - -} - -//=========================================================== - -/* -================== -BeginBSPFile -================== -*/ -void BeginBSPFile( void ) { - // these values may actually be initialized - // if the file existed when loaded, so clear them explicitly - nummodels = 0; - numnodes = 0; - numbrushsides = 0; - numleafsurfaces = 0; - numleafbrushes = 0; - - // leave leaf 0 as an error, because leafs are referenced as - // negative number nodes - numleafs = 1; -} - - -/* -============ -EndBSPFile -============ -*/ -void EndBSPFile( void ) { - char path[1024]; - - EmitPlanes (); - UnparseEntities (); - - // write the map - sprintf (path, "%s.bsp", source); - _printf ("Writing %s\n", path); - WriteBSPFile (path); -} - - -//=========================================================== - -/* -============ -EmitBrushes -============ -*/ -void EmitBrushes ( bspbrush_t *brushes ) { - int j; - dbrush_t *db; - bspbrush_t *b; - dbrushside_t *cp; - - for ( b = brushes ; b ; b = b->next ) { - if ( numbrushes == MAX_MAP_BRUSHES ) { - Error( "MAX_MAP_BRUSHES" ); - } - b->outputNumber = numbrushes; - db = &dbrushes[numbrushes]; - numbrushes++; - - db->shaderNum = EmitShader( b->contentShader->shader ); - db->firstSide = numbrushsides; - - // don't emit any generated backSide sides - db->numSides = 0; - for ( j=0 ; j<b->numsides ; j++ ) { - if ( b->sides[j].backSide ) { - continue; - } - if ( numbrushsides == MAX_MAP_BRUSHSIDES ) { - Error( "MAX_MAP_BRUSHSIDES "); - } - cp = &dbrushsides[numbrushsides]; - db->numSides++; - numbrushsides++; - cp->planeNum = b->sides[j].planenum; - cp->shaderNum = EmitShader( b->sides[j].shaderInfo->shader ); - } - } - -} - - -/* -================== -BeginModel -================== -*/ -void BeginModel( void ) { - dmodel_t *mod; - bspbrush_t *b; - entity_t *e; - vec3_t mins, maxs; - parseMesh_t *p; - int i; - - if ( nummodels == MAX_MAP_MODELS ) { - Error( "MAX_MAP_MODELS" ); - } - mod = &dmodels[nummodels]; - - // - // bound the brushes - // - e = &entities[entity_num]; - - ClearBounds (mins, maxs); - for ( b = e->brushes ; b ; b = b->next ) { - if ( !b->numsides ) { - continue; // not a real brush (origin brush, etc) - } - AddPointToBounds (b->mins, mins, maxs); - AddPointToBounds (b->maxs, mins, maxs); - } - - for ( p = e->patches ; p ; p = p->next ) { - for ( i = 0 ; i < p->mesh.width * p->mesh.height ; i++ ) { - AddPointToBounds( p->mesh.verts[i].xyz, mins, maxs ); - } - } - - VectorCopy (mins, mod->mins); - VectorCopy (maxs, mod->maxs); - - mod->firstSurface = numDrawSurfaces; - mod->firstBrush = numbrushes; - - EmitBrushes( e->brushes ); -} - - - - -/* -================== -EndModel -================== -*/ -void EndModel( node_t *headnode ) { - dmodel_t *mod; - - qprintf ("--- EndModel ---\n"); - - mod = &dmodels[nummodels]; - EmitDrawNode_r (headnode); - mod->numSurfaces = numDrawSurfaces - mod->firstSurface; - mod->numBrushes = numbrushes - mod->firstBrush; - - nummodels++; -} - |