C++ 为3D杯子创建圆柱体底座(现代OpenGL、GLM)

C++ 为3D杯子创建圆柱体底座(现代OpenGL、GLM),c++,opengl,3d,glm-math,C++,Opengl,3d,Glm Math,嘿,我很难弄清楚如何为我需要绘制的3D杯子创建360底座。 我正在使用GLEW、GLFW和GLM数学 到目前为止,我已经到了可以创建三维立方体和三维金字塔的地步。到目前为止,我的想法是,我需要以360度的方式创建6个或更多的三角形副本。我该怎么做?除了创建三角形、立方体和金字塔,现代OpenGL的资源并不多 守则: #include <GLEW/glew.h> #include <GLFW/glfw3.h> #include <iostream> // GL

嘿,我很难弄清楚如何为我需要绘制的3D杯子创建360底座。 我正在使用GLEW、GLFW和GLM数学

到目前为止,我已经到了可以创建三维立方体和三维金字塔的地步。到目前为止,我的想法是,我需要以360度的方式创建6个或更多的三角形副本。我该怎么做?除了创建三角形、立方体和金字塔,现代OpenGL的资源并不多

守则:

#include <GLEW/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

// GLM Mathematics
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

using namespace std;

int width, height;
const double PI = 3.14159;
const float toRadians = PI / 180.0f;

// Draw Primitive(s)
void draw()
{
    GLenum mode = GL_TRIANGLES;
    GLsizei indices = 6;
    glDrawElements(mode, indices, GL_UNSIGNED_BYTE, nullptr);
}

// Input Function Prototypes
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos);
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods);

// Declare View Matrix
glm::mat4 viewMatrix;

// Initialize FOV
GLfloat fov = 45.0f;

// Define Camera Attributes
glm::vec3 cameraPosition = glm::vec3(0.0f, 0.0f, 3.0f);
glm::vec3 target = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 cameraDirection = glm::normalize(cameraPosition - target);
glm::vec3 worldUp = glm::vec3(0.0f, 1.0f, 0.0f);
glm::vec3 cameraRight = glm::normalize(glm::cross(worldUp, cameraDirection));
glm::vec3 cameraUp = glm::normalize(glm::cross(cameraDirection, cameraRight));
glm::vec3 cameraFront = glm::normalize(glm::vec3(0.0f, 0.0f, -1.0f));

// Declare target prototype
glm::vec3 getTarget();

// Camera transformation prototype
void TransformCamera();

// Boolean array for keys and mouse buttons
bool keys[1024], mouseButtons[3];

// Boolean to check camera transformation
bool isPanning = false, isOrbiting = false, isZooming = false;

// Radius, Pitch, and Yaw
GLfloat radius = 3.0f, rawYaw = 0.0f, rawPitch = 0.0f, degYaw, degPitch;

GLfloat deltaTime = 0.0f, lastFrame = 0.0f;
GLfloat lastX = 320, lastY = 240, xChange, yChange;

// Check for any initial mouse movement
bool firstMouseMove = true;

void initCamera();

// Create and Compile Shaders
static GLuint CompileShader(const string& source, GLuint shaderType)
{
    // Create Shader object
    GLuint shaderID = glCreateShader(shaderType);
    const char* src = source.c_str();

    // Attach source code to Shader object
    glShaderSource(shaderID, 1, &src, nullptr);

    // Compile Shader
    glCompileShader(shaderID);

    // Return ID of Compiled shader
    return shaderID;

}

