Jump to content

openGL paint program - building interactive models


Recommended Posts

Hi, I'm trying to save, delete, and manipulate objects for this paint program. I created a structure that holds information for objects:

typedef struct object

{

int type;

int x, y;

float color[3];

}object;

created a table of 100 objects:

object table[100];

and initialize the index to the last object of the list:

int lastobject;

here is the code:

##############################################

// define macros corresponding to user choices

#define NULL 0

#define LINE 1

#define RECTANGLE 2

#define TRIANGLE 3

#define POINT 4

#define TEXT 5

#include <GL/glut.h>

// function prototypes

void mouse (int, int, int, int);

void key (unsigned char, int, int);

void display ();

void drawSquare(int, int);

void myReshape (GLsizei, GLsizei);

void myinit();

void screen_box (int, int, int);

void right_menu(int);

void middle_menu(int);

void color_menu(int);

void pixel_menu(int);

void fill_menu(int);

int pick(int, int);

// globals

GLsizei wh = 500, ww = 500; // initial window size

GLfloat size = 3.0; // half side length of square

int draw_mode = NULL; // drawing mode

int rx, ry; // raster position

GLfloat r = 1.0, g = 1.0, b = 1.0; // drawing color (initially white)

int fill = 0; // fill flag (initially no fill)

typedef struct object

{

int type;

int x, y;

float color[3];

}object;

object table[100];

int lastobject, i;

//

// Function: drawSquare ()

//

// This function draws a square centered about the point (x,y).

// The length of a side is twice the global variable size.

//

void drawSquare (int x, int y)

{

// the position (x,y) returned from a mouse event

// is in the window's coordinate system, which has its

// origin at the top left of the window so flip the

// y value returned

y = wh - y;

// Select a random color and draw a square centered around

// the mouse position

glColor3ub ( (char) rand()%256, (char) rand()%256, (char) rand%256);

glBegin(GL_POLYGON);

glVertex2f (x + size, y + size);

glVertex2f (x - size, y + size);

glVertex2f (x - size, y - size);

glVertex2f (x + size, y - size);

glEnd();

}

//

// Function: myReshape()

//

// This function is the callback for a window which has been

// resized or moved

//

void myReshape (GLsizei w, GLsizei h)

{

// adjust clipping box

glMatrixMode (GL_PROJECTION);

glLoadIdentity ();

gluOrtho2D (0.0, (GLdouble)w, 0.0, (GLdouble)h);

glMatrixMode (GL_MODELVIEW);

glLoadIdentity();

// adjust viewport and clear

glViewport(0, 0, w, h);

glClearColor (0.8, 0.8, 0.8, 1.0);

glClear (GL_COLOR_BUFFER_BIT);

display ();

glFlush();

// set global size for use by drawing routine

ww = w;

wh = h;

}

//

// Function: myinit()

//

// This function initializes OpenGl.

//

void myinit()

{

glViewport (0 , 0, ww, wh);

// Pick 2D clipping window to match size of X window

// This choice avoids having to scale object coordinates

// each time window is resized

glMatrixMode (GL_PROJECTION);

glLoadIdentity();

gluOrtho2D (0.0, (GLdouble) ww, 0.0, (GLdouble) wh);

// set clear color to black and clear window

glClearColor (0.8, 0.8, 0.8, 1.0);

glClear (GL_COLOR_BUFFER_BIT);

glFlush();

}

//

// Function: handle_line()

//

// This function takes care of user input after

// a straight line has been selected.

//

void handle_line (int x, int y)

{

static int xp, yp;

static int count = 0;

// is the user entering the first or

// second point on the line

if (count == 0)

{

// the user just entered the first point

count++;

xp = x;

yp = y;

}

else

{

// the user just entered the second point

// so draw the line

glBegin (GL_LINES);

glVertex2i (x, wh - y);

glVertex2i (xp, wh-yp);

glEnd();

draw_mode = NULL;

count = 0;

}

}

//

// Function: handle_rectangle()

//

// This function takes care of user input after

// a rectangle has been selected.

//

void handle_rectangle (int x, int y)

