Total members 10249 | Gratitudes |It is currently Thu May 17, 2012 9:40 am Login / Join Codemiles


All times are UTC [ DST ]




Post new topic Reply to topic  Quick reply  [ 1 post ] 
Author Code Snippet
 Code subject: how to attach a texture to polygon
PostPosted: Sun Mar 20, 2011 10:26 pm 
Offline
Mastermind
User avatar

Joined: Tue Mar 27, 2007 10:55 pm
Posts: 2272
Location: Earth
Has thanked: 39 time
Have thanks: 61 time

TextureTorus.c:
Code:

/**************************************************
* TextureTorus.c
*
* Program to demonstrate how to attach a texture
*    map to a torus.  This is the LightTorus program,
*    modified to display a texture map.
*
* The torus can be viewed in wireframe or in "filled
*     polygon" mode.
*
* The triangles or quadrilaterals are wrapped around the
* torus in a single long strip.    See figure 13 Chapter I
* in the book mentioned below.
*
*
* Author: Samuel R. Buss
*
* Software accompanying the book
*      3D Computer Graphics: A Mathematical Introduction with OpenGL,
*      by S. Buss, Cambridge University Press, 2003.
*
* Software is "as-is" and carries no warranty.  It may be used without
*   restriction, but if you modify it, please change the filenames to
*   prevent confusion between different versions.
* Bug reports: Sam Buss, sbuss@ucsd.edu.
* Web page: http://math.ucsd.edu/~sbuss/MathCG
*
* USAGES: There are a number of keyboard commands that control
* the animation.  They must be typed into the graphics window,
* and are listed below:
*
* TURN THE TEXTURE OFF AND ON:
*   Press "t" to toggle the texture off and on.
*
* CONTROLLING RESOLUTION OF THE TORUS MESH
*   Press "W" to increase the number wraps.
*   Press "w" to decrease the number wraps.
*   Press "N" to increase the number of segments per wrap.
*   Press "n" to decrease the number of segments per wrap.
*   Press "q" to toggle between quadrangles and triangles.
*   
* CONTROLLING THE ANIMATION:
*   Press the "a" key to toggle the animation off and on.
*   Press the "s" key to perform a single step of the animation.
*   The left and right arrow keys controls the
*      rate of rotation around the y-axis.
*   The up and down arrow keys increase and decrease the rate of
*      rotation around the x-axis.  In order to reverse rotational
*      direction you must zero or reset the torus ("0" or "r").
*   Press the "r" key to reset the torus back to initial
*      position, with no rotation.
*   Press "0" (zero) to zero the rotation rates.
*
* CONTROLLING LIGHTS
*    Press '0' or '1' to toggle the first or second light off and on.
*   Press 'f' to toggle between flat and smooth shading.
*   Press 'l' to toggle local modes on and off (local viewer and positional light,
*      or non-local viewer and directional light).
*
* COMMANDS SHOWING OPENGL FEATURES:
*   Pressing "p" toggles between wireframe and polygon mode.
*   Pressing "f" key toggles between flat and smooth shading.
*
**/

#include <stdlib.h>
#include <math.h>
#include <limits.h>
#include "RgbImage.h"
#include "TextureTorus.h"
#include <GL/glut.h>            // OpenGL Graphics Utility Library

const float PI2 = 2.0f*3.1415926535;

GLenum runMode = GL_TRUE;

GLenum shadeModel = GL_FLAT;      // Toggles between GL_FLAT and GL_SMOOTH
GLenum polygonMode = GL_LINE;      // Toggles between GL_LINE and GL_FILL

// Variables controlling the animation
float RotX = 0.0f;               // Rotational position around x-axis
float RotY = 0.0f;               // Rotational position around y-axis
float RotIncrementX = 0.0;         // Rotational increment, x-axis
float RotIncrementY = 0.0;         // Rotational increment, y-axis
const float RotIncFactor = 1.5;   // Factor change in rot rate per key stroke

// Variables controlling the fineness of the polygonal mesh
int NumWraps = 10;
int NumPerWrap = 8;

// Variables controlling the size of the torus
float MajorRadius = 3.0;
float MinorRadius = 1.0;

// Mode flags
int QuadMode = 1;            // Quad/Triangle toggling
GLenum LocalMode = GL_TRUE;      // Local viewer/non-local viewer mode
int Light0Flag = 1;            // Is light #0 on?
int Light1Flag = 1;            // Is light #1 on?

// Lighting values
float ambientLight[4] = {0.6, 0.6, 0.6, 1.0};
float Lt0amb[4] = {0.2, 0.2, 0.2, 1.0};
float Lt0diff[4] = {1.0, 1.0, 1.0, 1.0};
float Lt0spec[4] = {1.0, 1.0, 1.0, 1.0};
float Lt0pos[4] = {1.7f*(MajorRadius+MinorRadius), 0.0f, 0.0f, 1.0f};