// Create Program Object
static GLuint CreateShaderProgram(const string& vertexShader, const string& fragmentShader)
{
    // Compile vertex shader
    GLuint vertexShaderComp = CompileShader(vertexShader, GL_VERTEX_SHADER);

    // Compile fragment shader
    GLuint fragmentShaderComp = CompileShader(fragmentShader, GL_FRAGMENT_SHADER);

    // Create program object
    GLuint shaderProgram = glCreateProgram();

    // Attach vertex and fragment shaders to program object
    glAttachShader(shaderProgram, vertexShaderComp);
    glAttachShader(shaderProgram, fragmentShaderComp);

    // Link shaders to create executable
    glLinkProgram(shaderProgram);

    // Delete compiled vertex and fragment shaders
    glDeleteShader(vertexShaderComp);
    glDeleteShader(fragmentShaderComp);

    // Return Shader Program
    return shaderProgram;

}


int main(void)
{
    width = 640; height = 480;

    GLFWwindow* window;

    /* Initialize the library */
    if (!glfwInit())
        return -1;

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(width, height, "Main Window", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    // Set input callback functions
    glfwSetKeyCallback(window, key_callback);
    glfwSetCursorPosCallback(window, cursor_position_callback);
    glfwSetMouseButtonCallback(window, mouse_button_callback);
    glfwSetScrollCallback(window, scroll_callback);

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    // Initialize GLEW
    if (glewInit() != GLEW_OK)
        cout << "Error!" << endl;

    GLfloat vertices[] = {

        // Triangle 1
        -0.5, -0.5, 0.0, // index 0
        1.0, 0.0, 0.0, // red

        -0.5, 0.5, 0.0, // index 1
        0.0, 1.0, 0.0, // green

        0.5, -0.5, 0.0,  // index 2 
        0.0, 0.0, 1.0, // blue

        // Triangle 2   
        0.5, 0.5, 0.0,  // index 3  
        1.0, 0.0, 1.0 // purple
    };

    // Define element indices
    GLubyte indices[] = {
        0, 1, 2,
        1, 2, 3
    };

    // Plane Transforms
    glm::vec3 planePositions[] = {
        glm::vec3(0.0f,  0.0f,  0.5f),
        glm::vec3(0.5f,  0.0f,  0.0f),
        glm::vec3(0.0f,  0.0f,  -0.5f),
        glm::vec3(-0.5f, 0.0f,  0.0f)
    };

    glm::float32 planeRotations[] = {
        0.0f, 90.0f, 0.0f, 90.0f
    };

    // Setup some OpenGL options
    glEnable(GL_DEPTH_TEST);

    // Wireframe mode
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    GLuint VBO, EBO, VAO;

    glGenBuffers(1, &VBO); // Create VBO
    glGenBuffers(1, &EBO); // Create EBO

    glGenVertexArrays(1, &VAO); // Create VOA
    glBindVertexArray(VAO);

    // VBO and EBO Placed in User-Defined VAO
    glBindBuffer(GL_ARRAY_BUFFER, VBO); // Select VBO
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); // Select EBO


    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // Load vertex attributes
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // Load indices 

                                                                                     // Specify attribute location and layout to GPU
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);

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

    glBindVertexArray(0); // Unbind VOA or close off (Must call VOA explicitly in loop)

    // Vertex shader source code
    string vertexShaderSource =
        "#version 330 core\n"
        "layout(location = 0) in vec4 vPosition;"
        "layout(location = 1) in vec4 aColor;"
        "out vec4 oColor;"
        "uniform mat4 model;"
        "uniform mat4 view;"
        "uniform mat4 projection;"
        "void main()\n"
        "{\n"
        "gl_Position = projection * view * model * vPosition;"
        "oColor = aColor;"
        "}\n";

    // Fragment shader source code
    string fragmentShaderSource =
        "#version 330 core\n"
        "in vec4 oColor;"
        "out vec4 fragColor;"
        "void main()\n"
        "{\n"
        "fragColor = oColor;"
        "}\n";

    // Creating Shader Program
    GLuint shaderProgram = CreateShaderProgram(vertexShaderSource, fragmentShaderSource);


    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {

        // Set Delta time
        GLfloat currentFrame = glfwGetTime();
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;

        // Resize window and graphics simultaneously
        glfwGetFramebufferSize(window, &width, &height);
        glViewport(0, 0, width, height);

        /* Render here */
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Use Shader Program exe and select VAO before drawing 
        glUseProgram(shaderProgram); // Call Shader per-frame when updating attributes


        // Declare transformations (can be initialized outside loop)        

        glm::mat4 projectionMatrix;

        viewMatrix = glm::lookAt(cameraPosition, getTarget(), worldUp);

        projectionMatrix = glm::perspective(fov, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);

        // Get matrix's uniform location and set matrix
        GLint modelLoc = glGetUniformLocation(shaderProgram, "model");
        GLint viewLoc = glGetUniformLocation(shaderProgram, "view");
        GLint projLoc = glGetUniformLocation(shaderProgram, "projection");

        //glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(modelMatrix));
        glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(viewMatrix));
        glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projectionMatrix));


        glBindVertexArray(VAO); // User-defined VAO must be called before draw. 

        for (GLuint i = 0; i < 4; i++)
        {
            glm::mat4 modelMatrix;
            modelMatrix = glm::translate(modelMatrix, planePositions[i]);
            modelMatrix = glm::rotate(modelMatrix, planeRotations[i] * toRadians, glm::vec3(0.0f, 1.0f, 0.0f));
            glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(modelMatrix));
            // Draw primitive(s)
            draw();
        }

        // Unbind Shader exe and VOA after drawing per frame
        glBindVertexArray(0); //Incase different VAO wii be used after
        glUseProgram(0); // Incase different shader will be used after

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();

        // Poll camera transformations
        TransformCamera();
    }

    //Clear GPU resources
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);


    glfwTerminate();
    return 0;
}

