CG 中点法画直线

1. \((x_i,y_i) \rightarrow (x_{i+1},y_{i+1})\)

根据可能所取点间的中点M与直线的位置
构造判别式:\(d = F(M) = F(x_{i+1}, y_{i,r}+0.5)\)
由d的正和负可判定下一个像素。 其中 \(p(x_i , y_{i,r})\)为当前点坐标
d < 0, 取NE;否则取E

2.如何再确定下一个像素\((x_{i+2},?)\)

1) 若\(d≥0\), 取正右方像素E, 则判定再下一个像素的d为\(d_1=F(x_i+2, y_{i,r}+0.5)=a(x_{i+2})+b(y_{i,r}+0.5)+c=d+a\),d的增量是a
2) 若d<0, 取右上方像素NE, 则判定再下一个像素的d为\(d2=F(x_i+2, y_{i,r}+1.5)=d+a+b\),d的增量为a+b

3.增量d的初始值

\(d_0=F(x_0+1, y_0+0.5)=F(x_0, y_0)+a+0.5b=a + 0.5b\)

4.增量d的递推公式

\[d_0=a+0.5b \\ d_i+1 = \left\{ \begin{array}{lr} d_i+a & d_i>0\\ d_i+a+b & d_i\leq0 \end{array} \right. \]

2d代替d

\[d_0=2a+b\\ d_i+1 = \left\{ \begin{array}{lr} d_i+2a & d_i>0\\ d_i+2a+2b & d_i\leq0 \end{array} \right. \]

5.其他几种情况

\[0 \leq m \leq 1\\ d_0=2a+b \\ d_{i+1} = \left\{ \begin{array}{lr} d_i+2a & d_i>0\\ d_i+2a+2b & d_i\leq0 \end{array} \right. \]

\[ m > 1 \\ d_0=a+2b \\ d_{i+1} = \left\{ \begin{array}{lr} d_i+2a+2b & d_i>0\\ d_i+2b & d_i\leq0 \end{array} \right. \]

\[-1 \leq m \leq 0 \\ d_0=2a-b \\ d_{i+1} = \left\{ \begin{array}{lr} d_i+2a-2b & d_i>0\\ d_i+2a & d_i\leq0 \end{array} \right. \]

\[m<- 1 \\ d_0=a-2b \\ d_{i+1} = \left\{ \begin{array}{lr} d_i-2b & d_i>0\\ d_i+2a-2b & d_i\leq0 \end{array} \right. \]

#include <iostream>

// GLEW
#define GLEW_STATIC
#include <GL/glew.h>

// GLFW
#include <GLFW/glfw3.h>
using namespace std;

// Function prototypes
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);

// Window dimensions
const GLuint WIDTH = 800, HEIGHT = 800;

// Shaders
const GLchar* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
"}\0";
const GLchar* fragmentShaderSource = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
"color = vec4(128.0/255.0f, 1.0f, 28*6.0/255.0f, 1.0f);\n"
"}\n\0";

GLint tot = 0;
GLfloat vertices[100000];
void MidpointLine(GLint x0, GLint y0, GLint x1, GLint y1);
// The MAIN function, from here we start the application and run the game loop
int main()
{
    // Init GLFW
    glfwInit();
    // Set all the required options for GLFW
    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);

    // Create a GLFWwindow object that we can use for GLFW's functions
    GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
    glfwMakeContextCurrent(window);

    // Set the required callback functions
    glfwSetKeyCallback(window, key_callback);

    // Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
    glewExperimental = GL_TRUE;
    // Initialize GLEW to setup the OpenGL Function pointers
    glewInit();

    // Define the viewport dimensions
    int width, height;
    glfwGetFramebufferSize(window, &width, &height);
    glViewport(0, 0, width, height);


    // Build and compile our shader program
    // Vertex shader
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);
    // Check for compile time errors
    GLint success;
    GLchar infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
    }
    // Fragment shader
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    // Check for compile time errors
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
    }
    // Link shaders
    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    // Check for linking errors
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
    }
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);


    // Set up vertex data (and buffer(s)) and attribute pointers
    MidpointLine(0, 500, 0, -500);
    MidpointLine(-500, -500, 500, 700);
    MidpointLine(-500, 500, 500, -700);
    MidpointLine(-500, 200, 500, -300);
    GLuint VBO, VAO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    // Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointer(s).
    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0); // Note that this is allowed, the call to glVertexAttribPointer registered VBO as the currently bound vertex buffer object so afterwards we can safely unbind

    glBindVertexArray(0); // Unbind VAO (it's always a good thing to unbind any buffer/array to prevent strange bugs)

    // Game loop
    while (!glfwWindowShouldClose(window))
    {
        // Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
        glfwPollEvents();

        // Render
        // Clear the colorbuffer
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // Draw our first triangle
        glUseProgram(shaderProgram);
        glBindVertexArray(VAO);
        glDrawArrays(GL_POINTS, 0, tot);
        glBindVertexArray(0);

        // Swap the screen buffers
        glfwSwapBuffers(window);
    }
    // Properly de-allocate all resources once they've outlived their purpose
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    // Terminate GLFW, clearing any resources allocated by GLFW.
    glfwTerminate();
    return 0;
}

// Is called whenever a key is pressed/released via GLFW
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 addPoint(GLint x, GLint y, GLint z)
{
    vertices[tot++] = 1.0 * x / WIDTH;
    vertices[tot++] = 1.0 * y / HEIGHT;
    vertices[tot++] = z;
}

void MidpointLine(GLint x0, GLint y0, GLint x1, GLint y1)
{
    GLint a, b, d1, d2, d, x, y;
    GLfloat m;
    if (x1 < x0) { swap(x0, x1); swap(y0, y1);}
    a = y0 - y1, b = x1 - x0;
    if (b == 0) m = -1 * a * 100;
    else m = (GLfloat)a / (x0 - x1); 
    x = x0, y = y0;
    addPoint(x, y, 0);

    if (m >= 0 && m <= 1)
    {
        d = 2 * a + b; d1 = 2 * a; d2 = 2 * (a + b);
        while (x < x1)
        {
            if (d <= 0) { y++; d += d2; }
            else d += d1;
            x++;
            addPoint(x, y, 0);
        }
    }
    else if (m > 1)
    {
        d = a + 2 * b; d1 = 2 * (a + b); d2 = 2 * b;
        while (y < y1)
        {
            if (d > 0) { x++; d += d1; }
            else d += d2;
            y++;
            addPoint(x, y, 0);
        }
    }
    else if (m >= -1 && m <= 0)
    {
        d = 2 * a - b; d1 = 2 * a - 2 * b; d2 = 2 * a;
        while (x < x1)
        {
            if (d > 0) { y--; d += d1; }
            else d += d2;
            x++;
            addPoint(x, y, 0);
        }
    }
    else
    {
        d = a - 2 * b; d1 = -2 * b; d2 = 2 * (a - b);
        while (y > y1)
        {
            if (d <= 0) { x++; d += d2; }
            else d += d1;
            y--;
            addPoint(x, y, 0);
        }
    }
}
posted @ 2020-03-21 20:58  特特w  阅读(343)  评论(1编辑  收藏  举报