float Lt1amb[4] = {0.2, 0.2, 0.2, 1.0};
float Lt1diff[4] = {0.7, 0.7, 0.7, 1.0};
float Lt1spec[4] = {1.0, 1.0, 1.0, 1.0};
float Lt1pos[4] = {0.0f, 1.2f*(MajorRadius+MinorRadius), 0.0f, 1.0f};

// Material values
float Noemit[4] = {0.0, 0.0, 0.0, 1.0};
float Matspec[4] = {0.3, 0.3, 0.3, 1.0};
float Matnonspec[4] = {0.4, 0.4, 0.4, 1.0};
float Matshiny = 16.0;

// A texture
int TextureWrapVert=6;
int TextureWrapHoriz=6;
bool textureFlag = true;

// glutKeyboardFunc is called below to set this function to handle
//      all "normal" key presses.
void myKeyboardFunc( unsigned char key, int x, int y )
{
   switch ( key ) {
   case 'a':
      runMode = !runMode;
      break;
   case 's':
      runMode = GL_TRUE;
      updateScene();
      runMode = GL_FALSE;
      break;
   case 27:   // Escape key
      exit(1);
   case 'r':   // Reset the animation (resets everything)
      ResetAnimation();
      break;
   case 'z':   // Zero the rotation rates
      ZeroRotation();
      break;
   case 'f':   // Shade mode toggles from flat to smooth
      ShadeModelToggle();
      break;
   case 'p':   // Polygon mode toggles between fill and line
      FillModeToggle();
      break;
   case 'w':   // Decrement number of wraps around torus
      WrapLess();
      break;
   case 'W':   // Increment number of wraps around torus
      WrapMore();
      break;
   case 'n':   // Decrement number of polys per wrap
      NumPerWrapLess();
      break;
   case 'N':   // Increment number of polys per wrap
      NumPerWrapMore();
      break;
   case 'q':   // Toggle between triangles and Quadrilaterals
      QuadTriangleToggle();
      break;
   case 'l':   // Toggle between local and non-local viewer
      LocalToggle();
      break;
   case '0':   // Toggle light #0 on and off
      Light0Toggle();
      break;
   case '1':   // Toggle light #1 on and off
      Light1Toggle();
      break;
   case 't':
      textureFlag = !textureFlag;
      break;
   }
}

// glutSpecialFunc is called below to set this function to handle
//      all "special" key presses.  See glut.h for the names of
//      special keys.
void mySpecialKeyFunc( int key, int x, int y )
{
   switch ( key ) {
   case GLUT_KEY_UP:      
      // Either increase upward rotation, or slow downward rotation
      KeyUp();
      break;
   case GLUT_KEY_DOWN:
      // Either increase downwardward rotation, or slow upward rotation
      KeyDown();
      break;
   case GLUT_KEY_LEFT:
      // Either increase left rotation, or slow down rightward rotation.
      KeyLeft();
      break;
   case GLUT_KEY_RIGHT:
      // Either increase right rotation, or slow down leftward rotation.
      KeyRight();
      break;
   }
}

// The routines below are coded so that the only way to change from
//   one direction of rotation to the opposite direction is to first
//  reset the animation,

void KeyUp() {
    if ( RotIncrementX == 0.0 ) {
      RotIncrementX = -0.1;      // Initially, one-tenth degree rotation per update
   }
   else if ( RotIncrementX < 0.0f) {
      RotIncrementX *= RotIncFactor;
   }
   else {
      RotIncrementX /= RotIncFactor;
   }   
}

void KeyDown() {
    if ( RotIncrementX == 0.0 ) {
      RotIncrementX = 0.1;      // Initially, one-tenth degree rotation per update
   }
   else if ( RotIncrementX > 0.0f) {
      RotIncrementX *= RotIncFactor;
   }
   else {
      RotIncrementX /= RotIncFactor;
   }   
}

void KeyLeft() {
    if ( RotIncrementY == 0.0 ) {
      RotIncrementY = -0.1;      // Initially, one-tenth degree rotation per update
   }
   else if ( RotIncrementY < 0.0) {
      RotIncrementY *= RotIncFactor;
   }
   else {
      RotIncrementY /= RotIncFactor;
   }   
}

void KeyRight()
{
    if ( RotIncrementY == 0.0 ) {
      RotIncrementY = 0.1;      // Initially, one-tenth degree rotation per update
   }
   else if ( RotIncrementY > 0.0) {
      RotIncrementY *= RotIncFactor;
   }
   else {
      RotIncrementY /= RotIncFactor;
   }   
}


// Resets position and sets rotation rate back to zero.
void ResetAnimation() {
   RotX = RotY = RotIncrementX = RotIncrementY = 0.0;
}

// Sets rotation rates back to zero.
void ZeroRotation() {
   RotIncrementX = RotIncrementY = 0.0;
}

// Toggle between smooth and flat shading
void ShadeModelToggle() {
   if ( shadeModel == GL_FLAT ) {
      shadeModel = GL_SMOOTH;
   }
   else {
      shadeModel = GL_FLAT;
   }
}

