//////////////////////////////////////////////////////////////
//															//
//		-= The Cornflake Zone =-							//
//															//
//			-==============-								//
//															//	
//		Twisting Bulging Effect using OpenGL 				//
//		Written by Francis Shanahan, October 14th 2000		//
//															//
//		If you find this code useful mail me at				//
//		mainflake@cornflakezone.com							//	
//		http://www.cornflakezone.com						//
//															//
//////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h> 
#include <GL/glut.h>
#include <GL/glaux.h>
  static char *programname = "Cornflake Zone - Twisty Bulge";
  #define WINDOW_WIDTH	300
#define WINDOW_HEIGHT	300
  #define EPSILON			0.000001 
#define MY_PI			3.1415926535
  // These vectors store the coordinates.
float intX[50][50];
float intY[50][50];
  // This alters the size of the generated square.
#define size 1
  // Storage for 1 textures
GLuint	cflaketexture;		
  // A switch to decide if we're twisting or bulging
int twistbulge = 1;
  // If we're texture mapped or not
int usetexture = 0;
  // If we're drawing in lines or polygons.
int lines = 1;
  /********************************************************************
*
*	myarctan()
*
*	returns the arctan of y/x
*  This function is faster than the system "atan2()", which is why
*	we don't use the system function.
*
*/
  float 
myarctan(float x, float y)
{
    if (fabs(x) < EPSILON) {
		if (fabs(y) < EPSILON) {
			return(0.0);
        }
		else if (y > 0.0) {
			return(1.570796327f);  /*(pi*0.5);*/
        }
		else {
			return(4.712388980f);  /*(pi*1.5);*/
        }
    } else if (x<0.0) {
		return(atan(y/x)+ MY_PI);
    } else {
        return(atan(y/x)); 
    }
}
  /*************************************************************************
*
*	TwistyBulge()					
*
*	This is the meat of the program. we generate X and Y coords then
*	manipulate the points inside a unit circle.
*
*/
  void 
TwistyBulge(float p, float rotation)
{
    int iy, ix;
    int i=0,j=0;
    float r,theta,x=-1, y;
	float ax[4],ay[4];
	
	// These loops generate the coordinates.
    for (ix = 0; ix < 28 ; ix++) {   
		y=-1;
  		for (iy =0; iy < 20 ; iy++) { 
			// Get the radius of the current point
			r=sqrt(x*x+y*y);
  			// Get the current rotation
			theta = myarctan(x,y);   
            
			// If we're inside the unit circle
			if (r < 1.0) { 			    
				if(p!=1.0) {
  					// manipulate the radius
					// this is the bulging part.
					r=exp(log(r)*p); 
				}
				// this is the rotation part.
				theta+=(1.0-r)*rotation ;			    
            }
  			// Finally set the coordinates
			intX[i][j]= (size * r * cos(theta)); 
			intY[i][j]= (size * r * sin(theta));
  			j++;
			y += 0.1;
		}
		
		x+=0.075;
		j=0;
		i++;
    }
  	// At this point all vertices have been calculated.
	// We just need to draw them
    	
	// If we're to draw the lines only
	if ( lines ) {
		glBegin(GL_LINES); 
	} else {
		glBegin(GL_TRIANGLES); 
		
		// If texture mapping is on then bind the texture
		if (usetexture) {
			glColor3f( 1,1,1);
			glBindTexture(GL_TEXTURE_2D, cflaketexture);
		}
	}
	
	// Now we draw the grid 
    for (j=1;j<19;j++){    
		for (i=1;i<28;i++) {
			
			// These are the x and y coordinates.
			// I've coded it like this for readability
			ax[0]= intX[i-1][j]     ;
			ax[1]= intX[i][j]       ;
			ax[2]= intX[i][j+1]     ;
			ax[3]= intX[i-1][j+1]   ;
			
			ay[0]= intY[i-1][j]     ;
			ay[1]= intY[i][j]       ;
			ay[2]= intY[i][j+1]     ;
			ay[3]= intY[i-1][j+1]   ;
			
			// If we're to draw the lines only
			if ( lines ) { 
				
				glColor3f( 1.0f, 1.0f, 1.0f);
  				// Draw the first line
				glVertex3f(ax[0] , ay[0], 0);    
				glVertex3f(ax[1] , ay[1], 0);
				
				// Draw the second line
				glVertex3f(ax[0] , ay[0], 0); 
				glVertex3f(ax[3] , ay[3], 0);
				
			} else {
				// We draw polygons.
				
				if (usetexture) {
					// We draw texture coords with the polygons 
					
					// Draw the first polygon
					glTexCoord2f( (float)(i  )/28 , (float)(j  ) / 19); glVertex3f(ax[0] , ay[0], 0);    
					glTexCoord2f( (float)(i+1)/28 , (float)(j  ) / 19); glVertex3f(ax[1] , ay[1], 0);			
					glTexCoord2f( (float)(i+1)/28 , (float)(j+1) / 19); glVertex3f(ax[2] , ay[2], 0); 
					
					// Draw the second textured polygon
					glTexCoord2f( (float)(i  )/28 , (float)(j  ) / 19); glVertex3f(ax[0] , ay[0], 0); 
					glTexCoord2f( (float)(i  )/28 , (float)(j+1) / 19); glVertex3f(ax[3] , ay[3], 0);
					glTexCoord2f( (float)(i+1)/28 , (float)(j+1) / 19); glVertex3f(ax[2] , ay[2], 0);
			
				} else {
					// Just draw plain polygons
					glColor3f( 0.89f, 0.36f, 0.0f);
					
					// Draw the first polygon
					glVertex3f(ax[0] , ay[0], 0);    
					glVertex3f(ax[1] , ay[1], 0);			
					glVertex3f(ax[2] , ay[2], 0); 
					
					glColor3f( 0.3f, 0.3f, 0.3f);
					// Draw the second polygon
					glVertex3f(ax[0] , ay[0], 0); 
					glVertex3f(ax[3] , ay[3], 0);
					glVertex3f(ax[2] , ay[2], 0);
				}
			}
		}
    } 
	glEnd();
}
  