// Define Input Callback Functions
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    // Display ASCII Keycode
    // ALT = ASCII 342
    //cout << "ASCII: " << key << endl;

    if (action == GLFW_PRESS)
        keys[key] = true;
    else if (action == GLFW_RELEASE)
        keys[key] = false;
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
    /*
    // Display scroll offset
    if (yoffset > 0)
        cout << "Scroll Up: ";
    if (yoffset < 0)
        cout << "Scroll down: ";

    cout << yoffset << endl;
    */

    /*
    if (isZooming)
    {
        // Clamp FOV
        if (fov >= 1.0f && fov <= 55.0f)
            fov -= yoffset * 0.01f;

        // Default FOV
        if (fov < 1.0f)
            fov = 1.0f;
        if (fov > 45.0f)
            fov = 45.0f;
    }
    */

}
static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
{
    // cout << "Mouse X: " << xpos << endl;
    // cout << "Mouse Y: " << ypos << endl;

    if (firstMouseMove)
    {
        lastX = xpos;
        lastY = ypos;
        firstMouseMove = false;
    }

    // Calculate cursor offset
    xChange = xpos - lastX;
    yChange = lastY - ypos;

    lastX = xpos;
    lastY = ypos;

    // Zoom Camera
    if (isZooming)
    {
        if (fov < 1.0f)
            fov = 1.0f;
        if (fov > 45.0f)
            fov = 45.0f;

        if (xpos > 0)
            fov -= lastX * 0.01f;

        if (ypos > 0)
            fov -= lastY * 0.01f;


    }

    // Pan camera
    if (isPanning)
    {
        if (cameraPosition.z > 0.f)
            cameraFront.z = 1.0f;
        else
            cameraFront.z = -1.0f;


        GLfloat cameraSpeed = xChange * deltaTime;
        cameraPosition += cameraSpeed * cameraRight;

        cameraSpeed = yChange * deltaTime;
        cameraPosition += cameraSpeed * cameraUp;
    }

    // Orbit camera
    if (isOrbiting)
    {
        rawYaw += xChange;
        rawPitch += yChange;

        // Convert Yaw and Pitch to degrees
        degYaw = glm::radians(rawYaw);
        // degPitch = glm::radians(rawPitch);
        degPitch = glm::clamp(glm::radians(rawPitch), -glm::pi<float>() / 2.0f + .1f, glm::pi<float>() / 2.0f - .1f);

        // Azimuth Altitude Formula
        cameraPosition.x = target.x + radius * cosf(degPitch) * sinf(degYaw);
        cameraPosition.y = target.y + radius * sinf(degPitch);
        cameraPosition.z = target.z + radius * cosf(degPitch) * cosf(degYaw);
    }

}
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
    /*
    // Detect Mouse Button Clicks
    if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
        cout << "LMB Clicked" << endl;
    if (button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_PRESS)
        cout << "MMB Clicked" << endl;
    if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS)
        cout << "RMB Clicked" << endl;
    */

    if (action == GLFW_PRESS)
        mouseButtons[button] = true;
    else if (action == GLFW_RELEASE)
        mouseButtons[button] = false;
}