// Toggle between line mode and fill mode for polygons.
void FillModeToggle() {
   if ( polygonMode == GL_LINE ) {
      polygonMode = GL_FILL;
   }
   else {
      polygonMode = GL_LINE;
   }
}

// Toggle quadrilaterial and triangle mode
void QuadTriangleToggle() {
   QuadMode = 1-QuadMode;
}

// Toggle from local to global mode
void LocalToggle() {
   LocalMode = !LocalMode;
   if ( LocalMode ) {
      Lt0pos[3] = Lt1pos[3] = 1.0;   // Put lights back at finite location.
   }
   else {
      Lt0pos[3] = Lt1pos[3] = 0.0;   // Put lights at infinity too.
   }
}

// The next two routines toggle the lights on and off
void Light0Toggle() {
   Light0Flag = 1-Light0Flag;
}

void Light1Toggle() {
   Light1Flag = 1-Light1Flag;
}


// Increment number of wraps
void WrapMore() {
   NumWraps++;
}

// Decrement number of wraps
void WrapLess() {
   if (NumWraps>4) {
      NumWraps--;
   }
}

// Increment number of segments per wrap
void NumPerWrapMore() {
   NumPerWrap++;   
}

// Decrement number segments per wrap
void NumPerWrapLess() {
   if (NumPerWrap>4) {
      NumPerWrap--;
   }
}

/*
* issue vertex command for segment number j of wrap number i.
*/
void putVertTexture(int i, int j) {
   float wrapFrac = (j%NumPerWrap)/(float)NumPerWrap;
   float wrapFracTex = (float)j/(float)NumPerWrap;
   float phi = PI2*wrapFrac;
   float thetaFrac = ((float)(i%NumWraps)+wrapFracTex)/(float)NumWraps;
   float thetaFracTex = ((float)i+wrapFracTex)/(float)NumWraps;
   float theta = PI2*thetaFrac;
   float sinphi = sin(phi);
   float cosphi = cos(phi);
   float sintheta = sin(theta);
   float costheta = cos(theta);
   float y = MinorRadius*sinphi;
   float r = MajorRadius + MinorRadius*cosphi;
   float x = sintheta*r;
   float z = costheta*r;

   glTexCoord2f( wrapFracTex*(float)TextureWrapVert, thetaFracTex*(float)TextureWrapHoriz );
   glNormal3f(sintheta*cosphi, sinphi, costheta*cosphi);
   glVertex3f(x,y,z);
}


void updateScene( void )
{

   // Clear the redering window
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

   glShadeModel( shadeModel );   // Set the shading to flat or smooth.
   glPolygonMode(GL_FRONT_AND_BACK, polygonMode);   // Set to be "wire" or "solid"
   glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, LocalMode);

   // Set up lights
   glDisable( GL_TEXTURE_2D );
   if ( Light0Flag==1 || Light1Flag==1 ) {
      // Emissive spheres have no other color.
      glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Noemit);
      glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Noemit);
      glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0);
   }
   if ( Light0Flag==1 ) {
      glPushMatrix();
      glTranslatef(Lt0pos[0], Lt0pos[1], Lt0pos[2]);
      glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Lt0diff);
      glutSolidSphere(0.2,5,5);
      glPopMatrix();
      glEnable(GL_LIGHT0);
      glLightfv(GL_LIGHT0, GL_POSITION, Lt0pos);
   }
   else {
      glDisable(GL_LIGHT0);
   }
   if ( Light1Flag==1 ) {
      glPushMatrix();
      glTranslatef(Lt1pos[0], Lt1pos[1], Lt1pos[2]);
      glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Lt1diff);
      glutSolidSphere(0.2,5,5);
      glPopMatrix();
      glEnable(GL_LIGHT1);
      glLightfv(GL_LIGHT1, GL_POSITION, Lt1pos);
   }
   else {
      glDisable(GL_LIGHT1);
   }

   // Torus Materials
   glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Matnonspec);
   glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Matspec);
   glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, Matshiny);
   glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Noemit);

   if ( textureFlag ) {
      glEnable( GL_TEXTURE_2D );
   }

   glPushMatrix();      // Save to use again next time.

   // Update the orientation of the torus, if the animation is running.
   if ( runMode ) {
      RotY += RotIncrementY;
      if ( fabs(RotY)>360.0 ) {
         RotY -= 360.0*((int)(RotY/360.0));
      }
      RotX += RotIncrementX;
      if ( fabs(RotX)>360.0 ) {
         RotX -= 360.0*((int)(RotX/360.0));
      }
   }
   // Set the orientation.
   glRotatef( RotX, 1.0, 0.0, 0.0);
   glRotatef( RotY, 0.0, 1.0, 0.0);

   // Draw the torus
   for (int i=0; i<NumWraps; i++ ) {
      glBegin( QuadMode ? GL_QUAD_STRIP : GL_TRIANGLE_STRIP);
      for (int j=0; j<=NumPerWrap; j++) {
         putVertTexture(i, j);
         putVertTexture(i+1,j);
      }
      glEnd();
   }

   // Draw a reference sphere
   glDisable( GL_TEXTURE_2D );
   glTranslatef( -MajorRadius-MinorRadius-0.3, 0.0, 0.0);
   glColor3f( 1.0f, 0.0f, 0.0f );
   glutWireSphere( 0.1f, 5, 5 );

   glPopMatrix();      // Restore to original matrix as set in resizeWindow()

   // Flush the pipeline, swap the buffers
    glFlush();
    glutSwapBuffers();
}

