static void R_JPGOutputMessage(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 */ ri.Printf(PRINT_ALL, "%s\n", buffer); }
qboolean R_MirrorViewBySurface (drawSurf_t *drawSurf, int entityNum) { vec4_t clipDest[128]; viewParms_t newParms; viewParms_t oldParms; orientation_t surface, camera; // don't recursively mirror if (tr.viewParms.isPortal) { ri.Printf( PRINT_DEVELOPER, "WARNING: recursive mirror/portal found\n" ); return qfalse; } if ( r_noportals->integer || r_fastsky->integer ) { return qfalse; } // trivially reject portal/mirror if ( SurfIsOffscreen( drawSurf, clipDest ) ) { return qfalse; } // save old viewParms so we can return to it after the mirror view oldParms = tr.viewParms; newParms = tr.viewParms; newParms.isPortal = qtrue; if ( !R_GetPortalOrientations( drawSurf, entityNum, &surface, &camera, newParms.pvsOrigin, &newParms.isMirror ) ) { return qfalse; // bad portal, no portalentity } R_MirrorPoint (oldParms.or.origin, &surface, &camera, newParms.or.origin ); VectorSubtract( vec3_origin, camera.axis[0], newParms.portalPlane.normal ); newParms.portalPlane.dist = DotProduct( camera.origin, newParms.portalPlane.normal ); R_MirrorVector (oldParms.or.axis[0], &surface, &camera, newParms.or.axis[0]); R_MirrorVector (oldParms.or.axis[1], &surface, &camera, newParms.or.axis[1]); R_MirrorVector (oldParms.or.axis[2], &surface, &camera, newParms.or.axis[2]); // OPTIMIZE: restrict the viewport on the mirrored view // render the mirror view R_RenderView (&newParms); tr.viewParms = oldParms; return qtrue; }
void R_LoadTGA ( const char *name, byte **pic, int *width, int *height) { unsigned columns, rows, numPixels; byte *pixbuf; int row, column; byte *buf_p; byte *end; union { byte *b; void *v; } buffer; TargaHeader targa_header; byte *targa_rgba; int length; *pic = NULL; if(width) *width = 0; if(height) *height = 0; // // load the file // length = ri.FS_ReadFile ( ( char * ) name, &buffer.v); if (!buffer.b || length < 0) { return; } if(length < 18) { ri.Error( ERR_DROP, "LoadTGA: header too short (%s)", name ); } buf_p = buffer.b; end = buffer.b + length; targa_header.id_length = buf_p[0]; targa_header.colormap_type = buf_p[1]; targa_header.image_type = buf_p[2]; memcpy(&targa_header.colormap_index, &buf_p[3], 2); memcpy(&targa_header.colormap_length, &buf_p[5], 2); targa_header.colormap_size = buf_p[7]; memcpy(&targa_header.x_origin, &buf_p[8], 2); memcpy(&targa_header.y_origin, &buf_p[10], 2); memcpy(&targa_header.width, &buf_p[12], 2); memcpy(&targa_header.height, &buf_p[14], 2); targa_header.pixel_size = buf_p[16]; targa_header.attributes = buf_p[17]; targa_header.colormap_index = LittleShort(targa_header.colormap_index); targa_header.colormap_length = LittleShort(targa_header.colormap_length); targa_header.x_origin = LittleShort(targa_header.x_origin); targa_header.y_origin = LittleShort(targa_header.y_origin); targa_header.width = LittleShort(targa_header.width); targa_header.height = LittleShort(targa_header.height); buf_p += 18; if (targa_header.image_type!=2 && targa_header.image_type!=10 && targa_header.image_type != 3 ) { ri.Error (ERR_DROP, "LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported"); } if ( targa_header.colormap_type != 0 ) { ri.Error( ERR_DROP, "LoadTGA: colormaps not supported" ); } if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 ) { ri.Error (ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps)"); } columns = targa_header.width; rows = targa_header.height; numPixels = columns * rows * 4; if(!columns || !rows || numPixels > 0x7FFFFFFF || numPixels / columns / 4 != rows) { ri.Error (ERR_DROP, "LoadTGA: %s has an invalid image size", name); } targa_rgba = ri.Malloc (numPixels); if (targa_header.id_length != 0) { if (buf_p + targa_header.id_length > end) ri.Error( ERR_DROP, "LoadTGA: header too short (%s)", name ); buf_p += targa_header.id_length; // skip TARGA image comment } if ( targa_header.image_type==2 || targa_header.image_type == 3 ) { if(buf_p + columns*rows*targa_header.pixel_size/8 > end) { ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)", name); } // 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: ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'", 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; ) { if(buf_p + 1 > end) ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)", name); packetHeader= *buf_p++; packetSize = 1 + (packetHeader & 0x7f); if (packetHeader & 0x80) { // run-length packet if(buf_p + targa_header.pixel_size/8 > end) ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)", name); 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: ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'", 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 if(buf_p + targa_header.pixel_size/8*packetSize > end) ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)", name); 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: ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'", 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:; } } #if 0 // TTimo: this is the chunk of code to ensure a behavior that meets TGA specs // bit 5 set => top-down if (targa_header.attributes & 0x20) { unsigned char *flip = (unsigned char*)malloc (columns*4); unsigned char *src, *dst; for (row = 0; row < rows/2; row++) { src = targa_rgba + row * 4 * columns; dst = targa_rgba + (rows - row - 1) * 4 * columns; memcpy (flip, src, columns*4); memcpy (src, dst, columns*4); memcpy (dst, flip, columns*4); } free (flip); } #endif // instead we just print a warning if (targa_header.attributes & 0x20) { ri.Printf( PRINT_WARNING, "WARNING: '%s' TGA file header declares top-down image, ignoring\n", name); } if (width) *width = columns; if (height) *height = rows; *pic = targa_rgba; ri.FS_FreeFile (buffer.v); }
void R_LoadPCX ( const char *filename, byte **pic, int *width, int *height) { union { byte *b; void *v; } raw; byte *end; pcx_t *pcx; int len; unsigned char dataByte = 0, runLength = 0; byte *out, *pix; unsigned short w, h; byte *pic8; byte *palette; int i; unsigned size = 0; if (width) *width = 0; if (height) *height = 0; *pic = NULL; // // load the file // len = ri.FS_ReadFile( ( char * ) filename, &raw.v); if (!raw.b || len < 0) { return; } if((unsigned)len < sizeof(pcx_t)) { ri.Printf (PRINT_ALL, "PCX truncated: %s\n", filename); ri.FS_FreeFile (raw.v); return; } // // parse the PCX file // pcx = (pcx_t *)raw.b; end = raw.b+len; w = LittleShort(pcx->xmax)+1; h = LittleShort(pcx->ymax)+1; size = w*h; if (pcx->manufacturer != 0x0a || pcx->version != 5 || pcx->encoding != 1 || pcx->color_planes != 1 || pcx->bits_per_pixel != 8 || w >= 1024 || h >= 1024) { ri.Printf (PRINT_ALL, "Bad or unsupported pcx file %s (%dx%d@%d)\n", filename, w, h, pcx->bits_per_pixel); return; } pix = pic8 = ri.Malloc ( size ); raw.b = pcx->data; // FIXME: should use bytes_per_line but original q3 didn't do that either while(pix < pic8+size) { if(runLength > 0) { *pix++ = dataByte; --runLength; continue; } if(raw.b+1 > end) break; dataByte = *raw.b++; if((dataByte & 0xC0) == 0xC0) { if(raw.b+1 > end) break; runLength = dataByte & 0x3F; dataByte = *raw.b++; } else runLength = 1; } if(pix < pic8+size) { ri.Printf (PRINT_ALL, "PCX file truncated: %s\n", filename); ri.FS_FreeFile (pcx); ri.Free (pic8); } if (raw.b-(byte*)pcx >= end - (byte*)769 || end[-769] != 0x0c) { ri.Printf (PRINT_ALL, "PCX missing palette: %s\n", filename); ri.FS_FreeFile (pcx); ri.Free (pic8); return; } palette = end-768; pix = out = ri.Malloc(4 * size ); for (i = 0 ; i < size ; i++) { unsigned char p = pic8[i]; pix[0] = palette[p*3]; pix[1] = palette[p*3 + 1]; pix[2] = palette[p*3 + 2]; pix[3] = 255; pix += 4; } if (width) *width = w; if (height) *height = h; *pic = out; ri.FS_FreeFile (pcx); ri.Free (pic8); }
/* ============== SetFarClip ============== */ static void R_SetFarClip( void ) { float farthestCornerDistance = 0; int i; // if not rendering the world (icons, menus, etc) // set a 2k far clip plane if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) { tr.viewParms.zFar = 2048; return; } //----(SA) this lets you use r_zfar from the command line to experiment with different // distances, but setting it back to 0 uses the map (or procedurally generated) default if ( r_zfar->value ) { tr.viewParms.zFar = r_zfar->integer; R_SetFrameFog(); if ( r_speeds->integer == 5 ) { ri.Printf( PRINT_ALL, "r_zfar value forcing farclip at: %f\n", tr.viewParms.zFar ); } return; } // // set far clipping planes dynamically // farthestCornerDistance = 0; for ( i = 0; i < 8; i++ ) { vec3_t v; vec3_t vecTo; float distance; if ( i & 1 ) { v[0] = tr.viewParms.visBounds[0][0]; } else { v[0] = tr.viewParms.visBounds[1][0]; } if ( i & 2 ) { v[1] = tr.viewParms.visBounds[0][1]; } else { v[1] = tr.viewParms.visBounds[1][1]; } if ( i & 4 ) { v[2] = tr.viewParms.visBounds[0][2]; } else { v[2] = tr.viewParms.visBounds[1][2]; } VectorSubtract( v, tr.viewParms.or.origin, vecTo ); distance = vecTo[0] * vecTo[0] + vecTo[1] * vecTo[1] + vecTo[2] * vecTo[2]; if ( distance > farthestCornerDistance ) { farthestCornerDistance = distance; } } tr.viewParms.zFar = sqrt( farthestCornerDistance ); R_SetFrameFog(); }
/* ============== R_SetFrameFog ============== */ void R_SetFrameFog( void ) { if ( r_speeds->integer == 5 ) { if ( !glfogsettings[FOG_TARGET].registered ) { ri.Printf( PRINT_ALL, "no fog - calc zFar: %0.1f\n", tr.viewParms.zFar ); return; } } // DHM - Nerve :: If fog is not valid, don't use it if ( !glfogsettings[FOG_TARGET].registered ) { return; } // still fading if ( glfogsettings[FOG_TARGET].finishTime && glfogsettings[FOG_TARGET].finishTime >= tr.refdef.time ) { float lerpPos; int fadeTime; // transitioning from density to distance if ( glfogsettings[FOG_LAST].mode == GL_EXP && glfogsettings[FOG_TARGET].mode == GL_LINEAR ) { // for now just fast transition to the target when dissimilar fogs are memcpy( &glfogsettings[FOG_CURRENT], &glfogsettings[FOG_TARGET], sizeof( glfog_t ) ); glfogsettings[FOG_TARGET].finishTime = 0; } // transitioning from distance to density else if ( glfogsettings[FOG_LAST].mode == GL_LINEAR && glfogsettings[FOG_TARGET].mode == GL_EXP ) { memcpy( &glfogsettings[FOG_CURRENT], &glfogsettings[FOG_TARGET], sizeof( glfog_t ) ); glfogsettings[FOG_TARGET].finishTime = 0; } // transitioning like fog modes else { fadeTime = glfogsettings[FOG_TARGET].finishTime - glfogsettings[FOG_TARGET].startTime; if ( fadeTime <= 0 ) { fadeTime = 1; // avoid divide by zero } lerpPos = (float)( tr.refdef.time - glfogsettings[FOG_TARGET].startTime ) / (float)fadeTime; if ( lerpPos > 1 ) { lerpPos = 1; } // lerp near/far glfogsettings[FOG_CURRENT].start = glfogsettings[FOG_LAST].start + ( ( glfogsettings[FOG_TARGET].start - glfogsettings[FOG_LAST].start ) * lerpPos ); glfogsettings[FOG_CURRENT].end = glfogsettings[FOG_LAST].end + ( ( glfogsettings[FOG_TARGET].end - glfogsettings[FOG_LAST].end ) * lerpPos ); // lerp color glfogsettings[FOG_CURRENT].color[0] = glfogsettings[FOG_LAST].color[0] + ( ( glfogsettings[FOG_TARGET].color[0] - glfogsettings[FOG_LAST].color[0] ) * lerpPos ); glfogsettings[FOG_CURRENT].color[1] = glfogsettings[FOG_LAST].color[1] + ( ( glfogsettings[FOG_TARGET].color[1] - glfogsettings[FOG_LAST].color[1] ) * lerpPos ); glfogsettings[FOG_CURRENT].color[2] = glfogsettings[FOG_LAST].color[2] + ( ( glfogsettings[FOG_TARGET].color[2] - glfogsettings[FOG_LAST].color[2] ) * lerpPos ); glfogsettings[FOG_CURRENT].density = glfogsettings[FOG_TARGET].density; glfogsettings[FOG_CURRENT].mode = glfogsettings[FOG_TARGET].mode; glfogsettings[FOG_CURRENT].registered = qtrue; // if either fog in the transition clears the screen, clear the background this frame to avoid hall of mirrors glfogsettings[FOG_CURRENT].clearscreen = ( glfogsettings[FOG_TARGET].clearscreen || glfogsettings[FOG_LAST].clearscreen ); } } else { // probably usually not necessary to copy the whole thing. // potential FIXME: since this is the most common occurance, diff first and only set changes memcpy( &glfogsettings[FOG_CURRENT], &glfogsettings[FOG_TARGET], sizeof( glfog_t ) ); } // shorten the far clip if the fog opaque distance is closer than the procedural farcip dist if ( glfogsettings[FOG_CURRENT].mode == GL_LINEAR ) { if ( glfogsettings[FOG_CURRENT].end < tr.viewParms.zFar ) { tr.viewParms.zFar = glfogsettings[FOG_CURRENT].end; } } // else // glfogsettings[FOG_CURRENT].end = 5; if ( r_speeds->integer == 5 ) { if ( glfogsettings[FOG_CURRENT].mode == GL_LINEAR ) { ri.Printf( PRINT_ALL, "farclip fog - den: %0.1f calc zFar: %0.1f fog zfar: %0.1f\n", glfogsettings[FOG_CURRENT].density, tr.viewParms.zFar, glfogsettings[FOG_CURRENT].end ); } else { ri.Printf( PRINT_ALL, "density fog - den: %0.4f calc zFar: %0.1f fog zFar: %0.1f\n", glfogsettings[FOG_CURRENT].density, tr.viewParms.zFar, glfogsettings[FOG_CURRENT].end ); } } }
/* ======================================================================================================================================= R_SetFrameFog ======================================================================================================================================= */ void R_SetFrameFog(void) { if (r_speeds->integer == 5) { if (!glfogsettings[FOG_TARGET].registered) { ri.Printf(PRINT_ALL, "no fog - calc zFar: %0.1f\n", tr.viewParms.zFar); return; } } // still fading if (glfogsettings[FOG_TARGET].finishTime && glfogsettings[FOG_TARGET].finishTime >= tr.refdef.time) { float lerpPos; int fadeTime; // transitioning from density to distance if (glfogsettings[FOG_LAST].mode == GL_EXP && glfogsettings[FOG_TARGET].mode == GL_LINEAR) { // for now just fast transition to the target when dissimilar fogs are memcpy(&glfogsettings[FOG_CURRENT], &glfogsettings[FOG_TARGET], sizeof(glfog_t)); glfogsettings[FOG_TARGET].finishTime = 0; } // transitioning from distance to density else if (glfogsettings[FOG_LAST].mode == GL_LINEAR && glfogsettings[FOG_TARGET].mode == GL_EXP) { memcpy(&glfogsettings[FOG_CURRENT], &glfogsettings[FOG_TARGET], sizeof(glfog_t)); glfogsettings[FOG_TARGET].finishTime = 0; } // transitioning like fog modes else { fadeTime = glfogsettings[FOG_TARGET].finishTime - glfogsettings[FOG_TARGET].startTime; if (fadeTime <= 0) { fadeTime = 1; // avoid divide by zero } lerpPos = (float)(tr.refdef.time - glfogsettings[FOG_TARGET].startTime) / (float)fadeTime; if (lerpPos > 1) { lerpPos = 1; } // lerp near/far glfogsettings[FOG_CURRENT].start = glfogsettings[FOG_LAST].start + ((glfogsettings[FOG_TARGET].start - glfogsettings[FOG_LAST].start) * lerpPos); glfogsettings[FOG_CURRENT].end = glfogsettings[FOG_LAST].end + ((glfogsettings[FOG_TARGET].end - glfogsettings[FOG_LAST].end) * lerpPos); // lerp color glfogsettings[FOG_CURRENT].color[0] = glfogsettings[FOG_LAST].color[0] + ((glfogsettings[FOG_TARGET].color[0] - glfogsettings[FOG_LAST].color[0]) * lerpPos); glfogsettings[FOG_CURRENT].color[1] = glfogsettings[FOG_LAST].color[1] + ((glfogsettings[FOG_TARGET].color[1] - glfogsettings[FOG_LAST].color[1]) * lerpPos); glfogsettings[FOG_CURRENT].color[2] = glfogsettings[FOG_LAST].color[2] + ((glfogsettings[FOG_TARGET].color[2] - glfogsettings[FOG_LAST].color[2]) * lerpPos); glfogsettings[FOG_CURRENT].density = glfogsettings[FOG_TARGET].density; glfogsettings[FOG_CURRENT].mode = glfogsettings[FOG_TARGET].mode; glfogsettings[FOG_CURRENT].registered = qtrue; // if either fog in the transition clears the screen, clear the background this frame to avoid hall of mirrors glfogsettings[FOG_CURRENT].clearscreen = (glfogsettings[FOG_TARGET].clearscreen || glfogsettings[FOG_LAST].clearscreen); } glfogsettings[FOG_CURRENT].dirty = 1; } else { // potential FIXME: since this is the most common occurance, diff first and only set changes // if(glfogsettings[FOG_CURRENT].dirty) { memcpy(&glfogsettings[FOG_CURRENT], &glfogsettings[FOG_TARGET], sizeof(glfog_t)); glfogsettings[FOG_CURRENT].dirty = 0; // } } // shorten the far clip if the fog opaque distance is closer than the procedural farcip dist if (glfogsettings[FOG_CURRENT].mode == GL_LINEAR) { if (glfogsettings[FOG_CURRENT].end < tr.viewParms.zFar) { tr.viewParms.zFar = glfogsettings[FOG_CURRENT].end; } if (backEnd.refdef.rdflags & RDF_SNOOPERVIEW) { tr.viewParms.zFar += 1000; // zfar out slightly further for snooper. this works fine with our maps, but could be 'funky' with later maps } } // else // glfogsettings[FOG_CURRENT].end = 5; if (r_speeds->integer == 5) { if (glfogsettings[FOG_CURRENT].mode == GL_LINEAR) { ri.Printf(PRINT_ALL, "farclip fog - den: %0.1f calc zFar: %0.1f fog zfar: %0.1f\n", glfogsettings[FOG_CURRENT].density, tr.viewParms.zFar, glfogsettings[FOG_CURRENT].end); } else { ri.Printf(PRINT_ALL, "density fog - den: %0.6f calc zFar: %0.1f fog zFar: %0.1f\n", glfogsettings[FOG_CURRENT].density, tr.viewParms.zFar, glfogsettings[FOG_CURRENT].end); } } }