提问人:JS2023 提问时间:11/15/2023 最后编辑:genpfaultJS2023 更新时间:11/15/2023 访问量:35
带有圆柱体的 OpenGL/C++ 立方体仅呈现圆柱体圆形底的前半部分
OpenGL/C++ cube with cylinder inside only renders first half of cylinder's circular base
问:
我很困惑为什么这不能呈现整个实体。
这是我的圆柱体类.cpp:
#include "cylinderClass.h"
#include <glad/glad.h>
#include <vector>
#include <glm/trigonometric.hpp>
#include <stdio.h>
// ********* CYLINDER ************ //
// generates vertices for cylinder with radius 1.0 and height 1.0
// base is on the X/Z plane and y-axis passes through center
GLfloat* Cylinder::generateVertices()
{
// array to hold coordinates of all 722 vertices of cylinder (6 floats per set: x, y, z, r, g, b)
static GLfloat vertices2[4380]; // 4332 for cylinder vertices, 48 for cube
// center of bottom circle (origin)
vertices2[0] = 0.0f;
vertices2[1] = 0.0f;
vertices2[2] = 0.0f;
// color = red
vertices2[3] = 1.0f;
vertices2[4] = 0.0f;
vertices2[5] = 0.0f;
// center of top circle
vertices2[6] = 0.0f;
vertices2[7] = 1.0f;
vertices2[8] = 0.0f;
// color = green
vertices2[9] = 0.0f;
vertices2[10] = 1.0f;
vertices2[11] = 0.0f;
// angle = degrees from positive x-axis
// angle goes from 0 to 359 degrees in increments of 1
// circle bases are each made up of 360 triangles
float angle = 0.0f;
int offset = 2160;
float xcoord = 0.0f;
float zcoord = 0.0f;
// vertices2[12] is the point at 0 degrees on lower circle
// vertices2[2166] is the point at 359 degrees on lower circle
// vertices2[2172] is the point at 0 degrees on upper circle
// vertices2[4326] is the point at 359 degrees on upper circle
// vertices2[4332] will begin cube vertices
for (int i = 12; i < 2167; i = i + 6)
{
// x coordinates of lower and upper circles (they're the same)
xcoord = cosf(glm::radians((angle)));
if (abs(xcoord) < 0.0001f) {
xcoord = 0.0f;
}
vertices2[i] = xcoord;
vertices2[i + offset] = xcoord;
// y coordinates of lower and upper circles
vertices2[i + 1] = 0.0f;
vertices2[i + offset + 1] = 1.0f;
// z coordinates of lower and upper circles (they're the same)
zcoord = sinf(glm::radians((angle)));
if (abs(zcoord) < 0.0001f) {
zcoord = 0.0f;
}
vertices2[i + 2] = zcoord;
vertices2[i + offset + 2] = zcoord;
// red color value of lower and upper circles
vertices2[i + 3] = 0.0f;
vertices2[i + offset + 3] = 0.0f;
// green color value of lower and upper circles
vertices2[i + 4] = 0.0f;
vertices2[i + offset + 4] = 0.0f;
// blue color value of lower and upper circles
vertices2[i + 5] = 1.0f;
vertices2[i + offset + 5] = 1.0f;
angle = angle + 1.0f;
}
// ********* CUBE ************ //
//
// point 0, upper right corner of base (x, y, z, r, g, b)
vertices2[4332] = 0.5f;
vertices2[4333] = 0.0f;
vertices2[4334] = 0.5f;
// point 1, lower right corner of base
vertices2[4338] = 0.5f;
vertices2[4339] = 0.0f;
vertices2[4340] = -0.5f;
// point 2, lower left corner of base
vertices2[4344] = -0.5f;
vertices2[4345] = 0.0f;
vertices2[4346] = -0.5f;
// point 3, upper left corner of base
vertices2[4350] = -0.5f;
vertices2[4351] = 0.0f;
vertices2[4351] = 0.5f;
// point 4, upper right corner of top
vertices2[4356] = 0.5f;
vertices2[4357] = 1.0f;
vertices2[4358] = 0.5f;
// point 5, lower right corner of top
vertices2[4362] = 0.5f;
vertices2[4363] = 1.0f;
vertices2[4364] = -0.5f;
// point 6, lower left corner of top
vertices2[4368] = -0.5f;
vertices2[4369] = 1.0f;
vertices2[4370] = -0.5f;
// point 7, upper left corner of top
vertices2[4374] = -0.5f;
vertices2[4375] = 1.0f;
vertices2[4376] = 0.5f;
// color
for (int i = 4335; i < 4380; i = i + 6) {
vertices2[i] = 0.75f;
vertices2[i + 1] = 0.55f;
vertices2[i + 2] = 0.1f;
}
// multiply each x, z location coordinate of cylinder by scalar
// to scale the cylinder down to fit inside cube
for (int i = 0; i < 4332; i = i + 6)
{
vertices2[i] = vertices2[i] * 0.375f;
// vertices2[i + 1] = vertices2[i + 1] * 0.375f;
vertices2[i + 2] = vertices2[i + 2] * 0.375f;
}
return vertices2;
}
// ********* CYLINDER ************ //
// generates indices for the above vertices array to draw a cylinder
GLuint* Cylinder::generateTriangles()
{
GLuint p1, p2, p3, p4;
// array to hold indices (3 vertices per triangle, 1440 triangles total for cylinder)
static GLuint indices2[4356]; // first 4320 for cylinder, last 36 for cube
int j = 2;
for (int i = 0; i < 1080; i = i + 3)
{
// four corners of rectangle on side of cylinder
p1 = j; // lower left corner
p2 = j + 360; // upper left corner
p3 = j + 361; // upper right corner
p4 = j + 1; // lower right corner
// when angle reaches 359 degrees, the point at 0 degrees is used
if (i == 1077) {
p3 = 362;
p4 = 2;
}
// triangles that make up bottom circle
indices2[i] = 0;
indices2[i + 1] = p1;
indices2[i + 2] = p4;
// triangles that make up top circle
indices2[i + 1080] = 1;
indices2[i + 1081] = p2;
indices2[i + 1082] = p3;
// two triangles that make up side section (1 / 360) of cylinder
// triangle one
indices2[i + 2160] = p1;
indices2[i + 2161] = p2;
indices2[i + 2162] = p3;
// triangle two
indices2[i + 3240] = p1;
indices2[i + 3241] = p3;
indices2[i + 3242] = p4;
j = j + 1;
}
// ********* CUBE ************ //
int offset2 = 722;
// base triangles
indices2[4320] = 0 + offset2;
indices2[4321] = 1 + offset2;
indices2[4322] = 3 + offset2;
indices2[4323] = 1 + offset2;
indices2[4324] = 2 + offset2;
indices2[4325] = 3 + offset2;
// left face triangles
indices2[4326] = 2 + offset2;
indices2[4327] = 3 + offset2;
indices2[4328] = 6 + offset2;
indices2[4329] = 3 + offset2;
indices2[4330] = 6 + offset2;
indices2[4331] = 7 + offset2;
// top face triangles
indices2[4332] = 4 + offset2;
indices2[4333] = 5 + offset2;
indices2[4334] = 7 + offset2;
indices2[4335] = 5 + offset2;
indices2[4336] = 6 + offset2;
indices2[4337] = 7 + offset2;
// right face triangles
indices2[4338] = 0 + offset2;
indices2[4339] = 1 + offset2;
indices2[4340] = 5 + offset2;
indices2[4341] = 0 + offset2;
indices2[4342] = 4 + offset2;
indices2[4343] = 5 + offset2;
// front face triangles
indices2[4344] = 1 + offset2;
indices2[4345] = 2 + offset2;
indices2[4346] = 6 + offset2;
indices2[4347] = 1 + offset2;
indices2[4348] = 5 + offset2;
indices2[4349] = 6 + offset2;
// back face triangles
indices2[4350] = 0 + offset2;
indices2[4351] = 3 + offset2;
indices2[4352] = 4 + offset2;
indices2[4353] = 3 + offset2;
indices2[4354] = 4 + offset2;
indices2[4355] = 7 + offset2;
return indices2;
}
这是我的主要 cpp 文件:
#include <iostream> // cout, cerr
#include <glad/glad.h> // GLAD library
#include <GLFW/glfw3.h> // GLFW library
#include <cstdlib> // EXIT_FAILURE
// GLM Math Headers
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "shaderClass.h" // shader class
#include "VAO.h" // vertex array object
#include "VBO.h" // vertex buffer object
#include "EBO.h" // element buffer object (for indices)
#include "cylinderClass.h"
#include "cubeClass.h"
using namespace std;
// Variables for window width, height, and title
const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 800;
const char* const WINDOW_TITLE = "CS 330 Project";
// can't be calculated with sizeof(), because vertices and indices are pointers
const int SIZE_OF_VERTICES = 4380; // (722 vertices for cylinder + 8 vertices for cube) * 6 elements per vertex
const int SIZE_OF_INDICES = 4356; // total number of triangles for both shapes:
// (1440 for cylinder + 12 for cube) = 1452
// 1452 * 3 vertices per triangle = 4356
// cube with cylindrical cutout
// create instance of Cylinder class to generate vertices and indices
Cylinder* cylinder = new Cylinder();
// Coordinates of vertices of cylinder [number of vertices (722) x 3 = 2166, doubled for color coordinates]
GLfloat* vertices = cylinder->generateVertices();
// Indices of coordinates used to create triangles
GLuint* indices = cylinder->generateTriangles();
// main function. Entry point to the OpenGL program
int main()
{
// initialize GLFW
glfwInit();
// configure GLFW (version and type of profile)
// tell GLFW which version is being used (3.3)
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
// tell GLFW that CORE profile is being used (only have modern functions)
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// create GLFWwindow object
GLFWwindow* window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE, NULL, NULL);
// error check and message if window fails to create
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
// tell GLFW to use the window in the current context
glfwMakeContextCurrent(window);
// load GLAD so it configures OpenGL in the window
gladLoadGL();
// specify the viewport of OpenGL in the window
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
// set the background color of the window to black
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// generate shader object using shaders default.vert and default.frag
Shader shaderProgram("default.vert", "default.frag");
// generate vertex array object and bind it
VAO VAO1;
VAO1.Bind();
// generate vertex buffer object and link it to vertices
VBO VBO1(vertices, SIZE_OF_VERTICES);
// generate element buffer object and link it to indices
EBO EBO1(indices, SIZE_OF_INDICES);
// link VBO attributes (location coordinates and colors) to VAO
VAO1.LinkAttrib(VBO1, 0, 3, GL_FLOAT, 6 * 4, (void*)0);
VAO1.LinkAttrib(VBO1, 1, 3, GL_FLOAT, 6 * 4, (void*)(3 * 4));
// unbind all to prevent accidentally modifying them
VAO1.Unbind();
VBO1.Unbind();
EBO1.Unbind();
// gets ID of uniform called "scale"
GLuint uniID = glGetUniformLocation(shaderProgram.ID, "scale");
// enable depth buffer
glEnable(GL_DEPTH_TEST);
// main while loop
while (!glfwWindowShouldClose(window))
{
// set the background color of the window to black
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// clean the back buffer and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// tell OpenGL which shader program we want to use
shaderProgram.Activate();
// initialize matrices so they are not null
glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view = glm::mat4(1.0f);
glm::mat4 proj = glm::mat4(1.0f);
// assign different transformations to each matrix
// scales and rotates the cube with cylindrical hole 45 degrees about the y-axis
//model = glm::scale(model, glm::vec3(1.0f, 1.0f, 1.0f));
model = glm::rotate(model, glm::radians(45.0f), glm::vec3(0.0f, 1.0f, 0.0f));
// moves the camera up 0.5 and back 5.0
view = glm::translate(view, glm::vec3(0.0f, -0.5f, -5.0f));
// draws the cylinder with field of view 45 degrees, aspect ration width/height, near plane at 0.1, far plane at 100
proj = glm::perspective(glm::radians(45.0f), (float)(WINDOW_WIDTH / (float)WINDOW_HEIGHT), 0.1f, 100.0f);
// outputs matrices into the vertex shader
int modelLoc = glGetUniformLocation(shaderProgram.ID, "model");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
int viewLoc = glGetUniformLocation(shaderProgram.ID, "view");
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
int projLoc = glGetUniformLocation(shaderProgram.ID, "proj");
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(proj));
// assigns a value to the uniform (must be done after activating the shader program)
glUniform1f(uniID, 0.5f);
// bind the VAO so OpenGL knows to use it
VAO1.Bind();
// draw primitives (triangles), number of indices, datatype of indices, index of indices
glDrawElements(GL_TRIANGLES, SIZE_OF_INDICES / 3, GL_UNSIGNED_INT, 0);
// for testing
// glDrawElements(GL_POINTS, SIZE_OF_INDICES, GL_UNSIGNED_INT, 0);
// swap the back buffer with the front buffer
glfwSwapBuffers(window);
// take care of all GLFW events
glfwPollEvents();
}
// delete all the objects we've created
VAO1.Delete();
VBO1.Delete();
EBO1.Delete();
shaderProgram.Delete();
// delete window before ending the program
glfwDestroyWindow(window);
// terminatee the GLFW before ending the program
glfwTerminate();
return 0;
}
我已经运行了调试器并检查了 vertices2 和 indices2 数组值是否正确分配,它们似乎都正确分配了。
单独类中的立方体本身使用main.cpp中的相同逻辑正确呈现,因此我认为问题不在于与OpenGL相关的代码。
当我运行程序来绘制点而不是绘制三角形时,它会绘制圆的中心和底部圆的前半部分(0 到 180 度)。(注意:圆柱体旋转,正 z 轴指向您,因此很难分辨渲染了哪些点。
答: 暂无答案
评论
abs()
fabs()
glDrawArrays
/ 3