/*
* Read a texture map from a BMP bitmap file.
*/
void loadTextureFromFile(char *filename)
{   
   glClearColor (0.0, 0.0, 0.0, 0.0);
   glShadeModel(GL_FLAT);
   glEnable(GL_DEPTH_TEST);

   RgbImage theTexMap( filename );

   // Pixel alignment: each row is word aligned (aligned to a 4 byte boundary)
   //    Therefore, no need to call glPixelStore( GL_UNPACK_ALIGNMENT, ... );

   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

   gluBuild2DMipmaps(GL_TEXTURE_2D, 3,theTexMap.GetNumCols(), theTexMap.GetNumRows(),
                GL_RGB, GL_UNSIGNED_BYTE, theTexMap.ImageData() );

}

/*
* Initialize OpenGL: Lights, rendering modes, and textures.
*/
void initRendering()
{
    glEnable( GL_DEPTH_TEST );

   glEnable(GL_LIGHTING);      // Enable lighting calculations
   glEnable(GL_LIGHT0);      // Turn on lights (unnecessary here, since also in Animate()
   glEnable(GL_LIGHT1);
   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);   // Ambient light

   // Light 0 (Position is set in updateScene)
   glLightfv(GL_LIGHT0, GL_AMBIENT, Lt0amb);
   glLightfv(GL_LIGHT0, GL_DIFFUSE, Lt0diff);
   glLightfv(GL_LIGHT0, GL_SPECULAR, Lt0spec);

   // Light 1 (Position is set in updateScene)
   glLightfv(GL_LIGHT1, GL_AMBIENT, Lt1amb);
   glLightfv(GL_LIGHT1, GL_DIFFUSE, Lt1diff);
   glLightfv(GL_LIGHT1, GL_SPECULAR, Lt1spec);

   // Load the texture
   loadTextureFromFile( "WoodGrain.bmp" );
    glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
}

// Called when the window is resized
//      Sets up the projection view matrix (somewhat poorly, however)
void resizeWindow(int w, int h)
{
    float aspectRatio;
   glViewport( 0, 0, w, h );   // View port uses whole window
   h = (w == 0) ? 1 : h;
   aspectRatio = (float)w/(float)h;

   // Set up the proection view matrix
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    gluPerspective( 60.0, aspectRatio, 1.0, 30.0 );

   // Move system 10 units away to be able to view from the origin.
   // Also tilt the system 15 degrees downward in order to view from above.
   glMatrixMode( GL_MODELVIEW );
   glLoadIdentity();
   glTranslatef(0.0, 0.0, -10.0);
   glRotatef(15.0, 1.0,0.0,0.0);   
}


// Main routine
// Set up OpenGL, hook up callbacks, and start the main loop
int main( int argc, char** argv )
{
   glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );

   // Window position (from top corner), and size (width and hieght)
    glutInitWindowPosition( 10, 60 );
    glutInitWindowSize( 620, 160 );
    glutCreateWindow( "TextureTorus - Press \"t\" to toggle texture" );

   // Initialize OpenGL rendering modes
    initRendering();
   resizeWindow(620,160);

   // Set up callback functions for key presses
   glutKeyboardFunc( myKeyboardFunc );
   glutSpecialFunc( mySpecialKeyFunc );

   // Set up the callback function for resizing windows
    glutReshapeFunc( resizeWindow );

   // Call this for background processing
   glutIdleFunc( updateScene );
   // Call this whenever window needs redrawing
    glutDisplayFunc( updateScene );
   
   // Start the main loop.  glutMainLoop never returns.
   glutMainLoop(  );

    return(0);   // This line is never reached.
}



TextureTorus.h
Code:
/*
* TextureTorus.h
*
* Author: Samuel R. Buss
*
* Software accompanying the book
*      3D Computer Graphics: A Mathematical Introduction with OpenGL,
*      by S. Buss, Cambridge University Press, 2003.
*
* Software is "as-is" and carries no warranty.  It may be used without
*   restriction, but if you modify it, please change the filenames to
*   prevent confusion between different versions.
* Bug reports: Sam Buss, sbuss@ucsd.edu.
* Web page: http://math.ucsd.edu/~sbuss/MathCG
*/

// Function prototypes

