/* * CG_AddBlobShadow * * Ok, to not use decals space we need these arrays to store the * polygons info. We do not need the linked list nor registration */ static void CG_AddBlobShadow( vec3_t origin, vec3_t dir, float orient, float radius, float r, float g, float b, float a, cgshadebox_t *shadeBox ) { int i, j, c, nverts; vec3_t axis[3]; byte_vec4_t color; fragment_t *fr, fragments[MAX_BLOBSHADOW_FRAGMENTS]; int numfragments; poly_t poly; vec4_t verts[MAX_BLOBSHADOW_VERTS]; if( radius <= 0 || VectorCompare( dir, vec3_origin ) ) return; // invalid // calculate orientation matrix VectorNormalize2( dir, axis[0] ); PerpendicularVector( axis[1], axis[0] ); RotatePointAroundVector( axis[2], axis[0], axis[1], orient ); CrossProduct( axis[0], axis[2], axis[1] ); numfragments = trap_R_GetClippedFragments( origin, radius, axis, // clip it MAX_BLOBSHADOW_VERTS, verts, MAX_BLOBSHADOW_FRAGMENTS, fragments ); // no valid fragments if( !numfragments ) return; // clamp and scale colors if( r < 0 ) r = 0;else if( r > 1 ) r = 255;else r *= 255; if( g < 0 ) g = 0;else if( g > 1 ) g = 255;else g *= 255; if( b < 0 ) b = 0;else if( b > 1 ) b = 255;else b *= 255; if( a < 0 ) a = 0;else if( a > 1 ) a = 255;else a *= 255; color[0] = ( qbyte )( r ); color[1] = ( qbyte )( g ); color[2] = ( qbyte )( b ); color[3] = ( qbyte )( a ); c = *( int * )color; radius = 0.5f / radius; VectorScale( axis[1], radius, axis[1] ); VectorScale( axis[2], radius, axis[2] ); memset( &poly, 0, sizeof( poly ) ); for( i = 0, nverts = 0, fr = fragments; i < numfragments; i++, fr++ ) { if( nverts+fr->numverts > MAX_BLOBSHADOW_VERTS ) return; if( fr->numverts <= 0 ) continue; poly.shader = shadeBox->shader; poly.verts = &shadeBox->verts[nverts]; poly.normals = &shadeBox->norms[nverts]; poly.stcoords = &shadeBox->stcoords[nverts]; poly.colors = &shadeBox->colors[nverts]; poly.numverts = fr->numverts; poly.fognum = fr->fognum; nverts += fr->numverts; for( j = 0; j < fr->numverts; j++ ) { vec3_t v; Vector4Copy( verts[fr->firstvert+j], poly.verts[j] ); VectorCopy( axis[0], poly.normals[j] ); poly.normals[j][3] = 0; VectorSubtract( poly.verts[j], origin, v ); poly.stcoords[j][0] = DotProduct( v, axis[1] ) + 0.5f; poly.stcoords[j][1] = DotProduct( v, axis[2] ) + 0.5f; *( int * )poly.colors[j] = c; } trap_R_AddPolyToScene( &poly ); } }
/* * CG_AddFragmentedDecal */ void CG_AddFragmentedDecal( vec3_t origin, vec3_t dir, float orient, float radius, float r, float g, float b, float a, struct shader_s *shader ) { int i, j, c; vec3_t axis[3]; byte_vec4_t color; fragment_t *fr, fragments[MAX_TEMPDECAL_FRAGMENTS]; int numfragments; poly_t poly; vec4_t verts[MAX_BLOBSHADOW_VERTS]; static vec4_t t_verts[MAX_TEMPDECAL_VERTS * MAX_TEMPDECALS]; static vec4_t t_norms[MAX_TEMPDECAL_VERTS * MAX_TEMPDECALS]; static vec2_t t_stcoords[MAX_TEMPDECAL_VERTS * MAX_TEMPDECALS]; static byte_vec4_t t_colors[MAX_TEMPDECAL_VERTS * MAX_TEMPDECALS]; if( radius <= 0 || VectorCompare( dir, vec3_origin ) ) { return; // invalid } // calculate orientation matrix VectorNormalize2( dir, axis[0] ); PerpendicularVector( axis[1], axis[0] ); RotatePointAroundVector( axis[2], axis[0], axis[1], orient ); CrossProduct( axis[0], axis[2], axis[1] ); numfragments = trap_R_GetClippedFragments( origin, radius, axis, // clip it MAX_BLOBSHADOW_VERTS, verts, MAX_TEMPDECAL_FRAGMENTS, fragments ); // no valid fragments if( !numfragments ) { return; } // clamp and scale colors if( r < 0 ) { r = 0; } else if( r > 1 ) { r = 255; } else { r *= 255; } if( g < 0 ) { g = 0; } else if( g > 1 ) { g = 255; } else { g *= 255; } if( b < 0 ) { b = 0; } else if( b > 1 ) { b = 255; } else { b *= 255; } if( a < 0 ) { a = 0; } else if( a > 1 ) { a = 255; } else { a *= 255; } color[0] = ( uint8_t )( r ); color[1] = ( uint8_t )( g ); color[2] = ( uint8_t )( b ); color[3] = ( uint8_t )( a ); c = *( int * )color; radius = 0.5f / radius; VectorScale( axis[1], radius, axis[1] ); VectorScale( axis[2], radius, axis[2] ); memset( &poly, 0, sizeof( poly ) ); for( i = 0, fr = fragments; i < numfragments; i++, fr++ ) { if( fr->numverts <= 0 ) { continue; } if( cg_numDecalVerts + (unsigned)fr->numverts > sizeof( t_verts ) / sizeof( t_verts[0] ) ) { return; } poly.shader = shader; poly.verts = &t_verts[cg_numDecalVerts]; poly.normals = &t_norms[cg_numDecalVerts]; poly.stcoords = &t_stcoords[cg_numDecalVerts]; poly.colors = &t_colors[cg_numDecalVerts]; poly.numverts = fr->numverts; poly.fognum = fr->fognum; cg_numDecalVerts += (unsigned)fr->numverts; for( j = 0; j < fr->numverts; j++ ) { vec3_t v; Vector4Copy( verts[fr->firstvert + j], poly.verts[j] ); VectorCopy( axis[0], poly.normals[j] ); poly.normals[j][3] = 0; VectorSubtract( poly.verts[j], origin, v ); poly.stcoords[j][0] = DotProduct( v, axis[1] ) + 0.5f; poly.stcoords[j][1] = DotProduct( v, axis[2] ) + 0.5f; *( int * )poly.colors[j] = c; } trap_R_AddPolyToScene( &poly ); } }
/* * CG_SpawnDecal */ void CG_SpawnDecal( vec3_t origin, vec3_t dir, float orient, float radius, float r, float g, float b, float a, float die, float fadetime, bool fadealpha, struct shader_s *shader ) { int i, j; cdecal_t *dl; poly_t *poly; vec3_t axis[3]; vec3_t verts[MAX_DECAL_VERTS]; vec3_t v; byte_vec4_t color; fragment_t *fr, fragments[MAX_DECAL_FRAGMENTS]; int numfragments; float dietime, fadefreq; if( !cg_addDecals->integer ) return; // invalid decal if( radius <= 0 || VectorCompare( dir, vec3_origin ) ) return; // we don't spawn decals if too far away (we could move there, but players won't notice there should be a decal by then) if( DistanceFast( origin, cg.view.origin ) * cg.view.fracDistFOV > 2048 ) return; // calculate orientation matrix VectorNormalize2( dir, axis[0] ); PerpendicularVector( axis[1], axis[0] ); RotatePointAroundVector( axis[2], axis[0], axis[1], orient ); CrossProduct( axis[0], axis[2], axis[1] ); numfragments = trap_R_GetClippedFragments( origin, radius, axis, // clip it MAX_DECAL_VERTS, verts, MAX_DECAL_FRAGMENTS, fragments ); // no valid fragments if( !numfragments ) return; // clamp and scale colors if( r < 0 ) r = 0;else if( r > 1 ) r = 255;else r *= 255; if( g < 0 ) g = 0;else if( g > 1 ) g = 255;else g *= 255; if( b < 0 ) b = 0;else if( b > 1 ) b = 255;else b *= 255; if( a < 0 ) a = 0;else if( a > 1 ) a = 255;else a *= 255; color[0] = ( qbyte )( r ); color[1] = ( qbyte )( g ); color[2] = ( qbyte )( b ); color[3] = ( qbyte )( a ); radius = 0.5f / radius; VectorScale( axis[1], radius, axis[1] ); VectorScale( axis[2], radius, axis[2] ); dietime = cg.time + die * 1000; fadefreq = 0.001f / min( fadetime, die ); fadetime = cg.time + ( die - min( fadetime, die ) ) * 1000; for( i = 0, fr = fragments; i < numfragments; i++, fr++ ) { if( fr->numverts > MAX_DECAL_VERTS ) return; else if( fr->numverts <= 0 ) continue; // allocate decal dl = CG_AllocDecal(); dl->die = dietime; dl->fadetime = fadetime; dl->fadefreq = fadefreq; dl->fadealpha = fadealpha; dl->shader = shader; dl->color[0] = r; dl->color[1] = g; dl->color[2] = b; dl->color[3] = a; // setup polygon for drawing poly = dl->poly; poly->shader = shader; poly->numverts = fr->numverts; poly->fognum = fr->fognum; for( j = 0; j < fr->numverts; j++ ) { VectorCopy( verts[fr->firstvert+j], poly->verts[j] ); VectorCopy( fr->normal, poly->normals[j] ); VectorSubtract( poly->verts[j], origin, v ); poly->stcoords[j][0] = DotProduct( v, axis[1] ) + 0.5f; poly->stcoords[j][1] = DotProduct( v, axis[2] ) + 0.5f; *( int * )poly->colors[j] = *( int * )color; } } }