📅  最后修改于: 2023-12-03 15:23:14.436000             🧑  作者: Mango
本程序可以通过鼠标移动来绘制一个圆。
在程序开始时,需要初始化 OpenGL 环境,包括创建窗口、设置视角、添加光源等。
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("Draw Circle with Mouse");
glClearColor(0.0, 0.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1.0, 1.0, -1.0, 1.0);
回调函数用于处理不同事件,比如绘制图形、改变窗口大小、鼠标事件等。
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMouseFunc(mouse);
圆的绘制可以利用 OpenGL 的内置函数 gluDisk()
,但是这个函数是按半径绘制的,不利于鼠标移动时动态地绘制圆。
我们可以根据鼠标移动的距离来计算圆心坐标和半径,然后利用 OpenGL 的 GL_LINE_LOOP
模式来绘制圆:
float center_x = 0, center_y = 0, radius = 0;
int is_drawing_circle = 0;
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
if (is_drawing_circle) {
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINE_LOOP);
for (int i = 0; i < 360; i++) {
float theta = 2.0f * M_PI * (i / 360.0f);
float x = radius * cosf(theta);
float y = radius * sinf(theta);
glVertex2f(x + center_x, y + center_y);
}
glEnd();
}
glFlush();
}
在 reshape 函数中,我们需要设置视角。我们可以使用 glViewport()
和 gluOrtho2D()
函数来设置视角:
void reshape(GLint w, GLint h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
gluOrtho2D(-1.0, 1.0, -1.0 * (GLfloat) h / (GLfloat) w, 1.0 * (GLfloat) h / (GLfloat) w);
else
gluOrtho2D(-1.0 * (GLfloat) w / (GLfloat) h, 1.0 * (GLfloat) w / (GLfloat) h, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
我们需要处理鼠标事件,包括鼠标的按下、移动和释放事件。在本程序中,我们只需要处理鼠标的移动事件。
当鼠标移动时,我们可以使用 glutMotionFunc()
函数来处理事件。我们需要计算鼠标移动的距离,然后根据距离计算出圆心坐标和半径,最后利用 is_drawing_circle
变量来判断是否需要绘制圆。
void mouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
center_x = 2.0 * ((float) x / (float) glutGet(GLUT_WINDOW_WIDTH)) - 1.0;
center_y = -2.0 * ((float) y / (float) glutGet(GLUT_WINDOW_HEIGHT)) + 1.0;
radius = 0;
is_drawing_circle = 1;
}
else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
is_drawing_circle = 0;
}
}
void motion(int x, int y)
{
if (is_drawing_circle) {
float x_pos = 2.0 * ((float) x / (float) glutGet(GLUT_WINDOW_WIDTH)) - 1.0;
float y_pos = -2.0 * ((float) y / (float) glutGet(GLUT_WINDOW_HEIGHT)) + 1.0;
float dx = x_pos - center_x;
float dy = y_pos - center_y;
radius = sqrtf(dx * dx + dy * dy);
glutPostRedisplay();
}
}
#include <GL/glut.h>
#include <cmath>
float center_x = 0, center_y = 0, radius = 0;
int is_drawing_circle = 0;
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
if (is_drawing_circle) {
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINE_LOOP);
for (int i = 0; i < 360; i++) {
float theta = 2.0f * M_PI * (i / 360.0f);
float x = radius * cosf(theta);
float y = radius * sinf(theta);
glVertex2f(x + center_x, y + center_y);
}
glEnd();
}
glFlush();
}
void reshape(GLint w, GLint h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
gluOrtho2D(-1.0, 1.0, -1.0 * (GLfloat) h / (GLfloat) w, 1.0 * (GLfloat) h / (GLfloat) w);
else
gluOrtho2D(-1.0 * (GLfloat) w / (GLfloat) h, 1.0 * (GLfloat) w / (GLfloat) h, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
void mouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
center_x = 2.0 * ((float) x / (float) glutGet(GLUT_WINDOW_WIDTH)) - 1.0;
center_y = -2.0 * ((float) y / (float) glutGet(GLUT_WINDOW_HEIGHT)) + 1.0;
radius = 0;
is_drawing_circle = 1;
}
else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
is_drawing_circle = 0;
}
}
void motion(int x, int y)
{
if (is_drawing_circle) {
float x_pos = 2.0 * ((float) x / (float) glutGet(GLUT_WINDOW_WIDTH)) - 1.0;
float y_pos = -2.0 * ((float) y / (float) glutGet(GLUT_WINDOW_HEIGHT)) + 1.0;
float dx = x_pos - center_x;
float dy = y_pos - center_y;
radius = sqrtf(dx * dx + dy * dy);
glutPostRedisplay();
}
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("Draw Circle with Mouse");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glClearColor(0.0, 0.0, 0.0, 0.0);
glutMainLoop();
return 0;
}