void myKeyboardFunc( unsigned char key, int x, int y );
void mySpecialKeyFunc( int key, int x, int y );

void updateScene( void );

void initRendering();
void resizeWindow(int w, int h);

void KeyUp();
void KeyDown();
void KeyLeft();
void KeyRight();
void ResetAnimation();
void ZeroRotation();
void ShadeModelToggle();
void FillModeToggle();
void QuadTriangleToggle();
void LocalToggle();
void Light0Toggle();
void Light1Toggle();
void WrapMore();
void WrapLess();
void NumPerWrapMore();
void NumPerWrapLess();

// Torus specific routines.
void putVertTexture(int i, int j);





RgbImage.h
Code:
/*
*
* RayTrace Software Package, release 1.0.4,  February 2004.
*
* Author: Samuel R. Buss
*
* Software accompanying the book
*      3D Computer Graphics: A Mathematical Introduction with OpenGL,
*      by S. Buss, Cambridge University Press, 2003.
*
* Software is "as-is" and carries no warranty.  It may be used without
*   restriction, but if you modify it, please change the filenames to
*   prevent confusion between different versions.  Please acknowledge
*   all use of the software in any publications or products based on it.
*
* Bug reports: Sam Buss, sbuss@ucsd.edu.
* Web page: http://math.ucsd.edu/~sbuss/MathCG
*
*/

#ifndef RGBIMAGE_H
#define RGBIMAGE_H

#include <stdio.h>
#include <assert.h>

// Include the next line to turn off the routines that use OpenGL
// #define RGBIMAGE_DONT_USE_OPENGL

class RgbImage
{
public:
   RgbImage();
   RgbImage( const char* filename );
   RgbImage( int numRows, int numCols );   // Initialize a blank bitmap of this size.
   ~RgbImage();

   bool LoadBmpFile( const char *filename );      // Loads the bitmap from the specified file
   bool WriteBmpFile( const char* filename );      // Write the bitmap to the specified file
#ifndef RGBIMAGE_DONT_USE_OPENGL
   bool LoadFromOpenglBuffer();               // Load the bitmap from the current OpenGL buffer
#endif

   long GetNumRows() const { return NumRows; }
   long GetNumCols() const { return NumCols; }
   // Rows are word aligned
   long GetNumBytesPerRow() const { return ((3*NumCols+3)>>2)<<2; }   
   const void* ImageData() const { return (void*)ImagePtr; }

   const unsigned char* GetRgbPixel( long row, long col ) const;
   unsigned char* GetRgbPixel( long row, long col );
   void GetRgbPixel( long row, long col, float* red, float* green, float* blue ) const;
   void GetRgbPixel( long row, long col, double* red, double* green, double* blue ) const;

   void SetRgbPixelf( long row, long col, double red, double green, double blue );
   void SetRgbPixelc( long row, long col,
                  unsigned char red, unsigned char green, unsigned char blue );

   // Error reporting. (errors also print message to stderr)
   int GetErrorCode() const { return ErrorCode; }
   enum {
      NoError = 0,
      OpenError = 1,         // Unable to open file for reading
      FileFormatError = 2,   // Not recognized as a 24 bit BMP file
      MemoryError = 3,      // Unable to allocate memory for image data
      ReadError = 4,         // End of file reached prematurely
      WriteError = 5         // Unable to write out data (or no date to write out)
   };
   bool ImageLoaded() const { return (ImagePtr!=0); }  // Is an image loaded?

   void Reset();         // Frees image data memory

private:
   unsigned char* ImagePtr;   // array of pixel values (integers range 0 to 255)
   long NumRows;            // number of rows in image
   long NumCols;            // number of columns in image
   int ErrorCode;            // error code

   static short readShort( FILE* infile );
   static long readLong( FILE* infile );
   static void skipChars( FILE* infile, int numChars );
   static void RgbImage::writeLong( long data, FILE* outfile );
   static void RgbImage::writeShort( short data, FILE* outfile );
   
   static unsigned char doubleToUnsignedChar( double x );

};

inline RgbImage::RgbImage()
{
   NumRows = 0;
   NumCols = 0;
   ImagePtr = 0;
   ErrorCode = 0;
}

inline RgbImage::RgbImage( const char* filename )
{
   NumRows = 0;
   NumCols = 0;
   ImagePtr = 0;
   ErrorCode = 0;
   LoadBmpFile( filename );
}

inline RgbImage::~RgbImage()
{
   delete[] ImagePtr;
}

// Returned value points to three "unsigned char" values for R,G,B
inline const unsigned char* RgbImage::GetRgbPixel( long row, long col ) const
{
   assert ( row<NumRows && col<NumCols );
   const unsigned char* ret = ImagePtr;
   long i = row*GetNumBytesPerRow() + 3*col;
   ret += i;
   return ret;
}

inline unsigned char* RgbImage::GetRgbPixel( long row, long col )
{
   assert ( row<NumRows && col<NumCols );
   unsigned char* ret = ImagePtr;
   long i = row*GetNumBytesPerRow() + 3*col;
   ret += i;
   return ret;
}

