📄 glmovie-tile.c
字号:
/* * MODIFIED by Bruce Merry (bmerry@iafrica.com) on 10/11/2000 * - fixed to handle arbitrary tile dimensions, not just 1x2 * - max_texture_size renamed to texture_size and used as a variable * (to change the max texture size, edit the assigned value in the decl) * - hardcoded 256's changed to texture_size to allow small texture sizes * (e.g. for very low-res movies) * - all pieces of movie copied into the top left corner of texture tiles, * instead of being offset * - mechanism for keeping tiles aligned changed: a one texel border is * included in the tiles, which I think is used by the filtering even though * it is not explicitly selected for rendering (I think - I don't know much * about OpenGL, I've just fiddled until it looked right) * - removed glmovie_is_power_of_2: it was not needed and * it only went up to 2048 anyway. */#include "glmovie.h"#include <malloc.h>#include <string.h>/* Some data is redundant at this stage. */typedef struct glmovie_texture_t { GLuint id; /* OpenGL texture id. */ GLuint poly_width; /* Quad width for tile. */ GLuint poly_height; /* Quad height for tile. */ GLuint movie_width; /* Width of movie inside tile. */ GLuint movie_height; /* Height of movie inside tile. */ GLuint skip_rows; /* Number of rows of movie to skip */ GLuint skip_pixels; /* Number of columns of movie to skip */ GLuint row; /* Row number of tile in scheme. */ GLuint col; /* Column number of tile in scheme. */} glmovie_texture;/* Boy, is this not thread safe. *//* Our evil maximum texture size. Boo 3Dfx! */static GLuint texture_size = 256;/* Keep this around for easy freeing later. */static GLuint* texture_ids = NULL;/* Our main data. */static glmovie_texture* textures = NULL;static GLuint num_texture_rows = 0;static GLuint num_texture_cols = 0;/* Width and height of all tiling. */static GLuint tiled_width = 0;static GLuint tiled_height = 0;/* Width and height of entire movie. */static GLuint movie_width = 0;static GLuint movie_height = 0;/* * Draw the frame data. * * Parameters: * frame: Actual RGBA frame data */void glmovie_draw( GLubyte* frame ){ GLuint i; GLdouble shift; glClear( GL_COLOR_BUFFER_BIT ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity( ); shift = 1 / ((double) texture_size); for (i = 0; i < num_texture_rows * num_texture_cols; i++) { glBindTexture( GL_TEXTURE_2D, textures[i].id ); glPixelStorei( GL_UNPACK_ROW_LENGTH, movie_width ); glPixelStorei( GL_UNPACK_SKIP_ROWS, textures[i].skip_rows ); glPixelStorei( GL_UNPACK_SKIP_PIXELS, textures[i].skip_pixels ); glTexSubImage2D( GL_TEXTURE_2D, 0, 0, /* offset_x */ 0, /* offset_y */ textures[i].movie_width + 2, textures[i].movie_height + 2, GL_RGBA, GL_UNSIGNED_BYTE, frame ); glBegin( GL_QUADS ); glTexCoord2f( shift, shift ); glVertex2i( textures[i].col * texture_size, textures[i].row * texture_size ); glTexCoord2f( shift, shift + (textures[i].movie_height)/((double) texture_size) ); glVertex2i( textures[i].col * texture_size, (textures[i].row + 1) * texture_size); glTexCoord2f( shift + (textures[i].movie_width)/((double) texture_size), shift + (textures[i].movie_height)/((double) texture_size) ); glVertex2i( (textures[i].col + 1) * texture_size, (textures[i].row + 1) * texture_size); glTexCoord2f( shift + (textures[i].movie_width)/((double) texture_size), shift ); glVertex2i( (textures[i].col + 1) * texture_size, textures[i].row * texture_size ); glEnd( ); }}/* * Here we need to center the OpenGL viewport within the * window size that we are given. * * Parameters: * width: Width of the window in pixels * height: Height of the window in pixels */void glmovie_resize( GLuint width, GLuint height ){ glViewport( 0, 0, width, height ); glMatrixMode( GL_PROJECTION ); glLoadIdentity( ); gluOrtho2D( 0, tiled_width, tiled_height, 0 );}/* * Calculates the next power of 2 given a particular value. * Useful for calculating proper texture sizes for non power-of-2 * aligned texures. * * Parameters: * seed: Value to begin from * Returns: * Next power of 2 beginning from 'seed' */GLuint glmovie_next_power_of_2( GLuint seed ){ GLuint i; for( i = 1; i < seed; i *= 2 ) { }; return i;}/* * Initialize the movie player subsystem with the width and height * of the *movie data* (as opposed to the window). * * Parameters: * width: Width of movie in pixels * height: Height of movie in pixels * Returns: * GL_NO_ERROR on success * Any of the enumerated GL errors on failure */GLenum glmovie_init( GLuint width, GLuint height ){ /* Initial black texels. */ GLubyte* pixels; /* Absolute offsets from within tiled frame. */ GLuint offset_x = 0; GLuint offset_y = 0; GLuint skip_rows = 0; GLuint skip_pixels = 0; GLuint i, j, current; /* Save original movie dimensions. */ movie_width = width; movie_height = height; /* Get the power of 2 dimensions. */ tiled_width = glmovie_next_power_of_2( width ); tiled_height = glmovie_next_power_of_2( height ); while ( texture_size > tiled_width || texture_size > tiled_height ) texture_size /= 2; /* Now break it up into quads. */ num_texture_rows = tiled_height / texture_size; num_texture_cols = tiled_width / texture_size; /* Time for fun with data structures. */ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); glEnable( GL_TEXTURE_2D ); glEnable( GL_DITHER ); texture_ids = (GLuint*) malloc( sizeof( GLuint ) * num_texture_rows * num_texture_cols ); if( !texture_ids ) { return GL_OUT_OF_MEMORY; } glGenTextures( num_texture_rows * num_texture_cols, texture_ids ); textures = (glmovie_texture*) malloc( sizeof( glmovie_texture ) * num_texture_rows * num_texture_cols ); if( !textures ) { glDeleteTextures( num_texture_rows * num_texture_cols, texture_ids ); free( texture_ids ); return GL_OUT_OF_MEMORY; } for ( i = 0; i < num_texture_rows; i++ ) { skip_pixels = 0; for ( j = 0; j < num_texture_cols; j++ ) { current = i * num_texture_cols + j; /* Setup texture. */ textures[current].id = texture_ids[current]; textures[current].poly_width = texture_size; textures[current].poly_height = texture_size; textures[current].movie_width = (movie_width - 2) * (j + 1) / num_texture_cols - skip_pixels; textures[current].movie_height = (movie_height - 2) * (i + 1) / num_texture_rows - skip_rows; textures[current].row = i; textures[current].col = j; textures[current].skip_pixels = skip_pixels; textures[current].skip_rows = skip_rows; skip_pixels += textures[current].movie_width; pixels = (GLubyte*) malloc( textures[current].poly_width * textures[current].poly_height * 4 ); memset( pixels, 0, textures[current].poly_width * textures[current].poly_height * 4 ); if( !pixels ) { glDeleteTextures( num_texture_rows * num_texture_cols, texture_ids ); free( texture_ids ); free( textures ); return GL_OUT_OF_MEMORY; } /* Do all of our useful binding. */ glBindTexture( GL_TEXTURE_2D, textures[current].id ); glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); /* Specify our 256x256 black texture. */ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, textures[current].poly_width, textures[current].poly_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels ); free( pixels ); } skip_rows += textures[current].movie_height; } /* Simple state setup at the end. */ glClearColor( 0.0, 0.0, 0.0, 0.0 ); return glGetError( );}/* * Free any resources associated with the movie player. */void glmovie_quit( void ){ glDeleteTextures( num_texture_rows * num_texture_cols, texture_ids ); free( texture_ids ); free( textures );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -