Stretching a Line

Hi.

  1. I’m creating a program where the user creates a line.

  2. The user clicks on the first point and then drags the mouse to the next point.

  3. There is a line from the first point to wherever the mouse moves to, sort of like dragging a piece of string.

  4. When the user clicks on the second point the line is created and it can’t be moved around.

  5. I’m having trouble getting a line from the first point to the end of the mouse.

  6. I used the glutMotionFunc but that didn’t do anything.

  7. Can anybody help me out?

Thanks

It is called a rubber band effect, a search on that should bring something up.

Also here is a piece of code showing how to the effect in glut.
I have another version of this code that does just a line, but don’t have it handy.

// GlutDrawWindow.c
// By Eric Stringer 2002
// Simple examples of OpenGL and Glut usage.
// Keyboard input
// ‘v’ = view ortho/perspective
// ‘l’ = lighting on/off

#include <windows.h> // This header file will be needed for some windows compilers
//#include <GL/gl.h> // gl.h and glu.h also maybe needed for some compilers
//#include <GL/glu.h>
#include <GL/glut.h> // glut (gl utility toolkit) basic windows functions, keyboard, mouse.
#include <stdio.h> // standard (I/O library)
#include <stdlib.h> // standard library (set of standard C functions
#include <math.h> // Math library (Higher math functions )

int window_1, window_2;