inline void RgbImage::GetRgbPixel( long row, long col, float* red, float* green, float* blue ) const
{
   assert ( row<NumRows && col<NumCols );
   const unsigned char* thePixel = GetRgbPixel( row, col );
   const float f = 1.0f/255.0f;
   *red = f*(float)(*(thePixel++));
   *green = f*(float)(*(thePixel++));
   *blue = f*(float)(*thePixel);
}

inline void RgbImage::GetRgbPixel( long row, long col, double* red, double* green, double* blue ) const
{
   assert ( row<NumRows && col<NumCols );
   const unsigned char* thePixel = GetRgbPixel( row, col );
   const double f = 1.0/255.0;
   *red = f*(double)(*(thePixel++));
   *green = f*(double)(*(thePixel++));
   *blue = f*(double)(*thePixel);
}

inline void RgbImage::Reset()
{
   NumRows = 0;
   NumCols = 0;
   delete[] ImagePtr;
   ImagePtr = 0;
   ErrorCode = 0;
}


#endif // RGBIMAGE_H




RgbImage.cpp
Code:
/*
*
* RayTrace Software Package, release 1.0.4,  February 2004.
*
* Author: Samuel R. Buss
*
* Software accompanying the book
*      3D Computer Graphics: A Mathematical Introduction with OpenGL,
*      by S. Buss, Cambridge University Press, 2003.
*
* Software is "as-is" and carries no warranty.  It may be used without
*   restriction, but if you modify it, please change the filenames to
*   prevent confusion between different versions.  Please acknowledge
*   all use of the software in any publications or products based on it.
*
* Bug reports: Sam Buss, sbuss@ucsd.edu.
* Web page: http://math.ucsd.edu/~sbuss/MathCG
*
*/

#include "RgbImage.h"

#ifndef RGBIMAGE_DONT_USE_OPENGL
#include <windows.h>
#include "GL/gl.h"
#endif

RgbImage::RgbImage( int numRows, int numCols )
{
   NumRows = numRows;
   NumCols = numCols;
   ImagePtr = new unsigned char[NumRows*GetNumBytesPerRow()];
   if ( !ImagePtr ) {
      fprintf(stderr, "Unable to allocate memory for %ld x %ld bitmap.\n",
            NumRows, NumCols);
      Reset();
      ErrorCode = MemoryError;
   }
   // Zero out the image
   unsigned char* c = ImagePtr;
   int rowLen = GetNumBytesPerRow();
   for ( int i=0; i<NumRows; i++ ) {
      for ( int j=0; j<rowLen; j++ ) {
         *(c++) = 0;
      }
   }
}

/* ********************************************************************
*  LoadBmpFile
*  Read into memory an RGB image from an uncompressed BMP file.
*  Return true for success, false for failure.  Error code is available
*     with a separate call.
*  Author: Sam Buss December 2001.
**********************************************************************/

bool RgbImage::LoadBmpFile( const char* filename )

   Reset();
   FILE* infile = fopen( filename, "rb" );      // Open for reading binary data
   if ( !infile ) {
      fprintf(stderr, "Unable to open file: %s\n", filename);
      ErrorCode = OpenError;
      return false;
   }

   bool fileFormatOK = false;
   int bChar = fgetc( infile );
   int mChar = fgetc( infile );
   if ( bChar=='B' && mChar=='M' ) {         // If starts with "BM" for "BitMap"
      skipChars( infile, 4+2+2+4+4 );         // Skip 4 fields we don't care about
      NumCols = readLong( infile );
      NumRows = readLong( infile );
      skipChars( infile, 2 );               // Skip one field
      int bitsPerPixel = readShort( infile );
      skipChars( infile, 4+4+4+4+4+4 );      // Skip 6 more fields

      if ( NumCols>0 && NumCols<=100000 && NumRows>0 && NumRows<=100000 
         && bitsPerPixel==24 && !feof(infile) ) {
         fileFormatOK = true;
      }
   }
   if ( !fileFormatOK ) {
      Reset();
      ErrorCode = FileFormatError;
      fprintf(stderr, "Not a valid 24-bit bitmap file: %s.\n", filename);
      fclose ( infile );
      return false;
   }

   // Allocate memory
   ImagePtr = new unsigned char[NumRows*GetNumBytesPerRow()];
   if ( !ImagePtr ) {
      fprintf(stderr, "Unable to allocate memory for %ld x %ld bitmap: %s.\n",
            NumRows, NumCols, filename);
      Reset();
      ErrorCode = MemoryError;
      fclose ( infile );
      return false;
   }

   unsigned char* cPtr = ImagePtr;
   for ( int i=0; i<NumRows; i++ ) {
      int j;
      for ( j=0; j<NumCols; j++ ) {
         *(cPtr+2) = fgetc( infile );   // Blue color value
         *(cPtr+1) = fgetc( infile );   // Green color value
         *cPtr = fgetc( infile );      // Red color value
         cPtr += 3;
      }
      int k=3*NumCols;               // Num bytes already read
      for ( ; k<GetNumBytesPerRow(); k++ ) {
         fgetc( infile );            // Read and ignore padding;
         *(cPtr++) = 0;
      }
   }
   if ( feof( infile ) ) {
      fprintf( stderr, "Premature end of file: %s.\n", filename );
      Reset();
      ErrorCode = ReadError;
      fclose ( infile );
      return false;
   }
   fclose( infile );   // Close the file
   return true;
}