{

static int xp, yp; // keep track of the first point selected

static int count = 0;

// if this is the first corner point, count

// it and save it

if (count == 0)

{

count++;

xp = x;

yp = y;

}

// if this is the second point, draw the rectangle

// based on the fill attribute

else

{ // if the second point

if (fill)

glBegin (GL_POLYGON);

else

glBegin (GL_LINE_LOOP);

glVertex2i (x, wh - y);

glVertex2i (x, wh - yp);

glVertex2i (xp, wh - yp);

glVertex2i (xp, wh - y);

glEnd();

//set the drawing mode to nothing

draw_mode = NULL;

count = 0;

}

}

//

// Function: handle_triangle()

//

// This function takes care of user input after

// a triangle has been selected.

//

void handle_triangle(int x,int y)

{

static int xp[2], yp[2]; // save the first two points of the triangle

static int count; // count how many points have been selected

switch (count)

{

//if this is the first point, count it and save it

case (0):

count++;

xp[0] = x;

yp[0] = y;

break;

//if this is the second point, count it and save it

case (1):

count++;

xp[1] = x;

yp[1] = y;

break;

//if this is the third point, draw the triangle

case (2):

if (fill)

glBegin (GL_POLYGON);

else

glBegin (GL_LINE_LOOP);

glVertex2i (xp[0], wh-yp[0]);

glVertex2i (xp[1], wh-yp[1]);

glVertex2i (x, wh-y);

glEnd();

draw_mode = NULL;

count = 0;

}

}

//

// Function: mouse ()

//

// This function is the callback function for the mouse.

//

void mouse (int btn, int state, int x, int y)

{

int selection; // did the user press a button

// if the left mouse button was depressed, handle

// the event

if (btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN)

{

// determine which button was selected if any

selection = pick (x, y);

// set the drawing color

glColor3f (r, g, B);

// if a button was selected, keep track of which

// button in draw_mode

if (selection != 0)

draw_mode = selection;

// a button was already selected, now handle user

// input based on the previous selection

else switch (draw_mode)

{

// the line button was selected

case (LINE): handle_line (x, y);

break;

// the rectangle button was selected

case (RECTANGLE): handle_rectangle (x, y);

break;

// the triangle button was selected

case (TRIANGLE): handle_triangle (x, y);

break;

// the point button was selected

case (POINT): drawSquare (x,y);

break;

// the text button was selected

case (TEXT):

{

//record the mouse position for the

//next raster position

rx = x;

ry = wh - y;

}

}

glFlush();

}

}

//

// Function: pick()

//

// The mouse button was clicked. This function determines

// where the mouse cursor was positioned when the click occurred.

//

int pick (int x, int y)

{

y = wh - y;

//Was y value of the point in the button region?

if (y < wh - ww/10) return NULL;

//Was the x value of the point in the line button?

else if (x < ww/10) return LINE;

//Was the x value of the point in the rectangle button?

else if (x < ww/5) return RECTANGLE;

//Was the x value of the point in the triangle button?

else if (x < 3 * ww/10) return TRIANGLE;

//Was the x value in the Point button?

else if (x < 2 * ww/5) return POINT;

//Was the x value in the Text button?

else if (x < ww/2) return TEXT;

//The point wasn't in the button region.

else return NULL;

}

//

// Function: screen_box()

//

// This function is used to draw the buttons on the screen.

//

void screen_box (int x, int y, int s)

{

glBegin (GL_QUADS);

glVertex2i (x, y);

glVertex2i(x + s, y);

glVertex2i(x + s, y + s);

glVertex2i (x, y + s);

glEnd();

}

//

// Function: middle_menu()

//

// This funcion handles the menu associated with the middle mouse button.

// The single input argument (id) is the number of the menu item that

// has been selected. If the first item is selected, the program is

// exited. If the second item is selected, the display is cleared.

//

void middle_menu (int id)

{

if (id == 1) exit (0);

else display ();

}

//

// Function: right_menu ()

//

// This function is required because a menu is associated with the right

// mouse button. Three of the menu items are submenus. This function

// handles the other two menu items.

//

void right_menu(int id)

