//#include //#include //#include #include #include #include"ImageStone.h" //ImageStone is a free library used for loading images into c++. http://www.codeguru.com/cpp/g-m/bitmap/imagemanipulation/article.php/c12577/ #include #include using namespace std; unsigned long*** imagearray; //hold source image data unsigned long** viewarray; //hold desired image data float** color_data; int image_width; //how wide the source images are, in pixels. int image_height; //how tall the source images are, in pixels. int num_cameras; //how many source images we have. bool global_debug_test; float newX, newY, newZ; //desired viewpoint's coordinates class Plane{ //a mathematical plane. public: float a, b, c, d; //for plane equation: ax + by + cz + d = 0 }; class Ray{ public: float x,y,z; //x, y, z coordinates for starting point of ray float xdir, ydir, zdir; //x, y, z coordinates specificying direction vector }; class SourceImage{ public: int image_number; float x, y, z; //x y and z, values, where object is centered at 0,0,0. Plane ImagePlane; float r, g, b; //colors for that camera, used when we shade images by camera color. unsigned long PixelValue(int x, int y){ if((image_number-1) < 0){ cout<<"error code 1 "; cout<= image_width){ cout<<"error code 2"; }else if (y >= image_height){ cout<<"error code 3"; } return imagearray[(image_number - 1)][x][y]; } void MakePlane(){ //creates a plane using the source image's camera data. //because the camera is pointed at (0,0,0), the plane's normal vector's x, y, and z components will be //the negative x, y, and z values for the camera's center point: ImagePlane.a = -x; ImagePlane.b = -y; ImagePlane.c = -z; ImagePlane.d = sqrt((x*x) + (y*y) + (z*z)); } }; SourceImage* SourceImages; Plane* image_planes; float getDistance(float, float, float, float, float, float); int get_width(int); int get_desired_width(); int get_height(int, int); int get_desired_height(int); RGBQUAD** color_table; int* widths; //holds the left-margin for each image, with the last element being that of the source image. int** heights; class interval{ public: float startx; //x, y, and z coordinates of the starting position of this interval. float starty; float startz; float endx; //x,y,and z coordinates of the ending position of this interval. float endy; float endz; float start_length; //the start and end points of the interval, based on the distance (along the ray) from the ray's starting point. float end_length; void CalcLength(Ray theRay){ start_length = sqrt( ((startx-theRay.x)*(startx-theRay.x)) + ((starty-theRay.y)*(starty-theRay.y)) + ((startz-theRay.z)*(startz-theRay.z)) ); end_length = sqrt( ((endx-theRay.x)*(endx-theRay.x)) + ((endy-theRay.y)*(endy-theRay.y)) + ((endz-theRay.z)*(endz-theRay.z)) ); } }; class IntervalList{ public: interval* thelist; int currentlength; int maxlength; int best_image; //stores the best image for use in texturing float best_val; //compare to other images to determine which is best. unsigned long color; unsigned char r; unsigned char g; unsigned char b; IntervalList(){ currentlength = 0; maxlength = 10; thelist = new interval[maxlength]; } void DoubleMaxSize(){ interval* templist; maxlength = (2 * maxlength); templist = new interval[maxlength]; for(int i = 0; i < currentlength; i++){ templist[i] = thelist[i]; } delete thelist; thelist = new interval[maxlength]; for(int i = 0; i < currentlength; i++){ thelist[i] = templist[i]; } delete templist; } void add(interval x){ if(currentlength >= maxlength){ DoubleMaxSize(); } thelist[currentlength] = x; currentlength++; } IntervalList& operator=(IntervalList& y){ best_val = y.best_val; currentlength = y.currentlength; maxlength = y.maxlength; best_image = y.best_image; delete thelist; thelist = new interval[maxlength]; for(int i = 0; i < currentlength; i++){ thelist[i] = y.thelist[i]; } return *this; } //operator[](int i){ // return thelist[i]; // } }; class Image{ public: //created for debugging...so we have some idea of which image is contributing what intervals, //and what the intersection is, for each pixel. //holds (image_width * image_height) matrix of lists of interval lists. //for each element in the matrix, the list of interval lists is : //first element = intervals for first source image //second element = intervals for second source image //etc.... //last element = intersected intervals for all source images IntervalList*** the_matrix; Image(int width, int height, int images){ //pass it image width, image height, and number of images. the_matrix = new IntervalList**[width]; for(int i = 0; i < width; i++){ the_matrix[i] = new IntervalList*[height]; for(int j = 0; j < height; j++){ the_matrix[i][j] = new IntervalList[(images+1)]; } } } }; int sourceimage(0); //a counter to see which source image we are on. interval ColorData; IntervalList AllIntervals; //used for color data. Image* All_Data; bool debug_mode(true); //to keep track of if we are drawing draw_image or draw_debug. int debug_image(0); //debugging mode:this is used to determine which image to draw. int debug_x; //debugging mode:this is used to determine which pixel's ray to draw. int debug_y; //debugging mode:this is used to determine which pixel's ray to draw. Ray debug_ray; //debugging mode:this is used to draw the ray. IntervalList debug_intervals; //debugging mode:this is used to display the intervals on the ray. IntervalList temp_debug; interval GetIntervalRange(IntervalList); void GetDebugInfo(int, int, int); IntervalList GetDebugInfo2(int,int,int); int global_i, global_j; //used to pass info (coordinates) from GetDebugInfo to ReturnIntervals. //global_i and _j are used in getting color values for texturing. /*************************************OPENGL STUFF below********************************************************/ #define PIXEL_CENTER(x) ((long)(x) + 0.5) GLenum rgb, doubleBuffer, windType; GLint windW, windH; GLint boxW, boxH; float color[3]; float angle; int draw_mode; //1 for shaded, 2 for camera's color, 3 for textured int camera_color_counter; //used to pick a color for each camera. static void glInit () { // Clear color glPushAttrib(GL_COLOR_BUFFER_BIT); glColorMask(1, 1, 1, 1); glIndexMask(~0); glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); glPopAttrib(); // Enable Depth testing glEnable(GL_DEPTH_TEST); glClear(GL_DEPTH_BUFFER_BIT); } // Function that gets called when the window is resized. static void Reshape(int width, int height) { // Define window size. windW = (GLint)width; windH = (GLint)height; // Viewport mapping glViewport(0, 0, windW, windH); // Define a perspective projection with a 45 degree field of view // and looking from the the positive z axis at (0,0,10) towards the origin. glMatrixMode(GL_PROJECTION); glLoadIdentity(); //glFrustum(-10.0, 10.0, -10.0, 10.0, 1.0, 20.0); // Alternate method of specifying viewing paramters. gluPerspective (45.0, 1.0, 1.0, 20.0); gluLookAt (0.0, 0.0, 2.5, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); //glOrtho(0, image_width, 0, image_height, -10.0, 10.0); // Switch matrix stack to modelview stack. glMatrixMode(GL_MODELVIEW); } void draw_image(void){ if(draw_mode == 0){ draw_mode = 2; } //gluLookAt(newX, newY, newZ, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0); glOrtho(0, image_width, 0, image_height, -10.0, 10.0); glPointSize(1.0); glBegin (GL_POINTS); float depth; int g(0); if(draw_mode == 1){ //draw mode is: depth-shading. for(int i = 0; i < image_width; i++){ for(int j = 0; j < image_height; j++){ if((i == debug_x)&&(j == debug_y)){ glColor3f(1.0,0.0,0.0); }else if(viewarray[i][j] == 0){ glColor3f (0.0, 0.0, 1.0); }else if(viewarray[i][j] == 1){ float highest; float lowest; highest = ColorData.end_length; lowest = ColorData.start_length; //depth = ((AllIntervals.thelist[g].start_length - lowest) / (highest - lowest)); float temp_color = color_data[i][j]; if(temp_color > ((highest-lowest)/16)){ temp_color = ((highest-lowest)/16); } depth = ((color_data[i][j] - lowest) / ((highest - lowest)/16)); //depth = 1.0; glColor3f (0.0, (1-depth), 0.0); //glColor3f (1.0-(1/(color_data[i][j])), (1.0/(color_data[i][j])), 0.0); }else{ cout<<"error"; glColor3f(1.0, 0.0, 0.0); } g++; glVertex2f(i, j); /* output a source image. if(SourceImages[1].PixelValue(i, j) == 252){ glColor3f (0.0, 0.0, 1.0); }else{ glColor3f (0.0, 1.0, 0.0); } glVertex2f(i, j); */ } } }else if(draw_mode == 2){ //draw mode = per-camera color for(int i = 0; i < image_width; i++){ for(int j = 0; j < image_height; j++){ if(viewarray[i][j] == 0){ glColor3f (0.0, 0.0, 1.0); }else if(viewarray[i][j] == 1){ int best_image; best_image = All_Data->the_matrix[i][j][num_cameras].best_image; if(best_image == -1){ best_image = 9; cout<<"IMAGE NOT GETTING VALUE"; } glColor3f ( SourceImages[best_image].r, SourceImages[best_image].g, SourceImages[best_image].b ); //glColor3f (1.0-(1/(color_data[i][j])), (1.0/(color_data[i][j])), 0.0); }else{ cout<<"error in draw_image"; glColor3f(1.0, 0.0, 0.0); } g++; glVertex2f(i, j); } } }else if(draw_mode == 3){ //draw mode = textured hull. for(int i = 0; i < image_width; i++){ for(int j = 0; j < image_height; j++){ glColor3f(0.0, 1.0, 1.0); if(All_Data->the_matrix[i][j][num_cameras].color < 256){ if(All_Data->the_matrix[i][j][num_cameras].color > 0){ int best_image; best_image = All_Data->the_matrix[i][j][num_cameras].best_image; int i2; int j2; j2 = j; //uncomment below except, it works with this commented out, now uncomment it ///// if(i > image_width/2){ ///// //i2 = (i/2) - widths[num_cameras]; i2 = (i - image_width/2) + widths[best_image]; }else{ i2 = (i + image_width/2) - widths[best_image]; } float draw_r; float draw_g; float draw_b; if(heights[num_cameras][i] == 0){ j2 = j; }else{ if(j2 > (image_height/2)){ //j2 = j2 - (image_height/2); float temp1 = heights[best_image][i2] + 0.0; float temp2 = heights[num_cameras][i] + 0.0; float temp3 = temp1/temp2; float temp4 = j2 + 0.0; float temp5 = temp4 * temp3; j2 = (int)temp5; //j2 = j2 * (heights[best_image][i2])/(heights[num_cameras][i]); //j2 = (((heights[best_image][i2])/(heights[num_cameras][i2]))*j); }else{ float temp1 = heights[best_image][i2] + 0.0; float temp2 = heights[num_cameras][i] + 0.0; float temp3 = temp2/temp1; float temp4 = j2 + 0.0; float temp5 = temp4 * temp3; j2 = (int)temp5; } } if(i2 >= image_width){ cout<<"wtf"; } if(j2 >= image_height){ draw_r = 0.0; draw_g = 0.5; draw_b = 0.5; }else{ draw_r = color_table[best_image][SourceImages[best_image].PixelValue(i2, j2)].rgbRed; draw_g = color_table[best_image][SourceImages[best_image].PixelValue(i2, j2)].rgbGreen; draw_b = color_table[best_image][SourceImages[best_image].PixelValue(i2, j2)].rgbBlue; } //draw_r = All_Data->the_matrix[i][j][num_cameras].r; //draw_g = All_Data->the_matrix[i][j][num_cameras].g; //draw_b = All_Data->the_matrix[i][j][num_cameras].b; //_color = ((All_Data->the_matrix[i][j][num_cameras].color + 0.0)/255.0); glColor3f(draw_r, draw_g, draw_b); } } if(viewarray[i][j] == 0){ glColor3f(0.0, 0.9, 0.9); } g++; glVertex2f(i, j); } } } glEnd (); } void draw_debug(int image_number, int somex, int somey){ //this function outputs a given source image's silhouette, with a given ray projected over it. //it is mainly used for debugging. glOrtho(0, image_width, 0, image_height, -10.0, 10.0); glPointSize(1.0); glBegin (GL_POINTS); //now, draw the ray: int current(0); float totalmoved = 0; float moveX = debug_ray.zdir-debug_ray.z; float moveY = debug_ray.ydir-debug_ray.y; float x = debug_ray.z + (image_width/2); float y = debug_ray.y + (image_height/2); //cout<<"x starts at "< image_width){ //x is already past the image, and moving in the positive direciton--this ray won't hit the desired viewpoint. //quit the loop. somevalue = true; } if(((int)moveX != abs((int)moveX)) && x < 0){ //x is is before the image, and moving in the negative direciton--this ray won't hit the desired viewpoint. //quit the loop. somevalue = true; } //get x onto the image plane. if((x < 0) | (x >= image_width)){ x = x + moveX; y = y + moveY; }else{ somevalue = true; } } //cout<<"but then becomes"<= 0)){ //while x is still on the image plane: glColor3f (1.0, 0.0, 0.0); glPointSize(100.0); glVertex2f((int)x, (int)y); /* if((y < image_height) && (y >= 0)){ //cout<<"x,y is "<= debug_intervals.thelist[current].start_length)&&(totalmoved <= debug_intervals.thelist[current].end_length)){ } }*/ x = x + moveX; y = y + moveY; totalmoved = totalmoved + sqrt((moveX*moveX) + (moveY*moveY)); } //draw the source image: BYTE draw_r; BYTE draw_g; BYTE draw_b; for(int i = 0; i < image_width; i++){ for(int j = 0; j < image_height; j++){ if(SourceImages[image_number].PixelValue(i, j) == 252){ glColor3f (0.0, 0.0, 1.0); }else if(SourceImages[image_number].PixelValue(i, j) < 256){ draw_r = color_table[image_number][SourceImages[image_number].PixelValue(i, j)].rgbRed; draw_g = color_table[image_number][SourceImages[image_number].PixelValue(i, j)].rgbGreen; draw_b = color_table[image_number][SourceImages[image_number].PixelValue(i, j)].rgbBlue; glColor3f (draw_r, draw_g, draw_b); }else{ glColor3f(1.0, 0.0, 0.0); } glVertex2f(i, j); } } glEnd(); } // Draws the scene at any point in time. static void Draw(void) { // Clear color and depth buffers glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity (); glPushMatrix (); // glRotatef (angle, 0.0, 1, 0.0); // Rotate box if(debug_mode == false){ draw_image(); }else{ draw_debug(debug_image,1,1); } glPopMatrix (); glFlush(); // angle += 1.0; //if (angle == 360.0) angle = 0.0; if (doubleBuffer) { glutSwapBuffers(); } } // Called when a keyboard key is pressed static void Key(unsigned char key, int x, int y) { switch (key) { case 27: printf ("exit!\n"); exit(1); default: return; } glutPostRedisplay(); } // Called when special keys are pressed - arrows and page-up/down static void SpecialKey(int key, int x, int y) { int x1; int x2; int y1; int y2; int z1; int z2; int CameraCloseness; switch (key) { case GLUT_KEY_END: //toggle debug mode on and off. if(debug_mode == false){ debug_mode = true; cout<<"---------------------------------------------------"<the_matrix[debug_x][debug_y][debug_image].thelist[0].end_length == -1)){ cout<the_matrix[debug_x][debug_y][debug_image] = debug_intervals; } cout<<"==========At this point, The Intervals for this image are:"<the_matrix[debug_x][debug_y][debug_image].currentlength; i++){ cout<<"Interval from..."; cout<the_matrix[debug_x][debug_y][debug_image].thelist[i].start_length; cout<<" to "; cout<the_matrix[debug_x][debug_y][debug_image].thelist[i].end_length; cout<the_matrix[debug_x][debug_y][num_cameras].currentlength; i++){ cout<<"Interval from..."; cout<the_matrix[debug_x][debug_y][num_cameras].thelist[i].start_length; cout<<" to "; cout<the_matrix[debug_x][debug_y][num_cameras].thelist[i].end_length; cout<the_matrix[debug_x][debug_y][num_cameras].best_image; cout<<"Also...."; x1 = SourceImages[debug_image].x*image_height; y1 = SourceImages[debug_image].y*image_height; z1 = SourceImages[debug_image].z*image_height; x2 = 3*image_height; y2 = ((float)debug_y - (image_height/2)); z2 = ((float)debug_x - (image_width/2)); CameraCloseness = getDistance(x1, y1, z1, x2, y2, z2); break; case GLUT_KEY_PAGE_DOWN: //debugging mode: (source image number to display) --; if(debug_image == 0){ debug_image = (num_cameras-1); }else{ debug_image--; } GetDebugInfo(debug_x, debug_y, debug_image); cout<<"Debug Mode: Now displaying Source Image #"<the_matrix[debug_x][debug_y][debug_image].currentlength; i++){ cout<<"Interval from..."; cout<the_matrix[debug_x][debug_y][debug_image].thelist[i].start_length; cout<<" to "; cout<the_matrix[debug_x][debug_y][debug_image].thelist[i].end_length; cout<the_matrix[debug_x][debug_y][num_cameras].currentlength; i++){ cout<<"Interval from..."; cout<the_matrix[debug_x][debug_y][num_cameras].thelist[i].start_length; cout<<" to "; cout<the_matrix[debug_x][debug_y][num_cameras].thelist[i].end_length; cout<the_matrix[debug_x][debug_y][num_cameras].best_image; cout<<"Also...."; x1 = SourceImages[debug_image].x*image_height; y1 = SourceImages[debug_image].y*image_height; z1 = SourceImages[debug_image].z*image_height; x2 = 3*image_height; y2 = ((float)debug_y - (image_height/2)); z2 = ((float)debug_x - (image_width/2)); CameraCloseness = getDistance(x1, y1, z1, x2, y2, z2); cout<the_matrix[debug_x][debug_y][debug_image].currentlength; i++){ cout<<"Interval from..."; cout<the_matrix[debug_x][debug_y][debug_image].thelist[i].start_length; cout<<" to "; cout<the_matrix[debug_x][debug_y][debug_image].thelist[i].end_length; cout<the_matrix[debug_x][debug_y][num_cameras].currentlength; i++){ cout<<"Interval from..."; cout<the_matrix[debug_x][debug_y][num_cameras].thelist[i].start_length; cout<<" to "; cout<the_matrix[debug_x][debug_y][num_cameras].thelist[i].end_length; cout<the_matrix[debug_x][debug_y][num_cameras].best_image; break; case GLUT_KEY_DOWN: if(debug_y == (image_height-1)){ debug_y = 0; }else{ debug_y++; } GetDebugInfo(debug_x, debug_y, debug_image); cout<<"Debug Mode: Now displaying Ray from:"<the_matrix[debug_x][debug_y][debug_image].currentlength; i++){ cout<<"Interval from..."; cout<the_matrix[debug_x][debug_y][debug_image].thelist[i].start_length; cout<<" to "; cout<the_matrix[debug_x][debug_y][debug_image].thelist[i].end_length; cout<the_matrix[debug_x][debug_y][num_cameras].currentlength; i++){ cout<<"Interval from..."; cout<the_matrix[debug_x][debug_y][num_cameras].thelist[i].start_length; cout<<" to "; cout<the_matrix[debug_x][debug_y][num_cameras].thelist[i].end_length; cout<the_matrix[debug_x][debug_y][num_cameras].best_image; break; case GLUT_KEY_LEFT: if(debug_x == 0){ debug_x = (image_width-1); }else{ debug_x--; } GetDebugInfo(debug_x, debug_y, debug_image); cout<<"Debug Mode: Now displaying Ray from:"<the_matrix[debug_x][debug_y][debug_image].currentlength; i++){ cout<<"Interval from..."; cout<the_matrix[debug_x][debug_y][debug_image].thelist[i].start_length; cout<<" to "; cout<the_matrix[debug_x][debug_y][debug_image].thelist[i].end_length; cout<the_matrix[debug_x][debug_y][num_cameras].currentlength; i++){ cout<<"Interval from..."; cout<the_matrix[debug_x][debug_y][num_cameras].thelist[i].start_length; cout<<" to "; cout<the_matrix[debug_x][debug_y][num_cameras].thelist[i].end_length; cout<the_matrix[debug_x][debug_y][num_cameras].best_image; break; case GLUT_KEY_F1: draw_mode = 1; cout<<"F1 Pressed: Draw Mode switched to: Shaded."<the_matrix[debug_x][debug_y][debug_image].currentlength; i++){ cout<<"Interval from..."; cout<the_matrix[debug_x][debug_y][debug_image].thelist[i].start_length; cout<<" to "; cout<the_matrix[debug_x][debug_y][debug_image].thelist[i].end_length; cout<the_matrix[debug_x][debug_y][num_cameras].currentlength; i++){ cout<<"Interval from..."; cout<the_matrix[debug_x][debug_y][num_cameras].thelist[i].start_length; cout<<" to "; cout<the_matrix[debug_x][debug_y][num_cameras].thelist[i].end_length; cout<the_matrix[debug_x][debug_y][num_cameras].best_image; break; default: return; } glutPostRedisplay(); } // Read input. static GLenum Args(int argc, char **argv) { GLint i, inputfile_count; rgb = GL_TRUE; doubleBuffer = GL_TRUE; inputfile_count = 0; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-ci") == 0) { rgb = GL_FALSE; } else if (strcmp(argv[i], "-rgb") == 0) { rgb = GL_TRUE; } else if (strcmp(argv[i], "-sb") == 0) { doubleBuffer = GL_FALSE; } else if (strcmp(argv[i], "-db") == 0) { doubleBuffer = GL_TRUE; } else { //printf("%s (Bad option).\n", argv[i]); //return GL_FALSE; } } return GL_TRUE; } /***********************************OPENGL STUFF above****************************************************/ //function prototypes: void FillSourceArray(char*); //populates the array of pixel values of the source images unsigned long GetThePixel(int, int, int); //returns the value at one pixel of some image. Ray translate3dray(Ray,Plane); float getDistance(float, float, float, float, float, float); float angleAround(float, float); float angleUp(float, float, float); IntervalList ReturnIntervals(Ray, int, float, float, float); IntervalList CheckOnInterval(float, float, IntervalList); IntervalList intersect_intervals(IntervalList, IntervalList); Ray rotate3dray(Ray, float, float, float); float GetRedValue(); float GetGreenValue(); float GetBlueValue(); int main(int argc, char **argv){ //FCObjImage* source_images; ifstream cameradata("cameras.txt"); //camera input data should be in "cameras.txt" //--the first number in the file is the number of source images. //--the second and third numbers are image width and height. //--next should be a list of X,Y,Z coordinates of each image's camera //--(given that the object is centered at 0,0,0), in order. //--the cameras should point at 0,0,0. //an example cameras.txt file with 4 images of size 200x100 and camera //coordinates (1,0,0), (0,1,0), (-1,0,0), and (0,-1,0) would be: //4 200 100 1 0 0 0 1 0 -1 0 0 0 -1 0 //you also need to call FillSourceArray once in the program for each image that you have. int total_pixels; newX = 50.0; newY = 0.0; newZ = 0.0; cout<<"Loading camera data from file..."<>num_cameras; cameradata>>image_width; cameradata>>image_height; All_Data = new Image(image_width, image_height, num_cameras); total_pixels = (image_width * image_height); SourceImages = new SourceImage[num_cameras]; camera_color_counter = 0; color_table = new RGBQUAD*[num_cameras]; for(int the_x = 0; the_x < image_width; the_x++){ for(int the_y = 0; the_y < image_height; the_y++){ All_Data->the_matrix[the_x][the_y][num_cameras].best_image = -1; All_Data->the_matrix[the_x][the_y][num_cameras].best_val = 9999999; } } for(int i = 0; i < num_cameras; i++){ SourceImages[i].image_number = (i + 1); //set the image number cameradata>>SourceImages[i].x; //get the camera's x value cameradata>>SourceImages[i].z; //get the camera's z value cameradata>>SourceImages[i].y; //get the camera's y value SourceImages[i].r = GetRedValue(); SourceImages[i].g = GetGreenValue(); SourceImages[i].b = GetBlueValue(); camera_color_counter++; cout<<"vals are:"<the_matrix[i][j][k] = temp_intervals; /* cout<<"translated..."< the_intervals.thelist[i].end_length){ cout<<"Returned a bad value from intersect_intervals..."<the_matrix[i][j][num_cameras] = the_intervals; }} */ /////re-doing everything. cout<<"vertical scanline "; for(int debug_x = 0; debug_x < image_width; debug_x++){ cout<the_matrix[debug_x][debug_y][num_cameras].best_val){ // if(debug_image != 0){ // cout<<"WE DID SOMETHING RIGHT"<the_matrix[debug_x][debug_y][num_cameras].best_image = debug_image; All_Data->the_matrix[debug_x][debug_y][num_cameras].best_val = CameraCloseness; } GetDebugInfo(debug_x, debug_y, debug_image); All_Data->the_matrix[debug_x][debug_y][debug_image] = debug_intervals; a_temp_list = intersect_intervals(a_temp_list, debug_intervals); } //if(All_Data->the_matrix[debug_x][debug_y][num_cameras].best_image == 0){ // cout<<"THERE IS A NONZERO ARRAY VALUE..."<the_matrix[debug_x][debug_y][num_cameras].best_image; //} the_best_image = All_Data->the_matrix[debug_x][debug_y][num_cameras].best_image; All_Data->the_matrix[debug_x][debug_y][num_cameras] = a_temp_list; AllIntervals.add(a_temp_list.thelist[0]); if(a_temp_list.thelist[0].end_length != -1){ viewarray[debug_x][debug_y] = 1; color_data[debug_x][debug_y] = a_temp_list.thelist[0].start_length; }else{ viewarray[debug_x][debug_y] = 0; color_data[debug_x][debug_y] = 0; } All_Data->the_matrix[debug_x][debug_y][num_cameras].best_image = the_best_image; } } //now we have the desired image's bit-map stored...get the margin for the desired img: global_debug_test = false; widths[num_cameras] = get_desired_width(); for(int i = 0; i < image_width; i++){ heights[num_cameras][i] = get_desired_height(i); // heights[num_cameras][i] = 10; } //if(global_debug_test == false){ //cout<<"ok, so we never hit image..closing"; //return 0; //} /* uncomment this all later, perhaps. //AllIntervals.add(the_intervals.thelist[0]); AllIntervals.add(the_intervals.thelist[0]); //here i could choose to store the interval for each pixel in desired img. if(the_intervals.thelist[0].end_length == -1){ // if(image_hit == false){ //still doesn't work :( //there are no intervals--the object does not exist at this point. don't draw! viewarray[i][j] = 0; }else{ //cout<<"!231231231231"<the_matrix[i][j][num_cameras].color != 0){ cout<the_matrix[i][j][num_cameras].color<<"..."; } } }*/ /**************************************OPENGL STUFF below***************************************************/ glutInit(&argc, argv); if (Args(argc, argv) == GL_FALSE) { exit(1); } // Initialize window size. windW = image_width - 1; windH = image_height - 1; //windW = 512; // windH = 512; glutInitWindowPosition(0, 0); glutInitWindowSize(windW, windH); // Enable frame buffer for double buffering and z-buffering. windType = (rgb) ? GLUT_RGB : GLUT_INDEX; windType |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE; glutInitDisplayMode(windType | GLUT_DEPTH); if (glutCreateWindow("Visual Hull") == GL_FALSE) { exit(1); } angle = 0.0; // Initialize rotation to 0.0 glInit (); glutReshapeFunc(Reshape); // Set reshape function glutIdleFunc(Draw); // Even if no events, redraw to animate glutKeyboardFunc(Key); // Set keyboard function glutSpecialFunc(SpecialKey); // Set special keyboard function (arrow keys) glutDisplayFunc(Draw); // Set Display function glutMainLoop(); /*************************************OPENGL STUFF above****************************************************/ /* for(int i = 0; i < image_width; i++){ for(int j = 0; j < image_height; j++){ if(viewarray[i][j] == 0){ cout<<"."; }else if(viewarray[i][j] == 1){ cout<<"X"; }else{ cout<<"error"; } } } */ //cout<<"image outputted"; //cout<the_matrix[global_i][global_j][num_cameras].best_image == image_number){ ReturnValue = true; } float moveX = theRay.zdir-theRay.z; float moveY = theRay.ydir-theRay.y; ///comment one. two lines below.. float x = theRay.z + (image_width/2); float y = theRay.y + (image_height/2); IntervalList intervals; interval temp_interval; //intervals = new interval[image_width]; int current_int; bool not_background; //divide both the rise and the run by the run. this makes it so that we can easily increment by 1 in the x direction. if(moveX != 0){ moveY = moveY/abs(moveX); moveX = moveX/abs(moveX); //cout<<"moveX and moveY are "< image_width){ //x is already past the image, and moving in the positive direciton--this ray won't hit the desired viewpoint. //quit the loop. somevalue = true; } if(((int)moveX != abs((int)moveX)) && x < 0){ //x is is before the image, and moving in the negative direciton--this ray won't hit the desired viewpoint. //quit the loop. somevalue = true; } //get x onto the image plane. if((x < 0) | (x >= image_width)){ x = x + moveX; y = y + moveY; }else{ somevalue = true; } } //cout<<"but then becomes"<= 0)){ //while x is still on the image plane: if((y >= image_height) | (y < 0)){ //if the Y value is off the image plane, we can't check that pixel, so just do nothing. }else{ //cout<<"at least we are in the image plane somewhere."<"; if(ReturnValue == true){ All_Data->the_matrix[global_i][global_j][num_cameras].color = SourceImages[image_number].PixelValue((int)x, (int)y); All_Data->the_matrix[global_i][global_j][num_cameras].r = color_table[image_number][SourceImages[image_number].PixelValue((int)x, (int)y)].rgbRed; All_Data->the_matrix[global_i][global_j][num_cameras].g = color_table[image_number][SourceImages[image_number].PixelValue((int)x, (int)y)].rgbGreen; All_Data->the_matrix[global_i][global_j][num_cameras].b = color_table[image_number][SourceImages[image_number].PixelValue((int)x, (int)y)].rgbBlue; ReturnValue = false; } if(not_background == false){ //we aren't currently in an interval. create one. temp_interval.startz = x; temp_interval.starty = y; }else{ //we are already in an interval. just move on to the next pixel. } not_background = true; }else{ //we reach a pixel that is background. if(not_background == true){ //we were in an interval, but now it is over. temp_interval.endz = (x - moveX); temp_interval.endy = (y - moveY); intervals.add(temp_interval); //cout<<"interval from: "< image_height){ //x is already past the image, and moving in the positive direciton--this ray won't hit the desired viewpoint. //quit the loop. somevalue = true; } if(((int)moveY != abs((int)moveY)) && y < 0){ //x is is before the image, and moving in the negative direciton--this ray won't hit the desired viewpoint. //quit the loop. somevalue = true; } //get y onto the image plane. if((y < 0) | (y >= image_width)){ y = y + moveY; }else{ somevalue = true; } } //cout<<"but then becomes"<= 0)){ //while y is still on the image plane: //cout<<"at least we are in the image plane somewhere."<"; if(not_background == false){ //we aren't currently in an interval. create one. temp_interval.startz = x; temp_interval.starty = y; }else{ //we are already in an interval. just move on to the next pixel. } not_background = true; }else{ //we reach a pixel that is background. if(not_background == true){ //we were in an interval, but now it is over. temp_interval.endz = x; temp_interval.endy = (y - moveY); intervals.add(temp_interval); //cout<<"interval from: "< some_temp_ray.xdir){ float tempx, tempy, tempz; tempx = some_temp_ray.x; tempy = some_temp_ray.y; tempz = some_temp_ray.z; some_temp_ray.x = some_temp_ray.xdir; some_temp_ray.y = some_temp_ray.ydir; some_temp_ray.z = some_temp_ray.zdir; some_temp_ray.xdir = tempx; some_temp_ray.ydir = tempy; some_temp_ray.zdir = tempz; } // some_temp_ray = rotate3dray(some_temp_ray, -(image_planes[image_number].a), -(image_planes[image_number].b), -(image_planes[image_number].c)); /* cout<<"Before rotating..."< intervals.thelist[i].end_length){ float tempx, tempy, tempz, templen; tempx = intervals.thelist[i].startx; tempy = intervals.thelist[i].starty; tempz = intervals.thelist[i].startz; templen = intervals.thelist[i].start_length; intervals.thelist[i].startx = intervals.thelist[i].endx; intervals.thelist[i].starty = intervals.thelist[i].endy; intervals.thelist[i].startz = intervals.thelist[i].endz; intervals.thelist[i].start_length = intervals.thelist[i].end_length; intervals.thelist[i].endx = tempx; intervals.thelist[i].endy = tempy; intervals.thelist[i].endz = tempz; intervals.thelist[i].end_length = templen; } } //here, we add a "-1" interval to the end of the interval list. //this will signal to other parts of the program that there are no more intervals in the list. temp_interval.startx = -1; temp_interval.starty = -1; temp_interval.startz = -1; temp_interval.endx = -1; temp_interval.endy = -1; temp_interval.endz = -1; temp_interval.start_length = -1; temp_interval.end_length = -1; intervals.add(temp_interval); return intervals; } IntervalList intersect_intervals(IntervalList previouslist, IntervalList toadd){ for(int i = 0; i < previouslist.currentlength; i++){ if(previouslist.thelist[i].start_length > previouslist.thelist[i].end_length){ cout<<"passed a bad previouslist value to intersect"; cout< toadd.thelist[i].end_length){ cout<<"passed a bad toadd value to intersect"; cout< intervals.thelist[i].end_length){ cout<<"**************&&&&&&&&&&&&&"; cout<<"**************&&&&&&&&&&&&&"; cout<<"**************&&&&&&&&&&&&&"; cout<<"intersect is returning backwards stuff"< end){ float ftemp = start; start = end; end = ftemp; } IntervalList intervals; interval temp_interval; //intervals = new interval[image_width]; int i = 0; int current = 0; for(int g = 0; g < list.currentlength; g++){ if(list.thelist[g].start_length > list.thelist[g].end_length){ float gtemp = list.thelist[g].start_length; list.thelist[g].start_length = list.thelist[g].end_length; list.thelist[g].end_length = gtemp; } } while(list.thelist[i].endx != -1){ if((list.thelist[i].start_length >= start) && (list.thelist[i].start_length <= end)){ //the case where an interval starts within the bounds. if(list.thelist[i].end_length <= end){ //the end of the interval is within the bounds. intervals.add(list.thelist[i]); //intervals[current].start_length = list[i].start_length; //intervals[current].end_length = list[i].end_length; current++; }else{ //the end of the interval is outside of the bounds. temp_interval.start_length = list.thelist[i].start_length; temp_interval.end_length = end; intervals.add(temp_interval); current++; } }else if(list.thelist[i].start_length <= start){ //the case where an interval starts before the bounds if((list.thelist[i].end_length >= start) && (list.thelist[i].end_length <= end)){ //the interval ends within the bounds temp_interval.start_length = start; temp_interval.end_length = list.thelist[i].end_length; intervals.add(temp_interval); current++; }else if(list.thelist[i].end_length >= end){ //the interval ends past the bounds temp_interval.start_length = start; temp_interval.end_length = end; intervals.add(temp_interval); current++; }else{ //the interval ends before the bounds. do nothing. } }else{ //the interval starts after the bounds. do nothing. } i++; } temp_interval.endx = -1; temp_interval.endy = -1; temp_interval.endz = -1; temp_interval.starty = -1; temp_interval.startx = -1; temp_interval.startz = -1; temp_interval.end_length = -1; temp_interval.start_length = -1; intervals.add(temp_interval); return intervals; } /* Ray rotate3dray(Ray theRay, float x, float y, float z){ //given a 3d ray and a point to rotate to, this function rotates the ray. double RadiansToRotateAround = angleAround(x,y); double RadiansToRotateUp = angleUp(x, y, z); double RayHyp = getDistance(0,0,0,theRay.x, theRay.y, theRay.z); double XYRayHyp = getDistance(0,0,0,theRay.x, theRay.y,0); double RayHypD = getDistance(0,0,0,theRay.xdir, theRay.ydir, theRay.zdir); double XYRayHypD = getDistance(0,0,0,theRay.xdir, theRay.ydir,0); //rotate ray so that it is on the X axis double xtemp = 1.0 * XYRayHyp; double ytemp = 0.0 * XYRayHyp; double ztemp = theRay.z; double xdtemp = 1.0 * XYRayHypD; double ydtemp = 0.0 * XYRayHypD; double zdtemp = theRay.zdir; //then rotate it up or down the right amount of degrees ztemp = sin(angleUp(theRay.x, theRay.y, theRay.z)+RadiansToRotateUp)*RayHyp; xtemp = cos(angleUp(theRay.x, theRay.y, theRay.z)+RadiansToRotateUp)*RayHyp; zdtemp = sin(angleUp(theRay.xdir, theRay.ydir, theRay.zdir)+RadiansToRotateUp)*RayHypD; xdtemp = cos(angleUp(theRay.xdir, theRay.ydir, theRay.zdir)+RadiansToRotateUp)*RayHypD; //now rotate it back to original angle around position, plus the amount of degrees to rotate. XYRayHyp = getDistance(0,0,0,xtemp, ytemp,0); XYRayHypD = getDistance(0,0,0,xdtemp, ydtemp,0); xtemp = cos(angleAround(theRay.x, theRay.y) + RadiansToRotateAround) * XYRayHyp; ytemp = sin(angleAround(theRay.x, theRay.y) + RadiansToRotateAround) * XYRayHyp; xdtemp = cos(angleAround(theRay.xdir, theRay.ydir) + RadiansToRotateAround) * XYRayHypD; ydtemp = sin(angleAround(theRay.xdir, theRay.ydir) + RadiansToRotateAround) * XYRayHypD; theRay.x = xtemp; theRay.y = ytemp; theRay.z = ztemp; theRay.xdir = xdtemp; theRay.ydir = ydtemp; theRay.zdir = zdtemp; return theRay; }*/ Ray rotate3dray(Ray theRay, float x, float y, float z){ //given a 3d ray and a point to rotate to, this function rotates the ray. float RadiansToRotateAround = angleAround(x,z); float RadiansToRotateUp = angleUp(x,y,z); float RayHyp = getDistance(0,0,0,theRay.x, theRay.y, theRay.z); float XZRayHyp = getDistance(0,0,0,theRay.x, theRay.z,0); float RayHypD = getDistance(0,0,0,theRay.xdir, theRay.ydir, theRay.zdir); float XZRayHypD = getDistance(0,0,0,theRay.xdir, theRay.zdir,0); //now, the ray is made up of two points. a starting point and a point elsewhere indicating direction. //take each of these points and put them on the +x axis at 1.0. float xtemp = 1.0; float ztemp = 0.0; float ytemp = 0.0; float xdtemp = 1.0; float zdtemp = 0.0; float ydtemp = 0.0; //now rotate up or down however many degrees we need to rotate //also, make the point as far out from the origin as it was before, by multiplying by the ray's old hypotenuse. ytemp = sin(angleUp(theRay.x, theRay.y, theRay.z)+RadiansToRotateUp)*RayHyp; xtemp = cos(angleUp(theRay.x, theRay.y, theRay.z)+RadiansToRotateUp)*RayHyp; ydtemp = sin(angleUp(theRay.xdir, theRay.ydir, theRay.zdir)+RadiansToRotateUp)*RayHypD; xdtemp = cos(angleUp(theRay.xdir, theRay.ydir, theRay.zdir)+RadiansToRotateUp)*RayHypD; //now that each point is rotated up, //rotate them back to original angle-around position, plus the amount of degrees to rotate. XZRayHyp = xtemp; //returns value of X at this point. XZRayHypD = xdtemp;//returns value of Xd at this point. //so, RayHyp gets the X-distance from the center. this is the radius of the circle to rotate around. //the Y value will be unchanged, but the X and Z values will be on this circle. xtemp = cos(angleAround(theRay.x, theRay.z) + RadiansToRotateAround) * XZRayHyp; ztemp = sin(angleAround(theRay.x, theRay.z) + RadiansToRotateAround) * XZRayHyp; xdtemp = cos(angleAround(theRay.xdir, theRay.zdir) + RadiansToRotateAround) * XZRayHypD; zdtemp = sin(angleAround(theRay.xdir, theRay.zdir) + RadiansToRotateAround) * XZRayHypD; theRay.x = xtemp; theRay.y = ytemp; theRay.z = ztemp; theRay.xdir = xdtemp; theRay.ydir = ydtemp; theRay.zdir = zdtemp; return theRay; } interval GetIntervalRange(IntervalList list){ //given a list of intervals, this function returns a single interval, where the start_length value is the lowest //first interval starting point in the list, and the end_length value is the highest first interval starting point in the list. interval x; float highest = 0; float lowest = 999999; for(int i = 0; i < list.currentlength; i++){ if(list.thelist[i].endx != -1){ if(list.thelist[i].start_length < lowest){ lowest = list.thelist[i].start_length; } if(list.thelist[i].start_length > highest){ highest = list.thelist[i].start_length; } } } x.start_length = lowest; x.end_length = highest; cout<<"lowest is "< image_width){ closest_i = 1; cout<<"error in get_width, probably because the source image is empty"< image_width){ closest_i = 1; cout<<"error in get_width, probably because the source image is empty"<= image_width){ cout<<"error in G D H"<