short RgbImage::readShort( FILE* infile )
{
   // read a 16 bit integer
   unsigned char lowByte, hiByte;
   lowByte = fgetc(infile);         // Read the low order byte (little endian form)
   hiByte = fgetc(infile);         // Read the high order byte

   // Pack together
   short ret = hiByte;
   ret <<= 8;
   ret |= lowByte;
   return ret;
}

long RgbImage::readLong( FILE* infile )

   // Read in 32 bit integer
   unsigned char byte0, byte1, byte2, byte3;
   byte0 = fgetc(infile);         // Read bytes, low order to high order
   byte1 = fgetc(infile);
   byte2 = fgetc(infile);
   byte3 = fgetc(infile);

   // Pack together
   long ret = byte3;
   ret <<= 8;
   ret |= byte2;
   ret <<= 8;
   ret |= byte1;
   ret <<= 8;
   ret |= byte0;
   return ret;
}

void RgbImage::skipChars( FILE* infile, int numChars )
{
   for ( int i=0; i<numChars; i++ ) {
      fgetc( infile );
   }
}

/* ********************************************************************
*  WriteBmpFile
*  Write an RGB image to an uncompressed BMP file.
*  Return true for success, false for failure.  Error code is available
*     with a separate call.
*  Author: Sam Buss, January 2003.
**********************************************************************/

bool RgbImage::WriteBmpFile( const char* filename )
{
   FILE* outfile = fopen( filename, "wb" );      // Open for reading binary data
   if ( !outfile ) {
      fprintf(stderr, "Unable to open file: %s\n", filename);
      ErrorCode = OpenError;
      return false;
   }

   fputc('B',outfile);
   fputc('M',outfile);
   int rowLen = GetNumBytesPerRow();
   writeLong( 40+14+NumRows*rowLen, outfile );   // Length of file
   writeShort( 0, outfile );               // Reserved for future use
   writeShort( 0, outfile );
   writeLong( 40+14, outfile );            // Offset to pixel data
   writeLong( 40, outfile );               // header length
   writeLong( NumCols, outfile );            // width in pixels
   writeLong( NumRows, outfile );            // height in pixels (pos for bottom up)
   writeShort( 1, outfile );      // number of planes
   writeShort( 24, outfile );      // bits per pixel
   writeLong( 0, outfile );      // no compression
   writeLong( 0, outfile );      // not used if no compression
   writeLong( 0, outfile );      // Pixels per meter
   writeLong( 0, outfile );      // Pixels per meter
   writeLong( 0, outfile );      // unused for 24 bits/pixel
   writeLong( 0, outfile );      // unused for 24 bits/pixel

   // Now write out the pixel data:
   unsigned char* cPtr = ImagePtr;
   for ( int i=0; i<NumRows; i++ ) {
      // Write out i-th row's data
      int j;
      for ( j=0; j<NumCols; j++ ) {
         fputc( *(cPtr+2), outfile);      // Blue color value
         fputc( *(cPtr+1), outfile);      // Blue color value
         fputc( *(cPtr+0), outfile);      // Blue color value
         cPtr+=3;
      }
      // Pad row to word boundary
      int k=3*NumCols;               // Num bytes already read
      for ( ; k<GetNumBytesPerRow(); k++ ) {
         fputc( 0, outfile );            // Read and ignore padding;
         cPtr++;
      }
   }

   fclose( outfile );   // Close the file
   return true;
}

void RgbImage::writeLong( long data, FILE* outfile )

   // Read in 32 bit integer
   unsigned char byte0, byte1, byte2, byte3;
   byte0 = (unsigned char)(data&0x000000ff);      // Write bytes, low order to high order
   byte1 = (unsigned char)((data>>8)&0x000000ff);
   byte2 = (unsigned char)((data>>16)&0x000000ff);
   byte3 = (unsigned char)((data>>24)&0x000000ff);

   fputc( byte0, outfile );
   fputc( byte1, outfile );
   fputc( byte2, outfile );
   fputc( byte3, outfile );
}

void RgbImage::writeShort( short data, FILE* outfile )

   // Read in 32 bit integer
   unsigned char byte0, byte1;
   byte0 = data&0x000000ff;      // Write bytes, low order to high order
   byte1 = (data>>8)&0x000000ff;

   fputc( byte0, outfile );
   fputc( byte1, outfile );
}