{

if (id==1) //menu item "quit"

exit(0);

else

glutPostRedisplay(); //menu item "clear"

}

//

// Function: color_menu()

//

// This function handles the color menu which is a submenu of the menu

// associated with the right mouse button.

//

void color_menu (int id)

{

if (id == 1) { r = 1.0; g = 0.0; b = 0.0; } //red

else if (id == 2) {r = 0.0; g = 1.0; b = 0.0; } //green

else if (id == 3) {r = 0.0; g = 0.0; b = 1.0; } //blue

else if (id == 4) {r = 0.0; g = 1.0; b = 1.0; } //cyan

else if (id == 5) {r = 1.0; g = 0.0; b = 1.0; } //magenta

else if (id == 6) {r = 1.0; g = 1.0; b = 0.0; } //yellow

else if (id == 7) {r = 1.0; g = 1.0; b = 1.0; } //white

else if (id == 8) {r = 0.0; g = 0.0; b = 0.0; } //black

}

//

// Function: pixel_menu()

//

// This function increases or decreases the point sized based on

// the submenu item chosen. This submenu is associated with the

// right mouse button.

//

void pixel_menu (int id)

{

if (id == 1) //increase the point size

size = 2 * size;

else if (size > 1) //decrease the point size if possible

size = size/2;

}

//

// Function: fill_menu()

//

// This function handles the fill menu selection. This menu

// selection determines whether the square is filled or not.

void fill_menu (int id)

{

if (id == 1)

fill = 1;

else

fill = 0;

}

//

// Function: key()

//

// This function is activated when the user presses a key

// on the keyboard. It will only perform an action if

// the user has selected the text button.

void key (unsigned char k, int xx, int yy)

{

//check to see if the user has selected the text button

if (draw_mode != TEXT) return;

//Set the color to black

glColor3f (0.0, 0.0, 0.0);

//Set the current raster position to

//the last mouse click

glRasterPos2i (rx, ry);

//set the font and render the character k

glutBitmapCharacter (GLUT_BITMAP_9_BY_15,k);

//update the raster position by the appropriate

//width of the character k

rx += glutBitmapWidth(GLUT_BITMAP_9_BY_15,k);

glFlush();

}

//

// Function: display()

//

// This function is the display callback. It clears the screen

// and draws the buttons on the screen.

void display()

{

int shift = 0; //used to keep track of character placement

//clear the background to grey

glClearColor (0.8, 0.8, 0.8, 1.0);

glClear (GL_COLOR_BUFFER_BIT);

//set the color to white and draw the line button

glColor3f (1.0, 1.0, 1.0);

screen_box (0, wh-ww/10, ww/10);

//set the color to red and draw the box button

glColor3f(1.0, 0.0, 0.0);

screen_box (ww/10, wh-ww/10, ww/10);

//set the color to green and draw the triangle

//button.

glColor3f(0.0, 1.0, 0.0);

screen_box (ww/5, wh-ww/10, ww/10);

//set the color to blue and draw the point button

glColor3f(0.0, 0.0, 1.0);

screen_box (3*ww/10, wh-ww/10, ww/10);

//set the color to yellow and draw the text button

glColor3f(1.0, 1.0, 0.0);

screen_box (2*ww/5, wh-ww/10, ww/10);

//set the color to black and draw a line on the

//line button

glColor3f(0.0, 0.0, 0.0);

glBegin (GL_LINES);

glVertex2i (wh/40, wh-ww/20);

glVertex2i (wh/40 + ww/20, wh - ww/20);

glEnd();

//set the color to white and draw a square in

//the rectangle button

glColor3f(1.0, 1.0, 1.0);

screen_box(ww/10+ww/40, wh-ww/10+ww/40, ww/20);

//draw a triangle on the triangle button

glBegin (GL_TRIANGLES);

glVertex2i (ww/5 + ww/40, wh - ww/10 + ww/40);

glVertex2i (ww/5 + ww/20, wh-ww/40);

glVertex2i (ww/5 + 3 * ww/40, wh - ww/10 + ww/40);

glEnd();

//place a point on the point button

glPointSize(3.0);

glBegin (GL_POINTS);

glVertex2i (3 * ww/10 + ww/20, wh - ww/20);

glEnd();

//place "abc" on the text button

glRasterPos2i(2 * ww/5, wh - ww/20);

glutBitmapCharacter(GLUT_BITMAP_9_BY_15, 'A');

shift = glutBitmapWidth(GLUT_BITMAP_9_BY_15, 'A');

glRasterPos2i(2 * ww/5 + shift, wh - ww/20);

glutBitmapCharacter(GLUT_BITMAP_9_BY_15, 'B');

shift += glutBitmapWidth(GLUT_BITMAP_9_BY_15, 'B');

glRasterPos2i (2 * ww/5 + shift, wh - ww/20);

glutBitmapCharacter(GLUT_BITMAP_9_BY_15, 'C');

glFlush();

for(i = 0; i < lastobject; i++)

{

switch(table.type)

{

case 0: break;

case 2:

{

glColor3fv(table.color);

handle_rectangle(table.x, table.y);

break;

}

}

}

glFlush();

}

