//////////////////////////////////////////////////////////////
// //
// -= 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. */
}
|