/*********************************************************************
* SetRgbPixel routines allow changing the contents of the RgbImage. *
*********************************************************************/

void RgbImage::SetRgbPixelf( long row, long col, double red, double green, double blue )
{
   SetRgbPixelc( row, col, doubleToUnsignedChar(red),
                     doubleToUnsignedChar(green),
                     doubleToUnsignedChar(blue) );
}

void RgbImage::SetRgbPixelc( long row, long col,
               unsigned char red, unsigned char green, unsigned char blue )
{
   assert ( row<NumRows && col<NumCols );
   unsigned char* thePixel = GetRgbPixel( row, col );
   *(thePixel++) = red;
   *(thePixel++) = green;
   *(thePixel) = blue;
}


unsigned char RgbImage::doubleToUnsignedChar( double x )
{
   if ( x>=1.0 ) {
      return (unsigned char)255;
   }
   else if ( x<=0.0 ) {
      return (unsigned char)0;
   }
   else {
      return (unsigned char)(x*255.0);      // Rounds down
   }
}
// Bitmap file format  (24 bit/pixel form)      BITMAPFILEHEADER
// Header (14 bytes)
//    2 bytes: "BM"
//   4 bytes: long int, file size
//   4 bytes: reserved (actually 2 bytes twice)
//   4 bytes: long int, offset to raster data
// Info header (40 bytes)                  BITMAPINFOHEADER
//   4 bytes: long int, size of info header (=40)
//    4 bytes: long int, bitmap width in pixels
//   4 bytes: long int, bitmap height in pixels
//   2 bytes: short int, number of planes (=1)
//   2 bytes: short int, bits per pixel
//   4 bytes: long int, type of compression (not applicable to 24 bits/pixel)
//   4 bytes: long int, image size (not used unless compression is used)
//   4 bytes: long int, x pixels per meter
//   4 bytes: long int, y pixels per meter
//   4 bytes: colors used (not applicable to 24 bit color)
//   4 bytes: colors important (not applicable to 24 bit color)
// "long int" really means "unsigned long int"
// Pixel data: 3 bytes per pixel: RGB values (in reverse order).
//   Rows padded to multiples of four.


#ifndef RGBIMAGE_DONT_USE_OPENGL

bool RgbImage::LoadFromOpenglBuffer()               // Load the bitmap from the current OpenGL buffer
{
   int viewportData[4];
   glGetIntegerv( GL_VIEWPORT, viewportData );
   int& vWidth = viewportData[2];
   int& vHeight = viewportData[3];
   
   if ( ImagePtr==0 ) { // If no memory allocated
      NumRows = vHeight;
      NumCols = vWidth;
      ImagePtr = new unsigned char[NumRows*GetNumBytesPerRow()];
      if ( !ImagePtr ) {
         fprintf(stderr, "Unable to allocate memory for %ld x %ld buffer.\n",
               NumRows, NumCols);
         Reset();
         ErrorCode = MemoryError;
         return false;
      }
   }
   assert ( vWidth>=NumCols && vHeight>=NumRows );
   int oldGlRowLen;
   if ( vWidth>=NumCols ) {
      glGetIntegerv( GL_UNPACK_ROW_LENGTH, &oldGlRowLen );
      glPixelStorei( GL_UNPACK_ROW_LENGTH, NumCols );
   }
   glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

   // Get the frame buffer data.
   glReadPixels( 0, 0, NumCols, NumRows, GL_RGB, GL_UNSIGNED_BYTE, ImagePtr);

   // Restore the row length in glPixelStorei  (really ought to restore alignment too).
   if ( vWidth>=NumCols ) {
      glPixelStorei( GL_UNPACK_ROW_LENGTH, oldGlRowLen );
   }   
   return true;
}

#endif   // RGBIMAGE_DONT_USE_OPENGL


Attachments:
untitled.GIF
untitled.GIF [ 9.04 KiB | Viewed 511 times ]

_________________
Currenlty programming with : java , html , php , and javascript . (OCJP-6 certified )
TOP
 Profile Send private message  
Reply with quote  
Post new topic Reply to topic Quick reply  [ 1 post ] 
Quick reply


  

 Similar topics
 Add light to texture
 Add texture to teapot object using
 add texture to cube3D
 Read an image bitmap (.bmp) file and draw it as texture
 Polygon in Java
 Text Texture in java
 Drawing a Polygon in php

All times are UTC [ DST ]


Users browsing similar codes

Users browsing this forum: No registered users and 1 guest



Jump to:  
Previous Code Snippet | Next Code Snippet 




Home
General Talks
Finished Projects
Code Library
Games
Tutorials

Java
C/C++
C-sharp
php
Script
JSP/Servlets
Ajax
ASP/ASP.net
Google SEO
Database
Communications
Phpbb3 styles
Photoshop tutorials
Flash tutorials
Find a job






Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
All copyrights reserved to codemiles.com 2007-2011
mileX v1.0 designed by codemiles team