int main (int argc, char** argv)

{

int c_menu, p_menu, f_menu; //menu ids for the color menu, the

//pixel size menu, and the fill menu

//initialize glut

glutInit (&argc, argv);

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);

glutCreateWindow("Paint program");

//set the display callback

glutDisplayFunc(display);

//create a submenu that uses the function color_menu()

//as a callback

c_menu = glutCreateMenu(color_menu);

//specify menu items for this menu and associate the text

//in the menu item with a certain menu id.

glutAddMenuEntry ("Red", 1);

glutAddMenuEntry ("Green", 2);

glutAddMenuEntry ("Blue", 3);

glutAddMenuEntry ("Cyan", 4);

glutAddMenuEntry ("Magenta", 5);

glutAddMenuEntry ("Yellow", 6);

glutAddMenuEntry ("White", 7);

glutAddMenuEntry ("Black", 8);

//create a submenu that uses the function pixel_menu() as

//a callback.

p_menu = glutCreateMenu (pixel_menu);

//specify menu items for this menu and associate the

//text in the menu with a certain menu id.

glutAddMenuEntry ("increase pixel size", 1);

glutAddMenuEntry ("decrease pixel size", 2);

//create a submenu that uses the function fill_menu()

//as a callback.

f_menu = glutCreateMenu(fill_menu);

//specify menu items for this menu and associate the

//text in the menu with a certain menu id.

glutAddMenuEntry ("fill on", 1);

glutAddMenuEntry ("fill off", 2);

//create a top level menu that uses the function right_menu()

//as a callback.

glutCreateMenu(right_menu);

//add menu items to the top level menu

glutAddMenuEntry ("quit", 1);

glutAddMenuEntry ("clear", 2);

//add submenus to the top level menu

glutAddSubMenu ("Colors", c_menu);

glutAddSubMenu ("Pixel Size", p_menu);

glutAddSubMenu ("Fill", f_menu);

//attach the menu to the right mouse button

glutAttachMenu (GLUT_RIGHT_BUTTON);

//initialize opengl

myinit();

//set up the reshape, keyboard and mouse callbacks

glutReshapeFunc (myReshape);

glutKeyboardFunc (key);

glutMouseFunc (mouse);

//start the event loop

glutMainLoop ();

}

##########################################

let's say I specify the type, RECTANGLE (that is assign by #define RECTANGLE = 2).

I want to draw the RECTANGLE and store the information to the table so I can manipulate or delete the object. The code looks something like this:

table[lastobject].type = RECTANGLE;

table[lastobject].x = y;

table[lastobject].y = y;

table[lastobject].color[0] = r;

table[lastobject].color[1] = g;

table[lastobject].color[2] = b;

lastobject++;

I also want to display all of the objects using this code:

for(i = 0; i < lastobject; i++)

{

switch(table.type)

{

case 0: break;

case 2:

{

glColor3fv(table.color);

handle_rectangle(table.x, table.y);

break;

}

}

}

my question for today is where can I place these blocks of code on what function as you see above?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. Privacy Policy