/* ** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY ** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT ** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX ** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE ** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). ** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER ** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A ** FULL TEXT OF THE NON-WARRANTY PROVISIONS. ** ** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO ** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN ** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, ** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR ** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF ** THE UNITED STATES. ** ** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED ** ** $Revision: 1.2 $ ** $Date: 2000/06/15 00:11:40 $ */ #include #include #include #include #include /* * VIEWPPM * This is a simple program to show how to use the Texus library * to convert textures from an in memory format to a format * that Glide can handle for texture downloads. */ typedef struct { unsigned char b, g, r, a; } Color32; /* * This structure contains the factors to multiply normalized [0.0, 1.0] * texture coordinates by in order to get the texture coordinates that * Voodoo Graphics expect. */ typedef struct { float sMult; float tMult; } TexCoordFactors; /* * An array which is indexed by GrAspectRatio_t to convert from normalized * texture coordinates to Voodoo texture coordinates. */ TexCoordFactors aspectToTexCoordFactors[7] = { { 255.0f, 255.0f / 8.0f }, /* GR_ASPECT_8x1 */ { 255.0f, 255.0f / 4.0f }, /* GR_ASPECT_4x1 */ { 255.0f, 255.0f / 2.0f }, /* GR_ASPECT_2x1 */ { 255.0f, 255.0f }, /* GR_ASPECT_1x1 */ { 255.0f / 2.0f, 255.0f }, /* GR_ASPECT_1x2 */ { 255.0f / 4.0f, 255.0f }, /* GR_ASPECT_1x4 */ { 255.0f / 8.0f, 255.0f } /* GR_ASPECT_1x8 */ }; /* * Do whatever is necessary to get Glide going. */ void InitGlide( void ) { static GrHwConfiguration hwconfig; grGlideInit(); if ( !grSstQueryHardware( &hwconfig ) ) { fprintf( stderr, "grQuery failed!" ); exit( -1 ); } grSstSelect( 0 ); if ( !grSstWinOpen( 0, GR_RESOLUTION_640x480, GR_REFRESH_60Hz, GR_COLORFORMAT_ABGR, GR_ORIGIN_UPPER_LEFT, 2, 0 ) ) { fprintf( stderr, "grOpen failed!" ); exit( -1 ); } grTexCombineFunction( GR_TMU0, GR_TEXTURECOMBINE_DECAL ); guColorCombineFunction( GR_COLORCOMBINE_DECAL_TEXTURE ); grCullMode( GR_CULL_NEGATIVE ); } int ValidateImageDimensions( int width, int height ) { switch( width ) { case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: case 256: break; default: fprintf( stderr, "Invalid image width: %d\n", width ); return 0; } switch( height ) { case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: case 256: break; default: fprintf( stderr, "Invalid image height: %d\n", height ); return 0; } if( ( ( width / height ) > 8 ) || ( ( height / width ) > 8 ) ) { fprintf( stderr, "Invalid aspect ratio, must one of:\n" ); fprintf( stderr, "1:8, 1:4, 1:2, 1:1, 2:1, 4:1, 8:1\n" ); return 0; } return 1; } /* * Get the dimensions of a PPM file. * returns 1 if successful, 0 otherwise. */ int PPMGetDimensions( const char *filename, int *width, int *height ) { FILE *fp; char buf[200]; /* * Open the PPM file. */ if( !( fp = fopen( filename, "rb" ) ) ) return 0; /* * Read the PPM header. */ /* Skip the P6 */ fgets( buf, 200, fp ); /* REad the dimensions */ fgets( buf, 200, fp ); sscanf( buf, "%d %d", width, height ); fclose( fp ); return 1; } /* * LoadPPM * Allocate memory for an image, load a ppm file into it. * Not the most efficient loader because it reads directly * into a 8888 instead of an 888 without allocating any * extra memory. */ Color32 *PPMLoad( const char *filename ) { Color32 *out; char buf[200]; FILE *fp; int width, height; long i; /* * Open the PPM file. */ if( !( fp = fopen( filename, "rb" ) ) ) return NULL; /* * Read the PPM header. */ /* Skip the P6 */ fgets( buf, 200, fp ); /* REad the dimensions */ fgets( buf, 200, fp ); sscanf( buf, "%d %d", &width, &height ); /* Skip the maxval line. . . assume that it is 255. */ fgets( buf, 200, fp ); /* * Allocate memory for the output image. */ out = ( Color32 * )malloc( sizeof( Color32 ) * ( long )width * ( long )height ); if( !out ) { fclose( fp ); return NULL; } /* * Read in each texel. . .fill in the alpha with a totally * opaque value. */ for( i = 0; i < ( long )width * ( long )height; i++ ) { fread( &out[i].r, 1, 1, fp ); fread( &out[i].g, 1, 1, fp ); fread( &out[i].b, 1, 1, fp ); out[i].a = 0xff; } fclose( fp ); return out; } int main( int argc, char **argv ) { Color32 *raw_image; size_t tex_mem_required; Gu3dfInfo info; int ppm_width, ppm_height; int target_width, target_height; GrMipMapId_t mmid; GrVertex vtx[4]; float smult, tmult; if( argc < 2 ) { fprintf( stderr, "Usage: %s in.ppm [display_width display_height] \n", argv[0] ); exit( -1 ); } InitGlide(); if( !PPMGetDimensions( argv[1], &ppm_width, &ppm_height ) ) { fprintf( stderr, "Error getting PPM dimensions\n" ); exit( -1 ); } /* * If there are args to resize the image, then remember them. */ if( argc == 4 ) { target_width = atoi( argv[2] ); target_height = atoi( argv[3] ); } else { target_width = ppm_width; target_height = ppm_height; } #if 0 /* * Validate the geometry of the output image. */ if( !ValidateImageDimensions( target_width, target_height ) ) { fprintf( stderr, "Invalid image dimensions\n" ); exit( -1 ); } #endif tex_mem_required = txInit3dfInfo( &info, GR_TEXFMT_P_8, &target_width, &target_height, -1, TX_AUTORESIZE_GROW ); /* * Allocate system memory for the texture. */ info.data = malloc( tex_mem_required ); if( !info.data ) { fprintf( stderr, "Out of memory allocating system memory textures.\n" ); exit( -1 ); } /* * Make sure txInit3dfInfo didn't fail. */ if( tex_mem_required == 0 ) { fprintf( stderr, "Problem with txInit3dfInfo\n" ); exit( -1 ); } /* * Read the PPM image. */ if( !( raw_image = PPMLoad( argv[1] ) ) ) { fprintf( stderr, "Not able to load PPM file.\n" ); exit( -1 ); } /* * Convert to a texture that can be downloaded to the hardware. */ txConvert( &info, GR_TEXFMT_ARGB_8888, ppm_width, ppm_height, raw_image, TX_DITHER_NONE, NULL ); { FILE *fp; fprintf( stderr, "Writing blah.3df\n" ); if( !( fp = fopen( "blah.3df", "wb" ) ) ) { fprintf( stderr, "Not able to open output file.\n" ); exit( -1 ); } txWrite( &info, fp, TX_WRITE_3DF ); fclose( fp ); grTexDownloadTable( GR_TMU0, GR_TEXTABLE_PALETTE, &info.table.palette.data ); } /* * Call Glide to allocate memory for the converted texture. */ mmid = guTexAllocateMemory( 0, GR_MIPMAPLEVELMASK_BOTH, info.header.width, info.header.height, info.header.format, GR_MIPMAP_NEAREST, info.header.small_lod, info.header.large_lod, info.header.aspect_ratio, GR_TEXTURECLAMP_WRAP, GR_TEXTURECLAMP_WRAP, GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR, 0.0F, FXFALSE ); /* * Download the texture and set it as the current texture. */ guTexDownloadMipMap( mmid, info.data, &info.table.nccTable ); guTexSource( mmid ); /* * Figure out what the factor is to get from normalized texture * coords to something that the hardware can deal with. */ smult = aspectToTexCoordFactors[info.header.aspect_ratio].sMult; tmult = aspectToTexCoordFactors[info.header.aspect_ratio].tMult; /* * Set up some verts to draw the texture on a couple of triangles * with. */ vtx[0].x = 0.0f; vtx[0].y = 0.0f; vtx[0].oow = 1.0f; vtx[0].tmuvtx[0].sow = 0.0f; vtx[0].tmuvtx[0].tow = 0.0f; vtx[1].x = ( float )target_width - 1.0f; vtx[1].y = 0.0f; vtx[1].oow = 1.0f; vtx[1].tmuvtx[0].sow = 1.0f * smult; vtx[1].tmuvtx[0].tow = 0.0f; vtx[2].x = ( float )target_width - 1.0f; vtx[2].y = ( float )target_height - 1.0f; vtx[2].oow = 1.0f; vtx[2].tmuvtx[0].sow = 1.0f * smult; vtx[2].tmuvtx[0].tow = 1.0f * tmult; vtx[3].x = 0.0f; vtx[3].y = ( float )target_height - 1.0f; vtx[3].oow = 1.0f; vtx[3].tmuvtx[0].sow = 0.0f; vtx[3].tmuvtx[0].tow = 1.0f * tmult; printf( "Hit a key to exit\n" ); fflush( stdout ); while( !kbhit() ) { grDrawTriangle( &vtx[0], &vtx[1], &vtx[2] ); grDrawTriangle( &vtx[0], &vtx[2], &vtx[3] ); grBufferSwap( 1 ); } /* * Shutdown Glide (and switch the passthru back to the * main display. */ grGlideShutdown(); /* * Clean up. */ free( raw_image ); free( info.data ); return 0; }