// lighting
GLfloat LightAmbient= { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat LightDiffuse= { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat LightPosition= { 5.0f, 25.0f, 15.0f, 1.0f };
GLfloat mat_specular = { 1.0, 1.0, 1.0, 1.0 };

typedef struct POINT_3D
{
GLfloat x, y ,z;
}v3D;

// Define temp line variables
int line_start;

POINT_3D line_temp[2];

// Storage for our lines
POINT_3D line_array[100];
static int line_index = 0;

static int view_state = 0, light_state = 0;

static float Mouse_x, Mouse_y, Win_x, Win_y;

int spin;

// I use this to put text on the screen
void Sprint( int x, int y, char *st)
{
int l,i;

l=strlen( st ); // see how many characters are in text string.
glRasterPos2i( x, y); // location to start printing text
for( i=0; i < l; i++) // loop until i is greater then l
{
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, st[i]); // Print a character on the screen
}

}

// This creates the spinning of the cube.
static void TimeEvent(int te)
{

spin++;  // increase cube rotation by 1

if (spin > 360) spin = 0; // if over 360 degress, start back at zero.
glutSetWindow(window_1);
glutPostRedisplay(); // Update screen with new rotation data
glutSetWindow(window_2);
glutPostRedisplay();
glutTimerFunc( 100, TimeEvent, 1); // Reset our timmer.
}

// Setup our Opengl world, called once at startup.
void init(void)
{
glClearColor (0.0, 0.0, 0.0, 0.0); // When screen cleared, use black.
glShadeModel (GL_SMOOTH); // How the object color will be rendered smooth or flat
glEnable(GL_DEPTH_TEST); // Check depth when rendering
// Lighting is added to scene
glLightfv(GL_LIGHT1 ,GL_AMBIENT, LightAmbient);
glLightfv(GL_LIGHT1 ,GL_DIFFUSE, LightDiffuse);
glLightfv(GL_LIGHT1 ,GL_POSITION, LightPosition);
glEnable(GL_LIGHTING); // Turn on lighting
glEnable(GL_LIGHT1); // Turn on light 1
}

// Draw our world
void display_1(void)
{
int i;

glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Clear the screen

glMatrixMode (GL_PROJECTION); // Tell opengl that we are doing project matrix work
glLoadIdentity(); // Clear the matrix
glOrtho(-8.0, 8.0, -8.0, 8.0, 0.0, 30.0); // Setup an Ortho view
glMatrixMode(GL_MODELVIEW); // Tell opengl that we are doing model matrix work. (drawing)
glLoadIdentity(); // Clear the model matrix
// print view state on screen
glColor3f( 1.0, 1.0, 1.0);
Sprint(-2, 4, “Ortho view”);

// Lighting on/off
if (light_state == 1)
{
glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
}else
{
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
}

if (line_start == 1)
{
glColor3f( 1.0, 0.0, 0.0); // Line Color
//glBegin(GL_LINES);
//glVertex2f(line_temp[0].x, line_temp[0].y);
//glVertex2f(line_temp[1].x, line_temp[1].y);
//glEnd();
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glLineWidth( 5.0 );
glBegin(GL_QUADS);
glVertex2f(line_temp[0].x, line_temp[0].y);
glVertex2f(line_temp[1].x, line_temp[0].y);
glVertex2f(line_temp[1].x, line_temp[1].y);
glVertex2f(line_temp[0].x, line_temp[1].y);
glEnd();

glBegin(GL_TRIANGLES);
glVertex2f(line_temp[0].x + fabs(line_temp[0].x - line_temp[1].x)* 0.5, line_temp[0].y);
//glVertex2f(line_temp[1].x, line_temp[0].y);
glVertex2f(line_temp[1].x, line_temp[1].y);
glVertex2f(line_temp[0].x, line_temp[1].y);
glEnd();

glEnd();
}

// Process lines drawn
for(i = 0; i < line_index; i+=2)
{
glColor3f(1.0, 1.0, 1.0);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glLineWidth( 1.0 );
//glBegin(GL_LINES);
//glVertex2f(line_array[i].x, line_array[i].y);
//glVertex2f(line_array[i+1].x, line_array[i+1].y);
//glEnd();
//glBegin(GL_QUADS);
//glVertex2f(line_array[i].x, line_array[i].y);
//glVertex2f(line_array[i+1].x, line_array[i].y);
//glVertex2f(line_array[i+1].x, line_array[i+1].y);
//glVertex2f(line_array[i].x, line_array[i+1].y);
//glEnd();

glBegin(GL_TRIANGLES);
glVertex2f(line_array[i].x + fabs(line_array[i].x - line_array[i+1].x) * 0.5, line_array[i].y);
//glVertex2f(line_array[1].x, array_array[0].y);
glVertex2f(line_array[i+1].x, line_array[i+1].y);
glVertex2f(line_array[i].x, line_array[i+1].y);
glEnd();

}

glutSwapBuffers();
}

// This is called when the window has been resized.
void reshape_1 (int w, int h)
{
Win_x = w;
Win_y = h;
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
}

// Read the keyboard
void keyboard (unsigned char key, int x, int y)
{
switch (key)
{

case 'v':
case 'V':
    view_state = abs(view_state -1);
    break;
case 'l':
case 'L':
    light_state = abs(light_state -1);
    break;
case 27:
     exit(0); // exit program when [ESC] key presseed
     break;
  default:
     break;

}

}

void mouse(int button, int state, int x, int y)
{

Mouse_x = -8 + 16 * (x/Win_x);
Mouse_y = 8 - 16 * (y/Win_y);

if ((button == GLUT_LEFT_BUTTON) && (state == GLUT_DOWN))
{
line_start = 1;
line_temp[0].x = Mouse_x;
line_temp[0].y = Mouse_y;
}

if ((button == GLUT_LEFT_BUTTON) && (state == GLUT_UP))
{
line_start = 0;
line_temp[1].x = Mouse_x;
line_temp[1].y = Mouse_y;
line_array[line_index] = line_temp[0];
line_array[line_index+1] = line_temp[1];
line_index += 2;
}

}

void mouse_motion( int x, int y)
{

Mouse_x = -8 + 16 * (x/Win_x);
Mouse_y = 8 - 16 * (y/Win_y);
if (line_start == 1)
{
line_temp[1].x = Mouse_x;
line_temp[1].y = Mouse_y;
}
}

// Main program
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutTimerFunc( 10, TimeEvent, 1);
glutInitWindowSize (500, 500);
glutInitWindowPosition (10, 10);
window_1 = glutCreateWindow (argv[0]);
glutSetWindowTitle(“GlutDraw”);
glutDisplayFunc(display_1);
glutReshapeFunc(reshape_1);
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
glutMotionFunc(mouse_motion);
init ();

glutMainLoop();
return 0;
}

[This message has been edited by nexusone (edited 06-15-2003).]

Hi nexusone

  1. Thanks for the reply. I’ve got one question for you.

  2. I had inserted the rubberbanding code in the function I pass to glutPassiveMotionFunc(). Does that code belong in the Display() function?

Thanks.
Raja

I am not sure what you mean in your question #2.

But look at how my code works:

I use state variables to know when to draw the rubber band effect.

The state variable is set in the mouse routines, I use both mouse routines, mousemotion is only used to durring the rubber band effect to get current mouse position.
The other mouse routine, I get the the start and end of line.

Now in the display function is all drawing code with variables passed from the mouse functions.

Originally posted by ComputerUser43:
[b]Hi nexusone

  1. Thanks for the reply. I’ve got one question for you.
  1. I had inserted the rubberbanding code in the function I pass to glutPassiveMotionFunc(). Does that code belong in the Display() function?

Thanks.
Raja[/b]

Hi nexusone.

Even if you were unsure of my question you still answered it.

The rubberbanding works great now.

Thanks.
Raja