-/*
+/* -------------------------------------------------------------------------------
+
Copyright (C) 1999-2007 id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
/*
-AlphaMod()
-routines for dealing with vertex alpha modification
+ColorMod()
+routines for dealing with vertex color/alpha modification
*/
-void AlphaMod( alphaMod_t *am, int numVerts, bspDrawVert_t *drawVerts )
+void ColorMod( colorMod_t *cm, int numVerts, bspDrawVert_t *drawVerts )
{
- int i, j;
- float mult, add, a;
+ int i, j, k;
+ float c;
+ vec4_t mult, add;
bspDrawVert_t *dv;
- alphaMod_t *am2;
+ colorMod_t *cm2;
/* dummy check */
- if( am == NULL || numVerts < 1 || drawVerts == NULL )
+ if( cm == NULL || numVerts < 1 || drawVerts == NULL )
return;
/* get vertex */
dv = &drawVerts[ i ];
- /* walk alphamod list */
- for( am2 = am; am2 != NULL; am2 = am2->next )
+ /* walk colorMod list */
+ for( cm2 = cm; cm2 != NULL; cm2 = cm2->next )
{
+ /* default */
+ VectorSet( mult, 1.0f, 1.0f, 1.0f );
+ mult[ 3 ] = 1.0f;
+ VectorSet( add, 0.0f, 0.0f, 0.0f );
+ mult[ 3 ] = 0.0f;
+
/* switch on type */
- switch( am->type )
+ switch( cm2->type )
{
- case AM_DOT_PRODUCT:
- mult = DotProduct( dv->normal, am2->data );
- add = 0.0f;
+ case CM_COLOR_SET:
+ VectorClear( mult );
+ VectorScale( cm2->data, 255.0f, add );
+ break;
+
+ case CM_ALPHA_SET:
+ mult[ 3 ] = 0.0f;
+ add[ 3 ] = cm2->data[ 0 ] * 255.0f;
+ break;
+
+ case CM_COLOR_SCALE:
+ VectorCopy( cm2->data, mult );
+ break;
+
+ case CM_ALPHA_SCALE:
+ mult[ 3 ] = cm2->data[ 0 ];
+ break;
+
+ case CM_COLOR_DOT_PRODUCT:
+ c = DotProduct( dv->normal, cm2->data );
+ VectorSet( mult, c, c, c );
+ break;
+
+ case CM_ALPHA_DOT_PRODUCT:
+ mult[ 3 ] = DotProduct( dv->normal, cm2->data );
+ break;
+
+ case CM_COLOR_DOT_PRODUCT_2:
+ c = DotProduct( dv->normal, cm2->data );
+ c *= c;
+ VectorSet( mult, c, c, c );
+ break;
+
+ case CM_ALPHA_DOT_PRODUCT_2:
+ mult[ 3 ] = DotProduct( dv->normal, cm2->data );
+ mult[ 3 ] *= mult[ 3 ];
break;
default:
- mult = 1.0f;
- add = 0.0f;
break;
}
/* apply mod */
for( j = 0; j < MAX_LIGHTMAPS; j++ )
{
- a = (mult * dv->color[ j ][ 3 ]) + add;
- if( a < 0 )
- a = 0;
- else if( a > 255 )
- a = 255;
- dv->color[ j ][ 3 ] = a;
+ for( k = 0; k < 4; k++ )
+ {
+ c = (mult[ k ] * dv->color[ j ][ k ]) + add[ k ];
+ if( c < 0 )
+ c = 0;
+ else if( c > 255 )
+ c = 255;
+ dv->color[ j ][ k ] = c;
+ }
}
}
}
/*
-TcMod*()
+TCMod*()
routines for dealing with a 3x3 texture mod matrix
*/
-void TcMod( tcMod_t mod, float st[ 2 ] )
+void TCMod( tcMod_t mod, float st[ 2 ] )
{
float old[ 2 ];
}
-void TcModIdentity( tcMod_t mod )
+void TCModIdentity( tcMod_t mod )
{
mod[ 0 ][ 0 ] = 1.0f; mod[ 0 ][ 1 ] = 0.0f; mod[ 0 ][ 2 ] = 0.0f;
mod[ 1 ][ 0 ] = 0.0f; mod[ 1 ][ 1 ] = 1.0f; mod[ 1 ][ 2 ] = 0.0f;
}
-void TcModMultiply( tcMod_t a, tcMod_t b, tcMod_t out )
+void TCModMultiply( tcMod_t a, tcMod_t b, tcMod_t out )
{
int i;
}
-void TcModTranslate( tcMod_t mod, float s, float t )
+void TCModTranslate( tcMod_t mod, float s, float t )
{
mod[ 0 ][ 2 ] += s;
mod[ 1 ][ 2 ] += t;
}
-void TcModScale( tcMod_t mod, float s, float t )
+void TCModScale( tcMod_t mod, float s, float t )
{
mod[ 0 ][ 0 ] *= s;
mod[ 1 ][ 1 ] *= t;
}
-void TcModRotate( tcMod_t mod, float euler )
+void TCModRotate( tcMod_t mod, float euler )
{
tcMod_t old, temp;
float radians, sinv, cosv;
memcpy( old, mod, sizeof( tcMod_t ) );
- TcModIdentity( temp );
+ TCModIdentity( temp );
radians = euler / 180 * Q_PI;
sinv = sin( radians );
temp[ 0 ][ 0 ] = cosv; temp[ 0 ][ 1 ] = -sinv;
temp[ 1 ][ 0 ] = sinv; temp[ 1 ][ 1 ] = cosv;
- TcModMultiply( old, temp, mod );
+ TCModMultiply( old, temp, mod );
}
char shader[ MAX_QPATH ];
char *s;
int loc;
- md5_state_t md5;
+ MHASH mh;
byte digest[ 16 ];
char *srcShaderText, temp[ 8192 ], shaderText[ 8192 ]; /* ydnar: fixme (make this bigger?) */
}
/* make md5 hash of the shader text */
- md5_init( &md5 );
- md5_append( &md5, shaderText, strlen( shaderText ) );
- md5_finish( &md5, digest );
+ mh = mhash_init( MHASH_MD5 );
+ if( !mh )
+ Error( "Unable to initialize MD5 hash context" );
+ mhash( mh, shaderText, strlen( shaderText ) );
+ mhash_deinit( mh, digest );
/* mangle hash into a shader name */
sprintf( shader, "%s/%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", mapName,
void EmitVertexRemapShader( char *from, char *to )
{
- md5_state_t md5;
+ MHASH mh;
byte digest[ 16 ];
char key[ 64 ], value[ 256 ];
sprintf( value, "%s;%s", from, to );
/* make md5 hash */
- md5_init( &md5 );
- md5_append( &md5, value, strlen( value ) );
- md5_finish( &md5, digest );
+ mh = mhash_init( MHASH_MD5 );
+ if( !mh )
+ Error( "Unable to initialize MD5 hash context" );
+ mhash( mh, value, strlen( value ) );
+ mhash_deinit( mh, digest );
/* make key (this is annoying, as vertexremapshader is precisely 17 characters,
which is one too long, so we leave off the last byte of the md5 digest) */
si->notjunc = qfalse;
/* ydnar: set texture coordinate transform matrix to identity */
- TcModIdentity( si->mod );
+ TCModIdentity( si->mod );
- /* ydnar: lightmaps can now be > 128x128 in an externally generated tga */
- si->lmCustomWidth = lmCustomSize; //% LIGHTMAP_WIDTH;
- si->lmCustomHeight = lmCustomSize; //% LIGHTMAP_HEIGHT;
+ /* ydnar: lightmaps can now be > 128x128 in certain games or an externally generated tga */
+ si->lmCustomWidth = lmCustomSize;
+ si->lmCustomHeight = lmCustomSize;
/* return to sender */
return si;
if( !Q_stricmp( shader, si->shader ) )
{
/* load image if necessary */
- if( si->shaderImage == NULL )
+ if( si->finished == qfalse )
{
LoadShaderImages( si );
FinishShader( si );
else if( !Q_stricmp( token, "light" ) )
{
GetTokenAppend( shaderText, qfalse );
- strcpy( si->flareShader, "flareshader" );
+ si->flareShader = game->flareShader;
}
/* ydnar: damageShader <shader> <health> (sof2 mods) */
else if( !Q_stricmp( token, "damageShader" ) )
{
GetTokenAppend( shaderText, qfalse );
- strcpy( si->damageShader, token );
+ if( token[ 0 ] != '\0' )
+ {
+ si->damageShader = safe_malloc( strlen( token ) + 1 );
+ strcpy( si->damageShader, token );
+ }
GetTokenAppend( shaderText, qfalse ); /* don't do anything with health */
}
-
+
/* ydnar: enemy territory implicit shaders */
else if( !Q_stricmp( token, "implicitMap" ) )
{
sun = safe_malloc( sizeof( *sun ) );
memset( sun, 0, sizeof( *sun ) );
+ /* set style */
+ sun->style = si->lightStyle;
+
/* get color */
GetTokenAppend( shaderText, qfalse );
sun->color[ 0 ] = atof( token );
/* restore name and set to unfinished */
strcpy( si->shader, temp );
+ si->shaderWidth = 0;
+ si->shaderHeight = 0;
si->finished = qfalse;
}
}
si->bounceScale = atof( token );
}
- /* ydnar/splashdamage: q3map_skylight <value> <iterations> */
- else if( !Q_stricmp( token, "q3map_skylight" ) )
+ /* ydnar/splashdamage: q3map_skyLight <value> <iterations> */
+ else if( !Q_stricmp( token, "q3map_skyLight" ) )
{
GetTokenAppend( shaderText, qfalse );
si->skyLightValue = atof( token );
si->value = atof( token );
}
-
/* q3map_lightStyle (sof2/jk2 lightstyle) */
else if( !Q_stricmp( token, "q3map_lightStyle" ) )
{
{
Sys_Printf( "WARNING: Non power-of-two lightmap size specified (%d, %d)\n",
si->lmCustomWidth, si->lmCustomHeight );
- si->lmCustomWidth = LIGHTMAP_WIDTH;
- si->lmCustomHeight = LIGHTMAP_HEIGHT;
+ si->lmCustomWidth = lmCustomSize;
+ si->lmCustomHeight = lmCustomSize;
}
}
- /* ydnar: q3map_lightmapGamma N (for autogenerated shaders + external tga lightmaps) */
- else if( !Q_stricmp( token, "q3map_lightmapGamma" ) )
+ /* ydnar: q3map_lightmapBrightness N (for autogenerated shaders + external tga lightmaps) */
+ else if( !Q_stricmp( token, "q3map_lightmapBrightness" ) || !Q_stricmp( token, "q3map_lightmapGamma" ) )
{
GetTokenAppend( shaderText, qfalse );
- si->lmGamma = atof( token );
- if( si->lmGamma < 0 )
- si->lmGamma = 1.0;
+ si->lmBrightness = atof( token );
+ if( si->lmBrightness < 0 )
+ si->lmBrightness = 1.0;
}
/* q3map_vertexScale (scale vertex lighting by this fraction) */
si->vertexScale = atof( token );
}
- /* q3map_flare <shader> */
+ /* q3map_noVertexLight */
+ else if( !Q_stricmp( token, "q3map_noVertexLight" ) )
+ {
+ si->noVertexLight = qtrue;
+ }
+
+ /* q3map_flare[Shader] <shader> */
else if( !Q_stricmp( token, "q3map_flare" ) || !Q_stricmp( token, "q3map_flareShader" ) )
{
GetTokenAppend( shaderText, qfalse );
- strcpy( si->flareShader, token );
+ if( token[ 0 ] != '\0' )
+ {
+ si->flareShader = safe_malloc( strlen( token ) + 1 );
+ strcpy( si->flareShader, token );
+ }
}
/* q3map_backShader <shader> */
else if( !Q_stricmp( token, "q3map_backShader" ) )
{
GetTokenAppend( shaderText, qfalse );
- strcpy( si->backShader, token );
+ if( token[ 0 ] != '\0' )
+ {
+ si->backShader = safe_malloc( strlen( token ) + 1 );
+ strcpy( si->backShader, token );
+ }
}
- /* ydnar: q3map_offset <value> */
- else if( !Q_stricmp( token, "q3map_offset" ) )
+ /* ydnar: q3map_cloneShader <shader> */
+ else if ( !Q_stricmp( token, "q3map_cloneShader" ) )
{
GetTokenAppend( shaderText, qfalse );
- si->offset = atof( token );
+ if( token[ 0 ] != '\0' )
+ {
+ si->cloneShader = safe_malloc( strlen( token ) + 1 );
+ strcpy( si->cloneShader, token );
+ }
}
- /* ydnar: q3map_cloneShader <shader> */
- else if ( !Q_stricmp( token, "q3map_cloneShader" ) )
+ /* q3map_remapShader <shader> */
+ else if( !Q_stricmp( token, "q3map_remapShader" ) )
+ {
+ GetTokenAppend( shaderText, qfalse );
+ if( token[ 0 ] != '\0' )
+ {
+ si->remapShader = safe_malloc( strlen( token ) + 1 );
+ strcpy( si->remapShader, token );
+ }
+ }
+
+ /* ydnar: q3map_offset <value> */
+ else if( !Q_stricmp( token, "q3map_offset" ) )
{
GetTokenAppend( shaderText, qfalse );
- strcpy( si->cloneShader, token );
+ si->offset = atof( token );
}
/* ydnar: q3map_textureSize <width> <height> (substitute for q3map_lightimage derivation for terrain) */
}
}
- /* ydnar: gs mods: q3map_alphaMod <style> <parameters> */
- else if( !Q_stricmp( token, "q3map_alphaMod" ) )
+ /* ydnar: gs mods: q3map_[color|rgb|alpha][Gen|Mod] <style> <parameters> */
+ else if( !Q_stricmp( token, "q3map_colorGen" ) || !Q_stricmp( token, "q3map_colorMod" ) ||
+ !Q_stricmp( token, "q3map_rgbGen" ) || !Q_stricmp( token, "q3map_rgbMod" ) ||
+ !Q_stricmp( token, "q3map_alphaGen" ) || !Q_stricmp( token, "q3map_alphaMod" ) )
{
- alphaMod_t *am, *am2;
+ colorMod_t *cm, *cm2;
+ int alpha;
+
+ /* alphamods are colormod + 1 */
+ alpha = (!Q_stricmp( token, "q3map_alphaGen" ) || !Q_stricmp( token, "q3map_alphaMod" )) ? 1 : 0;
- /* allocate new alpha mod */
- am = safe_malloc( sizeof( *am ) );
- memset( am, 0, sizeof( *am ) );
+ /* allocate new colormod */
+ cm = safe_malloc( sizeof( *cm ) );
+ memset( cm, 0, sizeof( *cm ) );
/* attach to shader */
- if( si->alphaMod == NULL )
- si->alphaMod = am;
+ if( si->colorMod == NULL )
+ si->colorMod = cm;
else
{
- for( am2 = si->alphaMod; am2 != NULL; am2 = am2->next )
+ for( cm2 = si->colorMod; cm2 != NULL; cm2 = cm2->next )
{
- if( am2->next == NULL )
+ if( cm2->next == NULL )
{
- am2->next = am;
+ cm2->next = cm;
break;
}
}
/* get type */
GetTokenAppend( shaderText, qfalse );
- /* q3map_alphaMod dotproduct ( X Y Z ) */
- if( !Q_stricmp( token, "dotproduct" ) )
+ /* alpha set|const A */
+ if( alpha && (!Q_stricmp( token, "set" ) || !Q_stricmp( token, "const" )) )
+ {
+ cm->type = CM_ALPHA_SET;
+ GetTokenAppend( shaderText, qfalse );
+ cm->data[ 0 ] = atof( token );
+ }
+
+ /* color|rgb set|const ( X Y Z ) */
+ else if( !Q_stricmp( token, "set" ) || !Q_stricmp( token, "const" ) )
{
- am->type = AM_DOT_PRODUCT;
- Parse1DMatrixAppend( shaderText, 3, am->data );
+ cm->type = CM_COLOR_SET;
+ Parse1DMatrixAppend( shaderText, 3, cm->data );
}
+
+ /* alpha scale A */
+ else if( alpha && !Q_stricmp( token, "scale" ) )
+ {
+ cm->type = CM_ALPHA_SCALE;
+ GetTokenAppend( shaderText, qfalse );
+ cm->data[ 0 ] = atof( token );
+ }
+
+ /* color|rgb scale ( X Y Z ) */
+ else if( !Q_stricmp( token, "scale" ) )
+ {
+ cm->type = CM_COLOR_SCALE;
+ Parse1DMatrixAppend( shaderText, 3, cm->data );
+ }
+
+ /* dotProduct ( X Y Z ) */
+ else if( !Q_stricmp( token, "dotProduct" ) )
+ {
+ cm->type = CM_COLOR_DOT_PRODUCT + alpha;
+ Parse1DMatrixAppend( shaderText, 3, cm->data );
+ }
+
+ /* dotProduct2 ( X Y Z ) */
+ else if( !Q_stricmp( token, "dotProduct2" ) )
+ {
+ cm->type = CM_COLOR_DOT_PRODUCT_2 + alpha;
+ Parse1DMatrixAppend( shaderText, 3, cm->data );
+ }
+
+ /* volume */
+ else if( !Q_stricmp( token, "volume" ) )
+ {
+ /* special stub mode for flagging volume brushes */
+ cm->type = CM_VOLUME;
+ }
+
+ /* unknown */
else
- Sys_Printf( "WARNING: Unknown q3map_alphaMod method: %s\n", token );
+ Sys_Printf( "WARNING: Unknown colorMod method: %s\n", token );
}
/* ydnar: gs mods: q3map_tcMod <style> <parameters> */
GetTokenAppend( shaderText, qfalse );
b = atof( token );
- TcModTranslate( si->mod, a, b );
+ TCModTranslate( si->mod, a, b );
}
/* q3map_tcMod scale <s> <t> */
GetTokenAppend( shaderText, qfalse );
b = atof( token );
- TcModScale( si->mod, a, b );
+ TCModScale( si->mod, a, b );
}
/* q3map_tcMod rotate <s> <t> (fixme: make this communitive) */
{
GetTokenAppend( shaderText, qfalse );
a = atof( token );
- TcModRotate( si->mod, a );
+ TCModRotate( si->mod, a );
}
else
Sys_Printf( "WARNING: Unknown q3map_tcMod method: %s\n", token );