/*************************************************************************
*
*	idle()
*
*/
void
idle(void)
{
	glutPostRedisplay();
}
  /*************************************************************************
*
*	LoadGLTextures()
*
*	Real simple keyboard handler
*
*/
void
keyboard(unsigned char ch, int x, int y)
{
	switch (ch) {
	case 27:             /* escape */
		exit(0);
		break;
	case ' ':
		twistbulge^=1;
		break;
	case 't':
		usetexture^=1;
		lines = 0;
  		if (usetexture) {
			glEnable(GL_TEXTURE_2D);
		} else {
			glDisable(GL_TEXTURE_2D);
		}
		break;
	case 'l':
		lines^=1;
		break;
	}
  }
  /*************************************************************************
*
*	display()
*
*	Main display function
*
*
*/
  void
display(void)
{
	static float twist=0.0; // My twist factor
	static float bulge=1; // The bulge factor
	static float off=0.1; // The increment ( offset )
	
	// Clear the screen
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	// This is just a simple switch to decide if
	// we're twisting or bulging.
	if (twistbulge) {
		twist+=off;
		// These are magic numbers, you can play around with them
		// to find what works best for you
		if (twist<=-2.4) off=0.05;
		if (twist>= 2.4) off=-0.05;
	} else {
		bulge+=off;
		if (bulge<=0.2) off=0.05;
		if (bulge>=3.6) off=-0.05;
	}
	
	// Render the scene
	TwistyBulge( bulge, twist);    
	
	//glFlush();
	glutSwapBuffers();
	
}
  
/*************************************************************************
*
*	LoadGLTextures()
*
*	Load Bitmaps And Convert To Textures
*
*/
GLvoid LoadGLTextures()
{
	// Load Texture
	AUX_RGBImageRec *texture1;
	
	texture1 = auxDIBImageLoad("Data/cflakezone.bmp");
	if (!texture1)
	{
		exit(1);
	}
	
	// Create Linear Filtered Texture
	glBindTexture(GL_TEXTURE_2D, cflaketexture);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexImage2D(GL_TEXTURE_2D, 0, 3, texture1->sizeX, texture1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, texture1->data);
	
}
  /*************************************************************************
*
*	glInit()
*
*	Sets up OpenGL
*
*/
void glInit(){
	// Load The Texture(s)
	LoadGLTextures();	
  	// Enable Texture Mapping
	glEnable(GL_TEXTURE_2D);
  
	/* setup context */
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	
	// Calculate The Aspect Ratio Of The Window
	gluPerspective(45.0f, WINDOW_WIDTH /
		WINDOW_HEIGHT,0.1f,100.0f);	
	
	// Translate back a little for a better view.
	glTranslatef(0,0, -2.5);
	
	glShadeModel(GL_SMOOTH);
  	// Clear color is Black
	glClearColor(0.0, 0.0, 0.0, 1);
}
int
main(int argc, char **argv)
{
	glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
	glutInit(&argc, argv);
	
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	
	glutCreateWindow(programname);
	
	glutKeyboardFunc(keyboard);
	glutDisplayFunc(display);
	glutIdleFunc(idle);
	
	glInit();
	
	glutMainLoop();
	return 0;             /* ANSI C requires main to return int. */
}
   |