886 lines
24 KiB
C++
886 lines
24 KiB
C++
//C Stuff
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
|
|
//OpenGL Stuff
|
|
#include <GL/glut.h>
|
|
|
|
|
|
#define VPD_MIN 200
|
|
#define VPD_DEFAULT 800
|
|
#define VPD_MAX 1024
|
|
|
|
#define ORTHO_SIZE 1.0
|
|
|
|
#ifndef M_PI
|
|
#define M_PI 3.14159265358979323846
|
|
#endif
|
|
#define TWOPI (2.0 * M_PI)
|
|
|
|
//This will store each pixel's final spot
|
|
typedef struct pixelMap {
|
|
int x;
|
|
int y;
|
|
} Pixel;
|
|
|
|
void doFancyAttractorStuff();
|
|
|
|
/*
|
|
* For some godforsaken reason, rand() is returning negative numbers in
|
|
* FreeBSD and Linux.
|
|
*
|
|
* Hence this.
|
|
*/
|
|
inline float RANDNUM() {
|
|
float f = (float)( (float)rand() / (float)(RAND_MAX+1) );
|
|
if (f < 0) {
|
|
return -1.*f;
|
|
}
|
|
return f;
|
|
}
|
|
|
|
enum MENU { MENU_LINES=0,
|
|
MENU_TRIANGLES,
|
|
MENU_SPRAY_MORE_POINTS,
|
|
MENU_RESET,
|
|
MENU_RANDOMIZE,
|
|
MENU_ANIMATE,
|
|
MENU_DRAWSITES,
|
|
MENU_SITECOLORBLACK,
|
|
MENU_INCREASE_SITE_SIZE,
|
|
MENU_DECREASE_SITE_SIZE,
|
|
MENU_DRAWING,
|
|
MENU_GRABSCREENCAP
|
|
};
|
|
|
|
|
|
typedef struct SRGB {
|
|
float r;
|
|
float g;
|
|
float b;
|
|
} RGB;
|
|
|
|
typedef struct SSite {
|
|
RGB color;
|
|
float x;
|
|
float y;
|
|
} Site;
|
|
|
|
|
|
typedef struct _rgb {
|
|
unsigned char r,g,b;
|
|
} ppm_rgb;
|
|
|
|
typedef struct _ppmimage {
|
|
int sizex,sizey;
|
|
ppm_rgb *color;
|
|
} ppmimage;
|
|
|
|
//////////////////
|
|
// Global STUFF //
|
|
//////////////////
|
|
|
|
#define DEFAULT_NUMPOINTS 64
|
|
#define DEFAULT_RANDSITES 0
|
|
#define DEFAULT_SITEWIDTH ORTHO_SIZE*.0025
|
|
|
|
#define SITE_PRECISION .009
|
|
|
|
GLint wid; // GLUT window id
|
|
GLint vpd = VPD_DEFAULT; // (square) viewport dimensions
|
|
GLuint cone; //Cone display list
|
|
GLuint numPoints = DEFAULT_NUMPOINTS; //number of points for the cone fan
|
|
GLuint randSites = DEFAULT_RANDSITES; //The number of random points to draw from
|
|
//bool animate = false; //whether the world is animated or not
|
|
bool drawSites = true; //whether or not to draw sites
|
|
bool siteColorBlack = true; //defines whether sites will be drawn as black or not
|
|
float siteWidth = DEFAULT_SITEWIDTH; //siteWidth for the rectangle
|
|
bool useFile = false; //Use the ppm file or not
|
|
ppmimage* pImage = NULL;
|
|
GLfloat *screenCap = NULL;
|
|
//bool capFPS = true;
|
|
//float ONE_OVER_FPS = DEFAULT_FPS; //fps cap
|
|
|
|
Pixel* current = NULL;
|
|
GLubyte* newScreen = NULL;
|
|
|
|
Site* sites = NULL;
|
|
|
|
/************************************************************/
|
|
ppmimage read_ppmimage ( const char *name )
|
|
{
|
|
ppmimage result;
|
|
int range;
|
|
FILE *fp = fopen(name,"rb");
|
|
|
|
if (!fp)
|
|
{
|
|
fprintf(stderr,"No file\n");
|
|
exit(1);
|
|
}
|
|
|
|
if (getc(fp)!='P' || getc(fp)!='6') {
|
|
fprintf(stderr,"Invalid File\n");
|
|
exit(1);
|
|
}
|
|
|
|
fscanf(fp,"%d%d%d\n",&result.sizex,&result.sizey,&range);
|
|
|
|
assert(range==255); // we'll use only rgb range 0...255 here
|
|
|
|
result.color = (ppm_rgb*)malloc(result.sizex*result.sizey*sizeof(ppm_rgb));
|
|
fread(result.color,sizeof(ppm_rgb),result.sizex*result.sizey,fp);
|
|
|
|
return result;
|
|
}
|
|
|
|
ppm_rgb getRGB(float x, float y) {
|
|
int newX, newY;
|
|
|
|
x+=ORTHO_SIZE;
|
|
y+=ORTHO_SIZE;
|
|
|
|
x /= ORTHO_SIZE*2.;
|
|
y /= ORTHO_SIZE*2.;
|
|
|
|
y = 1.-y;
|
|
|
|
//printf("x= %f y= %f\n",x,y);
|
|
|
|
newX = (int)((x*pImage->sizex)-1.);
|
|
newY = (int)((y*pImage->sizey)-1.);
|
|
|
|
if (newX > pImage->sizex-1) {
|
|
newX = pImage->sizex-1;
|
|
} else if (newX < 0) {
|
|
newX = 0;
|
|
}
|
|
if (newY > pImage->sizey-1) {
|
|
newY = pImage->sizey-1;
|
|
} else if (newY < 0) {
|
|
newY = 0;
|
|
}
|
|
|
|
//printf("X= %d Y= %d sizex=%d\n",newX,newY,pImage->sizex);
|
|
|
|
ppm_rgb p = pImage->color[(newY*pImage->sizex) + newX];
|
|
|
|
//printf("%d\n",(newY*pImage->sizex) + newX);
|
|
|
|
return pImage->color[(newY*pImage->sizex) + newX];
|
|
}
|
|
|
|
/*************************************************************/
|
|
|
|
/*
|
|
* Sites will never be NULL when this is called
|
|
*/
|
|
inline void reinit_sites() {
|
|
free(sites);
|
|
sites = (Site*)malloc(sizeof(Site)*randSites);
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
GLvoid set_random_color(Site* s) {
|
|
s->color.r = RANDNUM();
|
|
s->color.g = RANDNUM();
|
|
s->color.b = RANDNUM();
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
GLvoid set_all_random_color() {
|
|
for (GLuint i = 0; i < randSites; i++) {
|
|
set_random_color(sites+i);
|
|
}
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
GLvoid init_random_sites(int start) {
|
|
float x, y;
|
|
for (GLuint i = start; i < randSites; i++) {
|
|
|
|
x = RANDNUM() * ORTHO_SIZE * 2.;
|
|
y = RANDNUM() * ORTHO_SIZE * 2.;
|
|
|
|
x -= ORTHO_SIZE;
|
|
y -= ORTHO_SIZE;
|
|
|
|
sites[i].x = x;
|
|
sites[i].y = y;
|
|
|
|
set_random_color(sites+i);
|
|
|
|
}
|
|
}
|
|
|
|
GLvoid init_random_sites() {
|
|
init_random_sites(0);
|
|
}
|
|
|
|
|
|
/**
|
|
* This performs window resizing, like project 2
|
|
*/
|
|
GLvoid window_resize(GLint vpw, GLint vph)
|
|
{
|
|
glutSetWindow(wid);
|
|
|
|
/* maintain a square viewport, not too small, not too big */
|
|
if( vpw < vph ) vpd = vph;
|
|
else vpd = vpw;
|
|
|
|
if( vpd < VPD_MIN ) vpd = VPD_MIN;
|
|
if( vpd > VPD_MAX ) vpd = VPD_MAX;
|
|
|
|
glViewport(0, 0, vpd, vpd);
|
|
glutReshapeWindow(vpd, vpd);
|
|
|
|
glutPostRedisplay();
|
|
}
|
|
|
|
/**
|
|
* Window menu
|
|
*/
|
|
GLvoid menu ( int value ) {
|
|
switch (value) {
|
|
case MENU_LINES:
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
glutPostRedisplay();
|
|
break;
|
|
case MENU_TRIANGLES:
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
glutPostRedisplay();
|
|
break;
|
|
case MENU_SPRAY_MORE_POINTS:
|
|
randSites *= 2;
|
|
sites = (Site*)realloc(sites,sizeof(Site)*randSites);
|
|
init_random_sites(randSites/2);
|
|
glutPostRedisplay();
|
|
break;
|
|
case MENU_RESET:
|
|
//animate = false;
|
|
siteColorBlack = true;
|
|
if (newScreen != NULL) {
|
|
free(newScreen);
|
|
newScreen = NULL;
|
|
}
|
|
drawSites = true;
|
|
useFile = false;
|
|
siteWidth = DEFAULT_SITEWIDTH;
|
|
//Avoid constantly rerandomizing
|
|
if (randSites == DEFAULT_RANDSITES) {
|
|
glutPostRedisplay();
|
|
break;
|
|
}
|
|
case MENU_RANDOMIZE:
|
|
useFile = false;
|
|
//animate = false;
|
|
siteColorBlack = true;
|
|
drawSites = true;
|
|
randSites = DEFAULT_RANDSITES;
|
|
reinit_sites();
|
|
init_random_sites();
|
|
glutPostRedisplay();
|
|
break;
|
|
//case MENU_ANIMATE:
|
|
//animate ? animate = false : animate = true;
|
|
//glutPostRedisplay();
|
|
//break;
|
|
case MENU_DRAWSITES:
|
|
drawSites ? drawSites = false : drawSites = true;
|
|
glutPostRedisplay();
|
|
break;
|
|
case MENU_SITECOLORBLACK:
|
|
siteColorBlack ? siteColorBlack = false : siteColorBlack = true;
|
|
glutPostRedisplay();
|
|
break;
|
|
case MENU_INCREASE_SITE_SIZE:
|
|
siteWidth *= 2;
|
|
glutPostRedisplay();
|
|
break;
|
|
case MENU_DECREASE_SITE_SIZE:
|
|
siteWidth /= 2;
|
|
glutPostRedisplay();
|
|
break;
|
|
case MENU_DRAWING:
|
|
useFile ? useFile = false : useFile = true;
|
|
glutPostRedisplay();
|
|
break;
|
|
/*case MENU_UNCAP_FPS:
|
|
capFPS ? capFPS = false : capFPS = true;
|
|
break;
|
|
case MENU_RESET_FPS:
|
|
ONE_OVER_FPS = DEFAULT_FPS;
|
|
break;
|
|
case MENU_DECREASE_MAX_FPS:
|
|
ONE_OVER_FPS *= 2.;
|
|
break;*/
|
|
case MENU_GRABSCREENCAP:
|
|
drawSites = false;
|
|
glutPostRedisplay();
|
|
doFancyAttractorStuff();
|
|
//drawSites = true;
|
|
//glutPostRedisplay();
|
|
break;
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Keyboard input callback
|
|
*/
|
|
GLvoid keyboard_event(GLubyte key, GLint x, GLint y)
|
|
{
|
|
switch(key) {
|
|
case 27: /* ESC */
|
|
exit(0);
|
|
case 'l':
|
|
menu(MENU_LINES);
|
|
break;
|
|
case 'f':
|
|
menu(MENU_TRIANGLES);
|
|
break;
|
|
case 's':
|
|
menu(MENU_SPRAY_MORE_POINTS);
|
|
break;
|
|
case 'r':
|
|
menu(MENU_RESET);
|
|
break;
|
|
case 'e':
|
|
menu(MENU_RANDOMIZE);
|
|
break;
|
|
/*case 'a':
|
|
menu(MENU_ANIMATE);
|
|
break;*/
|
|
case 'd':
|
|
menu(MENU_DRAWSITES);
|
|
break;
|
|
case 'i':
|
|
menu(MENU_SITECOLORBLACK);
|
|
break;
|
|
case '+':
|
|
menu(MENU_INCREASE_SITE_SIZE);
|
|
break;
|
|
case '-':
|
|
menu(MENU_DECREASE_SITE_SIZE);
|
|
break;
|
|
case 't':
|
|
menu(MENU_DRAWING);
|
|
break;
|
|
/*case 'u':
|
|
menu(MENU_UNCAP_FPS);
|
|
break;
|
|
case 'j':
|
|
menu(MENU_RESET_FPS);
|
|
break;
|
|
case 'k':
|
|
menu(MENU_DECREASE_MAX_FPS);
|
|
break;*/
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle mouse drag motion
|
|
*/
|
|
GLvoid button_motion(GLint mx, GLint my) {
|
|
//printf("Dragging %d %d\n",mx,my);
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* Handle mouse movement
|
|
*/
|
|
GLvoid passive_motion(GLint mx, GLint my) {
|
|
//printf("Someone is moving above me %d %d\n",mx,my);
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* Redraw the view
|
|
*/
|
|
GLvoid redraw(GLvoid) {
|
|
|
|
if (newScreen != NULL) {
|
|
glutSetWindow(wid);
|
|
|
|
//glPushMatrix();
|
|
|
|
glRasterPos2i(-1,-1);
|
|
|
|
glColor3f(1.0,1.0,1.0);
|
|
glDrawPixels(vpd,vpd,GL_RGB,GL_UNSIGNED_BYTE,newScreen);
|
|
|
|
glFlush();
|
|
|
|
glutSwapBuffers();
|
|
//glPopMatrix();
|
|
return;
|
|
}
|
|
|
|
clock_t frame = clock();
|
|
|
|
/* set the projection matrix */
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
glOrtho(-ORTHO_SIZE,ORTHO_SIZE,-ORTHO_SIZE,ORTHO_SIZE,15.0,25.0);
|
|
//gluPerspective(20.0,1.0,15.0,25.0);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
glTranslatef(0,0,-20.0);
|
|
|
|
/* ensure we're drawing to the correct GLUT window */
|
|
glutSetWindow(wid);
|
|
|
|
/* clear the color buffers */
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
ppm_rgb temp;
|
|
|
|
/* Draw random points */
|
|
for (GLuint i = 0; i < randSites; i++) {
|
|
glPushMatrix();
|
|
|
|
glTranslatef(sites[i].x,
|
|
sites[i].y,
|
|
0);
|
|
if (useFile && pImage) {
|
|
temp = getRGB(sites[i].x,sites[i].y);
|
|
|
|
glColor3f(temp.r / 255., temp.g / 255., temp.b / 255.);
|
|
|
|
} else {
|
|
glColor3f(sites[i].color.r,
|
|
sites[i].color.g,
|
|
sites[i].color.b);
|
|
}
|
|
glCallList(cone);
|
|
|
|
if (drawSites) {
|
|
if (siteColorBlack) {
|
|
glColor3f(0,0,0);
|
|
} else {
|
|
glColor3f(1-sites[i].color.r,
|
|
1-sites[i].color.g,
|
|
1-sites[i].color.b);
|
|
}
|
|
glRectf(-siteWidth,-siteWidth,siteWidth,siteWidth);
|
|
}
|
|
glPopMatrix();
|
|
}
|
|
|
|
/*if (current != NULL) {
|
|
float x = (current->x / vpd) * ORTHO_SIZE * 2.;
|
|
float y = (current->y / vpd) * ORTHO_SIZE * 2.;
|
|
|
|
x -= ORTHO_SIZE;
|
|
y -= ORTHO_SIZE;
|
|
|
|
y = ORTHO_SIZE*2. - y;
|
|
glPushMatrix();
|
|
glTranslatef(x,y,0);
|
|
glRectf(-siteWidth,-siteWidth,siteWidth,siteWidth);
|
|
glPopMatrix();
|
|
}*/
|
|
|
|
/* flush the pipeline */
|
|
glFlush();
|
|
|
|
/* look at our handiwork */
|
|
glutSwapBuffers();
|
|
|
|
printf("Finished redisplay");
|
|
}
|
|
|
|
/**
|
|
* Mouse button pressed
|
|
*/
|
|
GLvoid mouse_button(GLint btn, GLint state, GLint mx, GLint my)
|
|
{
|
|
if (btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
|
|
|
|
randSites++;
|
|
sites = (Site*)realloc(sites,sizeof(Site)*randSites);
|
|
init_random_sites(randSites-1);
|
|
sites[randSites-1].x = ((mx/((float)vpd)) * ORTHO_SIZE * 2.) - ORTHO_SIZE;
|
|
sites[randSites-1].y = -1.*(((my/((float)vpd)) * ORTHO_SIZE * 2.)-ORTHO_SIZE);
|
|
|
|
printf("Added Site at: %d %d w/ %f %f %f\n",mx,my,
|
|
sites[randSites-1].color.r,sites[randSites-1].color.g,
|
|
sites[randSites-1].color.b);
|
|
|
|
glutPostRedisplay();
|
|
}
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* This handles the glut initialization
|
|
*/
|
|
GLint init_glut(GLint *argc, char **argv)
|
|
{
|
|
GLint id;
|
|
|
|
glutInit(argc,argv);
|
|
|
|
/* size and placement hints to the window system */
|
|
glutInitWindowSize(vpd, vpd);
|
|
glutInitWindowPosition(10,10);
|
|
|
|
/* double buffered, RGB color mode */
|
|
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
|
|
|
|
/* create a GLUT window (not drawn until glutMainLoop() is entered) */
|
|
id = glutCreateWindow("cs4451 project 3: Voronoi Diagram");
|
|
|
|
/* register callbacks */
|
|
|
|
/* window size changes */
|
|
glutReshapeFunc(window_resize);
|
|
|
|
/* keypress handling when the current window has input focus */
|
|
glutKeyboardFunc(keyboard_event);
|
|
|
|
/* mouse event handling */
|
|
glutMouseFunc(mouse_button); /* button press/release */
|
|
glutMotionFunc(button_motion); /* mouse motion w/ button down */
|
|
glutPassiveMotionFunc(passive_motion); /* mouse motion with button up */
|
|
|
|
/* window obscured/revealed event handler */
|
|
glutVisibilityFunc(NULL);
|
|
|
|
/* handling of keyboard SHIFT, ALT, CTRL keys */
|
|
glutSpecialFunc(NULL);
|
|
|
|
/* what to do when mouse cursor enters/exits the current window */
|
|
glutEntryFunc(NULL);
|
|
|
|
/* what to do on each display loop iteration */
|
|
glutDisplayFunc(redraw);
|
|
|
|
/* Create the menu */
|
|
|
|
GLint viewMenu = glutCreateMenu(menu);
|
|
glutAddMenuEntry("Lines Only (l)",MENU_LINES);
|
|
glutAddMenuEntry("Full View (f)",MENU_TRIANGLES);
|
|
|
|
GLint siteMenu = glutCreateMenu(menu);
|
|
glutAddMenuEntry("Show/Hide Sites (d)",MENU_DRAWSITES);
|
|
glutAddMenuEntry("Toggle inverse site coloring (i)",MENU_SITECOLORBLACK);
|
|
glutAddMenuEntry("Increase site size (+)",MENU_INCREASE_SITE_SIZE);
|
|
glutAddMenuEntry("Decrease site size (-)",MENU_DECREASE_SITE_SIZE);
|
|
|
|
/*GLint fpsMenu = glutCreateMenu(menu);
|
|
glutAddMenuEntry("Increase Max FPS (j)",MENU_RESET_FPS);
|
|
glutAddMenuEntry("Decrease Max FPS (k)",MENU_DECREASE_MAX_FPS);
|
|
glutAddMenuEntry("Uncap FPS (u)",MENU_UNCAP_FPS);*/
|
|
|
|
/*GLint menuID = */
|
|
glutCreateMenu(menu);
|
|
glutAddSubMenu("View Options",viewMenu);
|
|
glutAddSubMenu("Site Options",siteMenu);
|
|
/*glutAddSubMenu("Framerate Options",fpsMenu);*/
|
|
glutAddMenuEntry("Spray More Points (s)",MENU_SPRAY_MORE_POINTS);
|
|
/*glutAddMenuEntry("Move Points (a)",MENU_ANIMATE);*/
|
|
glutAddMenuEntry("Toggle Coloring Method (t)",MENU_DRAWING);
|
|
glutAddMenuEntry("Grab Screencap",MENU_GRABSCREENCAP);
|
|
glutAddMenuEntry("Reset (r)",MENU_RESET);
|
|
glutAddMenuEntry("Reset-Randomize (e)",MENU_RANDOMIZE);
|
|
|
|
|
|
glutAttachMenu(GLUT_RIGHT_BUTTON);
|
|
|
|
return id;
|
|
}
|
|
|
|
/**
|
|
* OpenGL initializations
|
|
*/
|
|
GLvoid init_opengl(GLvoid)
|
|
{
|
|
/* clear to BLACK */
|
|
glClearColor(0.0, 0.0, 0.0, 1.0);
|
|
|
|
/* Enable depth test */
|
|
glEnable(GL_DEPTH_TEST);
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////
|
|
// Voronoi Diagram stuff //
|
|
///////////////////////////
|
|
|
|
|
|
GLuint init_cone ( )
|
|
{
|
|
GLuint sceneList = glGenLists(1);
|
|
float temp;
|
|
|
|
glNewList(sceneList,GL_COMPILE);
|
|
glBegin(GL_TRIANGLE_FAN);
|
|
|
|
//Initialize the first vertex
|
|
glVertex3f(0,0,0);
|
|
|
|
for (GLuint k = 0; k < numPoints; k++) {
|
|
temp = (TWOPI*k) / (float)numPoints;
|
|
glVertex4f(cos(temp),sin(temp),-1,0);
|
|
}
|
|
glVertex4f(cos(0.),sin(0.),-1,0);
|
|
|
|
glEnd();
|
|
glEndList();
|
|
|
|
return sceneList;
|
|
}
|
|
|
|
|
|
int main(int argc, char* argv[]) {
|
|
ppmimage image;
|
|
srand(time(NULL));
|
|
|
|
if (argc >= 2) {
|
|
image = read_ppmimage(argv[1]);
|
|
pImage = ℑ
|
|
}
|
|
|
|
wid = init_glut(&argc,argv);
|
|
init_opengl();
|
|
|
|
cone = init_cone();
|
|
|
|
randSites = 0;
|
|
|
|
sites = (Site*)malloc(sizeof(Site)*randSites);
|
|
init_random_sites();
|
|
|
|
glutMainLoop();
|
|
|
|
return 0;
|
|
}
|
|
|
|
inline bool movePixel(Pixel* curr, Pixel* center) {
|
|
float distance1, distance2, distance3, distance4;
|
|
float xP1, yP1;
|
|
bool tx, ty;
|
|
|
|
//x++
|
|
if((curr->x< vpd-1) && *((screenCap+(curr->y*vpd*3))+(curr->x*3)) ==
|
|
*((screenCap+(curr->y*vpd*3))+((curr->x+1)*3)))
|
|
{
|
|
distance1 = sqrt(pow(curr->x+1,2)+pow(curr->y,2));
|
|
} else { distance1 = 0; }
|
|
|
|
//x--
|
|
if((curr->x > 1) && *((screenCap+(curr->y*vpd*3))+(curr->x*3)) ==
|
|
*((screenCap+(curr->y*vpd*3))+((curr->x-1)*3)))
|
|
{
|
|
distance2 = sqrt(pow(curr->x-1,2)+pow(curr->y,2));
|
|
} else { distance2 = 0; }
|
|
tx = distance1 > distance2;
|
|
xP1 = tx ? distance1 : distance2;
|
|
|
|
//y++
|
|
if((curr->y < vpd-1) && *((screenCap+(curr->y*vpd*3))+(curr->x*3)) ==
|
|
*((screenCap+((curr->y+1)*vpd*3))+(curr->x*3)))
|
|
{
|
|
distance3 = sqrt(pow(curr->x,2) +pow(curr->y+1,2));
|
|
} else { distance3 = 0; }
|
|
|
|
//y--
|
|
if((curr->y > 1) && *((screenCap+(curr->y*vpd*3))+(curr->x*3)) ==
|
|
*((screenCap+((curr->y-1)*vpd*3))+(curr->x*3)))
|
|
{
|
|
distance4 = sqrt(pow(curr->x,2) +pow(curr->y-1,2));
|
|
} else {distance4 = 0;}
|
|
|
|
ty = distance3 > distance4;
|
|
yP1 = ty ? distance3 : distance4;
|
|
|
|
if (yP1 == xP1 == 0) {
|
|
return true;
|
|
}
|
|
else if (xP1 > yP1) {
|
|
tx ? curr->x+=1 : curr->x-=1;
|
|
return false;
|
|
} else if (xP1 > yP1) {
|
|
ty ? curr->y+=1 : curr->y-=1;
|
|
return false;
|
|
}
|
|
return false;
|
|
|
|
}
|
|
|
|
void doFancyAttractorStuff() {
|
|
//This will give us every pixel
|
|
Pixel *pixelMap = (Pixel*)malloc(vpd*vpd*sizeof(Pixel));
|
|
Pixel *attractors = NULL;
|
|
int numAttractors = 0;
|
|
|
|
//Allocate space for the current screen
|
|
screenCap = (GLfloat*)realloc(screenCap,vpd*vpd*3*sizeof(GLfloat));
|
|
|
|
newScreen = (GLubyte*)realloc(newScreen,vpd*vpd*3*sizeof(GLubyte));
|
|
|
|
//Quake2's Source code came in useful, figured out what function to use ;)
|
|
glReadPixels (0, 0, vpd, vpd, GL_RGB, GL_FLOAT, screenCap );
|
|
|
|
|
|
|
|
Pixel *curr;
|
|
//float distance;
|
|
Pixel center;
|
|
RGB color;
|
|
|
|
int lastX, lastY;
|
|
|
|
for (int j = 0; j < vpd; j++) {
|
|
for (int i = 0; i < vpd; i++) {
|
|
curr = (pixelMap+(j*vpd))+i;
|
|
curr->x = i;
|
|
curr->y = j;
|
|
|
|
color.r = *((screenCap+(j*vpd*3))+(i*3));
|
|
color.g = *((screenCap+(j*vpd*3))+(i*3)+1);
|
|
color.b = *((screenCap+(j*vpd*3))+(i*3)+2);
|
|
|
|
for (GLuint k = 0; k < randSites; k++) {
|
|
if (
|
|
sites[k].color.r - color.r <= SITE_PRECISION &&
|
|
sites[k].color.g - color.g <= SITE_PRECISION &&
|
|
sites[k].color.b - color.b <= SITE_PRECISION)
|
|
{
|
|
center.x = .5*vpd*(sites[k].x + ORTHO_SIZE);
|
|
center.y = .5*vpd*((2.*ORTHO_SIZE)-(sites[k].y + ORTHO_SIZE));
|
|
break;
|
|
}
|
|
}
|
|
|
|
//We now have the point we want to run like hell from
|
|
lastX = curr->x;
|
|
lastY = curr->y;
|
|
movePixel(curr,¢er);
|
|
|
|
int nX, nY;
|
|
nX = .5*vpd*(curr->x + ORTHO_SIZE);
|
|
nY = .5*vpd*((2.*ORTHO_SIZE)-(curr->y + ORTHO_SIZE));
|
|
|
|
if (*((screenCap+(nY*vpd*3))+(nX*3)) != color.r
|
|
|| *((screenCap+(nY*vpd*3))+(nX*3)+1) != color.g
|
|
|| *((screenCap+(nY*vpd*3))+(nX*3)+2) != color.b)
|
|
{
|
|
color.r = *((screenCap+(nY*vpd*3))+(nX*3));
|
|
color.g = *((screenCap+(nY*vpd*3))+(nX*3)+1);
|
|
color.b = *((screenCap+(nY*vpd*3))+(nX*3)+2);
|
|
|
|
for (GLuint k = 0; k < randSites; k++) {
|
|
if (
|
|
sites[k].color.r - color.r <= SITE_PRECISION &&
|
|
sites[k].color.g - color.g <= SITE_PRECISION &&
|
|
sites[k].color.b - color.b <= SITE_PRECISION)
|
|
{
|
|
center.x = .5*vpd*(sites[k].x + ORTHO_SIZE);
|
|
center.y = .5*vpd*((2.*ORTHO_SIZE)-(sites[k].y + ORTHO_SIZE));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
while (true) {
|
|
//glutPostRedisplay();
|
|
if (curr->x < 0 || curr->x >= vpd
|
|
|| curr->y < 0 || curr->y >= vpd)
|
|
{
|
|
//printf("Fell Outside\n");
|
|
curr->x = curr->y = -1;
|
|
*((newScreen+(j*vpd*3))+(i*3)) = 255;
|
|
*((newScreen+(j*vpd*3))+(i*3)+1) = 255;
|
|
*((newScreen+(j*vpd*3))+(i*3)+2) = 255;
|
|
break;
|
|
} else if ( rand() % 3 ) {
|
|
lastX = curr->x;
|
|
lastY = curr->y;
|
|
}
|
|
|
|
movePixel(curr,¢er);
|
|
nX = .5*vpd*(curr->x + ORTHO_SIZE);
|
|
nY = .5*vpd*((2.*ORTHO_SIZE)-(curr->y + ORTHO_SIZE));
|
|
|
|
if (*((screenCap+(nY*vpd*3))+(nX*3)) != color.r
|
|
|| *((screenCap+(nY*vpd*3))+(nX*3)+1) != color.g
|
|
|| *((screenCap+(nY*vpd*3))+(nX*3)+2) != color.b)
|
|
{
|
|
color.r = *((screenCap+(nY*vpd*3))+(nX*3));
|
|
color.g = *((screenCap+(nY*vpd*3))+(nX*3)+1);
|
|
color.b = *((screenCap+(nY*vpd*3))+(nX*3)+2);
|
|
|
|
for (GLuint k = 0; k < randSites; k++) {
|
|
if (
|
|
sites[k].color.r - color.r <= SITE_PRECISION &&
|
|
sites[k].color.g - color.g <= SITE_PRECISION &&
|
|
sites[k].color.b - color.b <= SITE_PRECISION)
|
|
{
|
|
center.x = .5*vpd*(sites[k].x + ORTHO_SIZE);
|
|
center.y = .5*vpd*((2.*ORTHO_SIZE)-(sites[k].y + ORTHO_SIZE));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (abs(curr->x - lastX) + abs(curr->y - lastY) == 0) {
|
|
printf("%d %d At attractor: %3d %3d\n",i,j,curr->x,curr->y);
|
|
*((newScreen+(j*vpd*3))+(i*3)) = i+j;
|
|
*((newScreen+(j*vpd*3))+(i*3)+1) = i+j;
|
|
*((newScreen+(j*vpd*3))+(i*3)+2) = i+j;
|
|
/*int k;
|
|
|
|
for (k = 0; k < numAttractors; k++) {
|
|
if (abs(attractors[i].x - curr->x) + abs(attractors[i].y - curr->y)
|
|
< 8)
|
|
{
|
|
printf("At attractor %d\n",k);
|
|
break;
|
|
}
|
|
}
|
|
if (k == numAttractors) {
|
|
printf("New Attractor %d\n",numAttractors);
|
|
numAttractors++;
|
|
attractors = (Pixel*)realloc(attractors,sizeof(Pixel)*numAttractors);
|
|
attractors[k].x = curr->x;
|
|
attractors[k].y = curr->y;
|
|
}*/
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
//printf("col %d: %f %f %f\n",j,color.r,color.g,color.b);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|