// Define getTarget function
glm::vec3 getTarget()
{
    if (isPanning)
        target = cameraPosition + cameraFront;
    return target;
}

// Define TransformCamera function
void TransformCamera()
{
    // Pan camera if left alt key and middle mouse button pressed same time
    if (keys[GLFW_KEY_LEFT_ALT] && mouseButtons[GLFW_MOUSE_BUTTON_MIDDLE])
        isPanning = true;
    else
        isPanning = false;

    // Orbit camera if left alt key and left mouse button pressed same time
    if (keys[GLFW_KEY_LEFT_ALT] && mouseButtons[GLFW_MOUSE_BUTTON_LEFT])
        isOrbiting = true;
    else
        isOrbiting = false;

    // Zoom camera if left alt key and right mouse button pressed same time
    if (keys[GLFW_KEY_LEFT_ALT] && mouseButtons[GLFW_MOUSE_BUTTON_RIGHT])
        isZooming = true;
    else
        isZooming = false;

    // Reset Camera
    if (keys[GLFW_KEY_F])
        initCamera();
}

void initCamera()
{
    cameraPosition = glm::vec3(0.0f, 0.0f, 3.0f);
    target = glm::vec3(0.0f, 0.0f, 0.0f);
    cameraDirection = glm::normalize(cameraPosition - target);
    worldUp = glm::vec3(0.0f, 1.0f, 0.0f);
    cameraRight = glm::normalize(glm::cross(worldUp, cameraDirection));
    cameraUp = glm::normalize(glm::cross(cameraDirection, cameraRight));
    cameraFront = glm::normalize(glm::vec3(0.0f, 0.0f, -1.0f));
}
#包括
#包括
#包括
//GLM数学
#包括
#包括
#包括
使用名称空间std;
int宽度、高度;
常数双PI=3.14159;
常数浮点环面=π/180.0f;
//绘制基本体
作废提款()
{
GLenum模式=GL_三角形;
GLsizei指数=6;
GLD元素(模式、索引、GLU无符号字节、空PTR);
}
//输入函数原型
void key_回调(GLFWwindow*窗口、int key、int scancode、int action、int mods);
void scroll_回调(GLFWwindow*窗口,双xoffset,双yoffset);
静态无效光标位置回调(GLFWwindow*窗口,双XPO,双YPO);
无效鼠标按钮回调(GLFWwindow*窗口、int按钮、int操作、int mods);
//声明视图矩阵
glm::mat4视图矩阵;
//初始化视场
GLFOV=45.0f;
//定义摄影机属性
glm::vec3 cameraPosition=glm::vec3(0.0f,0.0f,3.0f);
glm::vec3 target=glm::vec3(0.0f,0.0f,0.0f);
glm::vec3 cameraDirection=glm::normalize(cameraPosition-target);
glm::vec3 worldUp=glm::vec3(0.0f,1.0f,0.0f);
glm::vec3 cameraRight=glm::normalize(glm::cross(worldUp,CamerarDirection));
glm::vec3 cameraUp=glm::normalize(glm::cross(CamerarDirection,cameraRight));
glm::vec3 cameraFront=glm::normalize(glm::vec3(0.0f,0.0f,-1.0f));
//声明目标原型
glm::vec3 getTarget();
//摄像机变换原型
无效的照相机();
//键和鼠标按钮的布尔数组
布尔键[1024],鼠标按钮[3];
//用于检查摄影机变换的布尔值
bool isPanning=false,isOrbiting=false,isZooming=false;
//半径、俯仰和偏航
GLfloat半径=3.0f,横摆角=0.0f,横摆角=0.0f,反摆角,反摆角;
GLfloat deltaTime=0.0f,lastFrame=0.0f;
GLfloat lastX=320,lastY=240,xChange,yChange;
//检查是否有任何初始鼠标移动
bool firstMouseMove=true;
void initCamera();
//创建和编译着色器
静态GLuint编译器标头(常量字符串和源代码,GLuint着色器类型)
{
//创建着色器对象
GLuint shaderID=glCreateShader(shaderType);
const char*src=source.c_str();
//将源代码附加到着色器对象
glShaderSource(shaderID,1,&src,nullptr);
//编译着色器
glCompileShader(shaderID);
//已编译着色器的返回ID
返回shaderID;
}
//创建程序对象
静态GLuint CreateShaderProgram(常量字符串和顶点着色器、常量字符串和碎片着色器)
{
//编译顶点着色器
GLuint vertexShaderComp=编译器着色器(vertexShader,GL_VERTEX_着色器);
//编译片段着色器
GLuint fragmentShaderComp=编译器着色器(fragmentShader,GL\u FRAGMENT\u着色器);
//创建程序对象
GLuint shaderProgram=glCreateProgram();
//将顶点和片段着色器附着到程序对象
glAttachShader(着色器程序,vertexShaderComp);
glAttachShader(shaderProgram,fragmentShaderComp);
//链接着色器以创建可执行文件
GLLINK程序(着色器程序);
//删除已编译的顶点和片段着色器
glDeleteShader(vertexShaderComp);
glDeleteShader(fragmentShaderComp);
//返回着色器程序
返回着色器程序;
}
内部主(空)
{
宽度=640;高度=480;
GLFWwindow*窗口;
/*初始化库*/
如果(!glfwInit())
返回-1;
/*创建窗口模式窗口及其OpenGL上下文*/
window=glfwCreateWindow(宽度、高度、“主窗口”、NULL、NULL);
如果(!窗口)
{
glfwTerminate();
返回-1;
}
//设置输入回调函数
glfwSetKeyCallback(窗口、键回调);
glfwSetCursorPosCallback(窗口、光标位置回调);
glfwSetMouseButtonCallback(窗口、鼠标按钮回调);
glfwSetScrollCallback(窗口,滚动_回调);
/*将窗口的上下文设置为当前*/
glfwMakeContextCurrent(窗口);
//初始化GLEW
如果(glewInit()!=GLEW\u确定)

coutAFAIK,在OpenGL中绘制圆的最佳方法是使用如下三角形:


你基本上是在做比萨饼。切片越多,它看起来就越像一个圆。你可以使用GL_TRIANGLE_FAN来减少绘制圆所需的顶点数。

我明白了。我开始手动绘制每个三角形。所以现在我有6个,但正如你所说,我想我需要更多才能使它更像一个圆。手动编码很烦人每一个并计算出6个以上三角形的顶点x、y更好的方法是:1.计算出圆周长上需要多少点2.将360除以点数-此值为“步长”量3.使用for循环,从角度0开始,并按步长量递增,直到达到360 4.在ea处对于for循环的ch迭代,计算当前角度的sin和cos;角度的cos乘以所需的圆半径即为X位置,与Y位置类似,但为sin。请参阅此海报代码: