OpenGL---GLEW和GLFW库下通过鼠标绘制点以及bezier曲线

环境配置

系统:Windows 10

OpenGL配置:参照https://learnopengl-cn.readthedocs.io/zh/latest/这系列的教程配置的GLEW和GLFW库

根据鼠标点击画点

鼠标回调函数

int num = 0;    //记录当前存储的坐标个数
GLfloat pos[4][3];  //记录每个顶点的x,y, z坐标
GLfloat mouseX, mouseY; //鼠标点击时的鼠标位置

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, GL_TRUE);
}

void mouse_move_callback(GLFWwindow* window, double xpos, double ypos) {
    mouseX = xpos;
    mouseY = ypos;
}

显示点的函数

void display(void) {
    glBegin(GL_POINTS);
    for (int i = 0; i < Points.size(); i++) {
        glColor3f(1.0f, 1.0f, 1.0f);//绘点的颜色
        glVertex3f(Points[i][0], Points[i][1], Points[i][2]);
    }
    glEnd();
}

完整代码

#include <iostream>
#include <vector>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
using std::vector;

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
void mouse_move_callback(GLFWwindow* window, double xpos, double ypos);
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods);
void display(void);

const GLuint WIDTH = 800, HEIGHT = 600;

vector<vector<GLfloat>> Points;  //记录每个顶点的x,y, z坐标
GLfloat mouseX, mouseY; //鼠标点击时的鼠标位置

int main()
{
    glfwInit();

    GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
    glfwMakeContextCurrent(window);

    glfwSetKeyCallback(window, key_callback);
    glfwSetCursorPosCallback(window, mouse_move_callback);//鼠标移动回调函数
    glfwSetMouseButtonCallback(window, mouse_button_callback);//鼠标点击回调函数

    glewInit();

    while (!glfwWindowShouldClose(window))
    {
        glfwPollEvents();

        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        display();

        glfwSwapBuffers(window);
    }

    glfwTerminate();
    return 0;
}


void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, GL_TRUE);
}

void mouse_move_callback(GLFWwindow* window, double xpos, double ypos) {
    mouseX = xpos;
    mouseY = ypos;
}

void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
    float rotateAngle = 0.0f;
    if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {
        vector<GLfloat> pos(3);
        pos[0] = mouseX / 400 - 1;
        pos[1] = (mouseY / 300 - 1)*-1;
        pos[2] = 0.0f;
        Points.push_back(pos);
    }
}

void display(void) {
    glBegin(GL_POINTS);
    for (int i = 0; i < Points.size(); i++) {
        glColor3f(1.0f, 1.0f, 1.0f);//绘点的颜色
        glVertex3f(Points[i][0], Points[i][1], Points[i][2]);
    }
    glEnd();
}

PS:我一直在学习LearnOpenGL这个教程,在教程中作者让我们通过以下几个语句设置OpenGL的版本和模式。但我发现如果这样设置之后,无法利用glXXX()这些函数(比如画点用的glVertex3f()),不知原因。

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

利用鼠标选择4个点绘制Bezier曲线

描绘Bezier曲线函数

void Bezier(int n) {
    float f1, f2, f3, f4;
    float deltaT = 1.0 / n;
    float T;
    glBegin(GL_LINE_STRIP);
    glColor3f(0.8f, 0.2f, 0.5f);
    for (int i = 0; i <= n; i++) {
        T = i * deltaT;
        f1 = (1 - T) * (1 - T) * (1 - T);
        f2 = 3 * T * (1 - T) * (1 - T);
        f3 = 3 * T * T * (1 - T);
        f4 = T * T * T;
        float x = f1 * Points[0][0] + f2 * Points[1][0] + f3 * Points[2][0] + f4 * Points[3][0];
        float y = f1 * Points[0][1] + f2 * Points[1][1] + f3 * Points[2][1] + f4 * Points[3][1];
        float z = f1 * Points[0][2] + f2 * Points[1][2] + f3 * Points[2][2] + f4 * Points[3][2];
        glVertex3f(x, y, z);
    }
    glEnd();
}

完整代码

#include <iostream>
#include <vector>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
using std::vector;

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
void mouse_move_callback(GLFWwindow* window, double xpos, double ypos);
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods);
void display(void);
void Bezier(int n);

const GLuint WIDTH = 800, HEIGHT = 600;

vector<vector<GLfloat>> Points(4,vector<GLfloat>(3));  //记录每个顶点的x,y, z坐标
GLfloat mouseX, mouseY; //鼠标点击时的鼠标位置
int count = 0;

int main()
{
    glfwInit();

    GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
    glfwMakeContextCurrent(window);

    glfwSetKeyCallback(window, key_callback);
    glfwSetCursorPosCallback(window, mouse_move_callback);//鼠标移动回调函数
    glfwSetMouseButtonCallback(window, mouse_button_callback);//鼠标点击回调函数

    glewInit();

    while (!glfwWindowShouldClose(window))
    {
        glfwPollEvents();

        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        display();

        glfwSwapBuffers(window);
    }

    glfwTerminate();
    return 0;
}


void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, GL_TRUE);
}

void mouse_move_callback(GLFWwindow* window, double xpos, double ypos) {
    mouseX = xpos;
    mouseY = ypos;
}

void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
    if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {
        count %= 4;
        Points[count][0] = mouseX / 400 - 1;
        Points[count][1] = (mouseY / 300 - 1)*-1;
        Points[count][2] = 0.0f;
        count++;
    }
}

void display(void) {
    if (count == 4) {
        glBegin(GL_LINE_STRIP);
        for (int i = 0; i < count; i++) {
            glColor3f(1.0f, 1.0f, 1.0f);//绘点的颜色
            glVertex3f(Points[i][0], Points[i][1], Points[i][2]);
        }
        glEnd();
        Bezier(20);
    }
    else {
        glBegin(GL_POINTS);
        for (int i = 0; i < count; i++) {
            glColor3f(1.0f, 1.0f, 1.0f);//绘点的颜色
            glVertex3f(Points[i][0], Points[i][1], Points[i][2]);
        }
        glEnd();
    }
}


void Bezier(int n) {
    float f1, f2, f3, f4;
    float deltaT = 1.0 / n;
    float T;
    glBegin(GL_LINE_STRIP);
    glColor3f(0.8f, 0.2f, 0.5f);
    for (int i = 0; i <= n; i++) {
        T = i * deltaT;
        f1 = (1 - T) * (1 - T) * (1 - T);
        f2 = 3 * T * (1 - T) * (1 - T);
        f3 = 3 * T * T * (1 - T);
        f4 = T * T * T;
        float x = f1 * Points[0][0] + f2 * Points[1][0] + f3 * Points[2][0] + f4 * Points[3][0];
        float y = f1 * Points[0][1] + f2 * Points[1][1] + f3 * Points[2][1] + f4 * Points[3][1];
        float z = f1 * Points[0][2] + f2 * Points[1][2] + f3 * Points[2][2] + f4 * Points[3][2];
        glVertex3f(x, y, z);
    }
    glEnd();
}

当鼠标点出了4个点之前,只显示点,而当4个点选完之后,描绘出曲线。

三次贝塞尔曲线参数方程如下:

B ( x ) = P 0 ( 1 t ) 3 + 3 P 1 t ( 1 t ) 2 + 3 P 2 t 2 ( 1 t ) + P 3 t 3

在离散的时候,我们可以让t=i/n,其中i为绘制的第i个点,n为绘制的总的点数。(这里我选择的是20个点)

猜你喜欢

转载自blog.csdn.net/qq_39178023/article/details/80567523
今日推荐