OpenGL / GLUT help

Hi. I'm creating a program in which a triangle is drawn on screen using OpenGL, and the area of the triangle is drawn on screen along with the height and base.

However, I want to be able to drag each vertex of the triangle to resize it, but I can't figure out any way to do it. I'm guessing I'll need to use SDL for the mouse events, but I'm not sure how to implement SDL in an OpenGL program.

If anyone could help, it would be much appreciated. Here is the code for drawing my triangle and maths:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include "Vec2.h"
#include "Triangles.h"
#include "StringFuncts.h"

#include <SDL.h>
#include <iostream>
#include <random>
#include <GL/glut.h>

void PrintText(float x, float y, std::string& text)
{
	glRasterPos2f(x, y);
	for (unsigned int k = 0; k < text.size(); k++)
	{
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, text[k]);
	}
}

float CalcArea(Vec2f& a, Vec2f& b, Vec2f& c)
{
	if (a.x < b.x)
		base = b.x - a.x;
	else if (a.x > b.x)
		base = a.x - b.x;

	if (a.y < c.y)
		height = c.y - a.y;
	else if (a.y > c.y)
		height = a.y - c.y;

	area = height * 0.5 * base;
	return area;
}

float BaseText(Vec2f& a, Vec2f& b)
{
	if (a.y < b.y) return a.y - 5;
	else if (a.y > b.y) return a.y + 5;
	else return 0;
}



void Draw()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0, 0, 100.0, 0, 0, 0, 0, 1.0, 0);



	CalcArea(PointA, PointB, PointC);

	glBegin(GL_TRIANGLES);
	glVertex3f(PointA.x, PointA.y, 0);
	glVertex3f(PointB.x, PointA.y, 0);
	glVertex3f(PointC.x, PointC.y, 0);
	glColor3f(PointA.x, PointB.x, PointC.x);
	glEnd();

	PrintText(15, 30, Area);
	PrintText(30, 30, ToString(area));
	PrintText(-36, height, Height);
	PrintText(-25, height, ToString(height));
	PrintText(base - 10, BaseText(PointA, PointC), Base);
	PrintText(base, BaseText(PointA, PointC), ToString(base));

    glutSwapBuffers();
    glutPostRedisplay();
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(300, 300);
    glutCreateWindow("Triangles!");
    glutDisplayFunc(Draw);
	CalcArea(PointA, PointB, PointC);

	std::cout << "Area: " << area << "cm^2\n";

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_COLOR_MATERIAL);


    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, 1.0, 1.0, 1000.0); 

    glutMainLoop();

	return 0;
}
Last edited on
You actually are not using SDL, you're using GLUT. Glut is old and rather limited, but should suffice to teach yourself.

I found LightHouse3d to have a good tutorial:
http://www.lighthouse3d.com/opengl/glut/

I dont understand where you assign values to PointA, PointB, or PointC.

But yeah, you're going to need a mouse event function. This event is triggered when you click the mouse in the scene, and will give you the location of the click. It would be your job to figure out if this is a vertice, the difference in mouse click location from the last one, and move that point accordingly.
GLUT has mouse handling. You can use glutMouseFunc() to assign a callback which is called whenever the mouse button changes state, and glutMotionFunc() to assign a callback for the mouse motion. Implement your mouse as a state machine, e.g.

1
2
3
4
5
struct Mouse {
    int state_;
    int vertex_;
    int x_, y_;
};


You can write your mouse state callback so that the motion callback is disabled whenever the left button goes up, and enabled whenever the button goes down. When it goes down, transform the mouse coordinates into world coordinates. If the mouse position is within a certain number of units of one of the vertices, set the vertex_ member of the Mouse object to an integer corresponding to that vertex (otherwise set it to 0).

Then all you have to do is write the motion callback so that every time it's called it updates the position of the vertex corresponding to the vertex_ variable (unless vertex_ = 0) to be equal to the world coordinates of the mouse. Next time the update function is called (which you haven't implemented yet), it will render the triangle with that vertex in its new position.

Edit: Actually, I'm thinking you'll need to project world coordinates to relative coordinates instead. You can't just extend coordinates into a higher dimension and get a unique value.
Last edited on
This is a bit more of a noobish question to ask, but I'm still very new to OpenGL and glut. How would I implement an Update() function? It seems like the glut program constantly loops through the Draw() function as if its the Update()
You are looping in Draw() because you put a glutPostRedisplay() at the end. (it doesn't make sense).

The idea:
_ You've got callback functions, registered to events. (by instance, every time you make a click it would call the mouse_click() function)
_ If the function does something that requires to redraw the screen (by instance, every time that you resize the window or you move an object of the world),
then you call glutPostRedisplay() to make notice of that.
If there is such notice, the draw() function will be executed `at some point'
So in that case, would I want to move the glutPostRedisplay() from Draw() and add it to the Update() function I create?
Topic archived. No new replies allowed.