- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我一直在研究我的第一个 opengl、glfw 和 glm 项目(在 cmake 中),同时遵循在线教程,我想开始将我的代码组织到特定的类中以执行特定的任务(例如用于组织着色器的模型类和顶点);然而,一旦我组织了我的代码,我就遇到了两个问题。
首先,在我终于摆脱了代码中的所有语法错误之后,我遇到了两个单独的类(一个是静态类)的编译错误 'class' type redefinition
两次。我在唯一的头文件 (zachos.h) 的最顶部有 #pragma once
,所以我不知道这里的问题是什么。为什么我的代码(见下文)会抛出这个错误?列出的确切错误消息是:
zachos.cpp(94): error C2011: 'zachos::Model': 'class' type redefinition
zachos.h(53): note: see declaration of 'zachos::Model'
zachos.cpp(173): error C2011: 'zachos::Mainframe': 'class' type redefinition
zachos.h(84): note: see declaration of 'zachos::Mainframe'
其次,我需要从该类的静态函数内部初始化一个静态成员对象。我使用 static Model mModel;
在我的头文件 (zachos.h) 中定义了对象,然后在我的代码文件 (zachos.cpp) 中重新定义了它,最后我在静态函数中创建了类使用复制操作符 Model model(gVertexBufferData, gColorBufferData); mModel = 模型;
。我对这个工作有严重的怀疑(因为复制运算符只做浅拷贝),我不知道如何使用指针在函数内定义 mModel(我相信我必须使用 delete
以某种方式)。这种形式的对象初始化是否有问题,有没有更好的方法?
代码(所有文件都在同一个目录下并被CMake引用,如果需要我也可以提供CMakeLists.txt文件):
zachos.h:
#pragma once
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <sstream>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctime>
/*
Namespace that contains all basic codestuff for zachos.
*/
namespace zachos {
// Constant data
static const std::string DATA_DEF("#version 330 core\nlayout(location = 0) in vec3 vertexPosition_modelspace;\nlayout(location = 1) in vec3 vertexColor;\nout vec3 fragmentColor;\n\nuniform mat4 MVP;\n\nvoid main()\n{\n\tgl_Position = MVP * vec4(vertexPosition_modelspace, 1);\n\t\n\tfragmentColor = vertexColor;\n}\n\n#version 330 core\nin vec3 fragmentColor;\nout vec3 color;\n\nvoid main()\n{\n\tcolor = fragmentColor;\n}");
std::vector<GLfloat> gVertexBufferData = {
-1.0f, -1.0f, -1.0f, // triangle 1 : begin
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f, // triangle 1 : end
1.0f, 1.0f, -1.0f, // triangle 2 : begin
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f, // triangle 2 : end
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};
std::vector<GLfloat> gColorBufferData(12 * 3 * 3, 0);
/*
Enum of all possible error codes for the program to return on its own
*/
enum ErrorCodes {
SUCCESS,
GLFW_INIT_FAIL,
GLFW_WINDOW_CREATION_FAIL,
GLAD_INIT_FAIL,
WINDOW_FAIL
};
/*
Error callback function for glfw. Nothing special.
*/
void errorCallback(int error, const char* description);
/*
Load shaders function for convenience. Used especially by the Model class.
*/
GLuint loadShaders(std::string shaders);
/*
Class for creating models; it holds a VBO, CBO, and programID.
*/
class Model {
public:
std::vector<GLfloat> mVertexBufferData;
std::vector<GLfloat> mColorBufferData;
GLuint VBO;
GLuint CBO;
GLuint programID;
glm::mat4 model;
/*
Default Constructor. Must contain all vertex and color data from the get go.
*/
Model(std::vector<GLfloat> vertexBufferData, std::vector<GLfloat> colorBufferData);
/*
Model update() function, called every "tick"
*/
virtual void update();
/*
Model draw() function, called to draw the model
*/
virtual void draw();
};
/*
Wrapper class of the main window for handling events and perspective.
*/
class Mainframe {
public:
static GLFWwindow* window;
static glm::mat4 projection;
static glm::mat4 view;
static Model mModel;
static int i;
// Event functions
static void framebufferSizeCallback(GLFWwindow* window, int width, int height);
static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
/*
Class initialization function.
*/
static int init();
/*
Frame by frame drawing function.
*/
static int draw();
/*
Get whether the window should close or not
*/
static bool shouldClose();
};
}
zachos.cpp:
#include "zachos.h"
namespace zachos {
void errorCallback(int error, const char* description) {
fprintf(stderr, "GLFW error %d: %s\n", error, description);
}
GLuint loadShaders(std::string shaders) {
// Create the shaders
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Read the shader code
std::string shaderCode;
std::string vertexShaderCode;
std::string fragmentShaderCode;
//std::ifstream shaderStream(file_path, std::ios::in);
if (/*shaderStream.is_open()*/ true) {
//std::stringstream sstr;
//sstr << shaderStream.rdbuf();
//shaderCode = sstr.str();
shaderCode = shaders;
//shaderStream.close();
size_t val = shaderCode.find("#version", 8);
vertexShaderCode = shaderCode.substr(0, val);
fragmentShaderCode = shaderCode.substr(val);
}
else {
//printf("Impossible to open \"%s\". Are you in the right directory? Don't forget to read the FAQ!\n", file_path);
getchar();
return 0;
}
GLint result = GL_FALSE;
int infoLogLength;
// Compile Vertex Shader
char const * vertexSourcePointer = vertexShaderCode.c_str();
glShaderSource(vertexShaderID, 1, &vertexSourcePointer, nullptr);
glCompileShader(vertexShaderID);
// Check Vertex Shader
glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &result);
glGetShaderiv(vertexShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 0) {
std::vector<char> vertexShaderErrorMessage(infoLogLength + 1);
glGetShaderInfoLog(vertexShaderID, infoLogLength, nullptr, &vertexShaderErrorMessage[0]);
printf("%s\n", &vertexShaderErrorMessage[0]);
}
// Compile Fragment Shader
char const * fragmentSourcePointer = fragmentShaderCode.c_str();
glShaderSource(fragmentShaderID, 1, &fragmentSourcePointer, nullptr);
glCompileShader(fragmentShaderID);
// Check Fragment Shader
glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &result);
glGetShaderiv(fragmentShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 0) {
std::vector<char> fragmentShaderErrorMessage(infoLogLength + 1);
glGetShaderInfoLog(fragmentShaderID, infoLogLength, nullptr, &fragmentShaderErrorMessage[0]);
printf("%s\n", &fragmentShaderErrorMessage[0]);
}
// Link the program
printf("Linking program\n");
GLuint programID = glCreateProgram();
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
glLinkProgram(programID);
// Check the program
glGetProgramiv(programID, GL_LINK_STATUS, &result);
glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 0) {
std::vector<char> programErrorMessage(infoLogLength + 1);
glGetProgramInfoLog(programID, infoLogLength, nullptr, &programErrorMessage[0]);
printf("%s\n", &programErrorMessage[0]);
}
glDetachShader(programID, vertexShaderID);
glDetachShader(programID, fragmentShaderID);
glDeleteShader(vertexShaderID);
glDeleteShader(fragmentShaderID);
return programID;
}
class Model {
public:
std::vector<GLfloat> mVertexBufferData;
std::vector<GLfloat> mColorBufferData;
GLuint VBO;
GLuint CBO;
GLuint programID;
glm::mat4 model = glm::mat4(1.0f);
Model(std::vector<GLfloat> vertexBufferData, std::vector<GLfloat> colorBufferData) {
mVertexBufferData = vertexBufferData;
mColorBufferData = colorBufferData;
// Generate 1 buffer, put the resulting identifier in vertexbuffer
glGenBuffers(1, &VBO);
// The following commands will talk about our 'vertexbuffer' buffer
glBindBuffer(GL_ARRAY_BUFFER, VBO);
// Give our vertices to OpenGL.
glBufferData(GL_ARRAY_BUFFER, sizeof(mVertexBufferData), &mVertexBufferData.front(), GL_STATIC_DRAW);
glGenBuffers(1, &CBO);
glBindBuffer(GL_ARRAY_BUFFER, CBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(mColorBufferData), &mColorBufferData.front(), GL_STATIC_DRAW);
// Create and compile our GLSL program from the shaders
GLuint programID = loadShaders(zachos::DATA_DEF);
glUseProgram(programID);
}
virtual void update() {
for (int v = 0; v < 12 * 3; v++) {
mColorBufferData[3 * v + 0] = (float)std::rand() / RAND_MAX;
mColorBufferData[3 * v + 1] = (float)std::rand() / RAND_MAX;
mColorBufferData[3 * v + 2] = (float)std::rand() / RAND_MAX;
}
glBufferData(GL_ARRAY_BUFFER, sizeof(mColorBufferData), &mColorBufferData.front(), GL_STATIC_DRAW);
}
virtual void draw() {
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, CBO);
glVertexAttribPointer(
1, // attribute. No particular reason for 1, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Setup some 3D stuff
glm::mat4 mvp = Mainframe::projection * Mainframe::view * model;
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &mvp[0][0]);
// Draw the array
glDrawArrays(GL_TRIANGLES, 0, mVertexBufferData.size() / 3);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
}
};
class Mainframe {
public:
static GLFWwindow* window;
static glm::mat4 projection;
static glm::mat4 view;
static Model mModel;
static int i;
static void framebufferSizeCallback(GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
glm::perspective(glm::radians(45.0f), (float)width / (float)height, 0.1f, 100.0f);
}
static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
switch (key) {
case GLFW_KEY_ESCAPE:
break;
}
}
static int init() {
// Initialize GLFW
int glfwInitRes = glfwInit();
if (!glfwInitRes) {
fprintf(stderr, "Unable to initialize GLFW\n");
return GLFW_INIT_FAIL;
}
// Set GLFW flags. Not exactly sure if these are needed.
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
// Attempt to create the main window.
window = glfwCreateWindow(1280, 720, "InitGL", nullptr, nullptr);
if (!window) {
fprintf(stderr, "Unable to create GLFW window\n");
glfwTerminate();
return GLFW_WINDOW_CREATION_FAIL;
}
glfwMakeContextCurrent(window);
// Initialize GLAD and OpenGL
int gladInitRes = gladLoadGL();
if (!gladInitRes) {
fprintf(stderr, "Unable to initialize glad\n");
glfwTerminate();
return GLAD_INIT_FAIL;
}
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwSetFramebufferSizeCallback(window, framebufferSizeCallback);
glfwSetKeyCallback(window, keyCallback);
// Create da CUBANGLÉ
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
for (int v = 0; v < 12 * 3; v++) {
gColorBufferData[3 * v + 0] = (float)std::rand() / RAND_MAX;
gColorBufferData[3 * v + 1] = (float)std::rand() / RAND_MAX;
gColorBufferData[3 * v + 2] = (float)std::rand() / RAND_MAX;
}
Model model(gVertexBufferData, gColorBufferData);
mModel = model;
// Set the clear color
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
projection = glm::perspective(glm::radians(45.0f), (float)1280 / (float)720, 0.1f, 100.0f);
view = glm::lookAt(
glm::vec3(4, 3, 3), // Camera is at (4,3,3), in World Space
glm::vec3(0, 0, 0), // and looks at the origin
glm::vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down)
);
i = 60;
return SUCCESS;
}
static int draw() {
if (i <= 0) {
view = glm::lookAt(
glm::vec3(3 + 2 * (float)std::rand() / RAND_MAX, 3 + 2 * (float)std::rand() / RAND_MAX, 3 + 2 * (float)std::rand() / RAND_MAX), // Camera is at (), in World Space
glm::vec3(0, 0, 0), // and looks at the origin
glm::vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down)
);
mModel.update();
i = 60;
}
i--;
mModel.draw();
glfwSwapBuffers(window);
}
static bool shouldClose() {
return glfwWindowShouldClose(window);
}
};
}
主要.cpp:
#include "zachos.h"
/*
I'm pretty sure you know what this function is.
*/
int main(int argc, char* argv[]) {
// Seed the random number generator
std::srand(static_cast<unsigned int>(std::time(nullptr)));
// Implement Mainframe for shorthand
using zachos::Mainframe;
// set GLFW error callback function
glfwSetErrorCallback(zachos::errorCallback);
// Run the window initiazation function
int value = Mainframe::init();
if (!value) {
// Return if failed
return value;
}
// Main loop
while (!Mainframe::shouldClose()) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glfwPollEvents();
// Actually does the hard work
Mainframe::draw();
}
glfwTerminate();
return zachos::SUCCESS;
}
我还知道此代码中存在的其他可能问题。如果愿意,您也可以提及它们,但我的主要问题围绕这两个主要问题展开。
最佳答案
您似乎两次声明类“Model”和“Mainframe”,一次在 zachos.h 中,一次在 zachos.cpp 中。您应该在 header 中声明类
class Model {
public:
virtual void update();
...
}
然后在cpp中定义类
void Model::update() {
...
}
header 告诉编译器类的结构和内容,cpp 提供函数的实际作用。
关于你的第二点,我不确定你正在尝试实现什么,所以不知道是否有更好的方法。
关于c++ - (2 个问题) 'class' 类型重定义(即使使用#pragma once),以及静态函数内部的静态成员对象初始化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58715694/
在complier.h中有一个宏定义如下: # define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0) 但是这里我有一个问题,就是哪里
curl_easy_setopt 的选项在哪里?定义?我试图寻找 CURLOPT_VERBOSE 和其他一些整数值,但这些似乎没有在 curl.h 中明确定义。 最佳答案 第 792 行: #ifde
我确实有一个如下所示的类(class): //.h file class __declspec(dllimport) MyClass { public: //stuff pri
作者: zhuwenzhuang, 2024.05.08. 阅读前假设读者熟悉数据库使用,了解 SQL 的语法和关系算子的大概含义, 能通过 EXPLAIN 命令查看数据库执行计划. 0 前言
我似乎无法找到是否可以声明一个 header 对象以便在响应 header 中重用它,有一些示例定义了响应模式的对象,但它不会转置为响应 header 。我只设法制作了一个可重用的响应对象,如下所示:
css 选择器 * + * 实际上是什么意思?当您执行检查元素时,您可以在谷歌浏览器的控制台中看到它。在我看来,这似乎是对 "Every second child"应用一种风格,但仍然想确定。谁能帮我
我试图弄清楚基本的IO Haskell 函数是定义好的,所以我使用了this reference我到了putChar函数定义: putChar :: Char -> IO () putChar
我得到了一个自动生成的文件,该文件定义了程序集属性,我正在尝试理解内容。 [assembly: global::System.Runtime.Versioning.TargetFrameworkAtt
This文档演示了如何检查变量是否先前已在 gnuplot 脚本中定义。 文档中的示例: a = 10 if (exists("a")) print "a is defined" if (!exist
好吧,这是一个相当基本的问题:我正在关注 SICP 视频,我对 define、let 和 之间的区别有点困惑设置!. 1) 根据 Sussman 在视频中的说法,define 只允许为变量附加一个值一
我一直在尝试定义一个包含只能具有以下三个值之一的字段的 XSD: 绿色 红色 蓝色 本质上,我想在架构级别定义严格的枚举。 我的第一次尝试似乎是错误的,我不确定修复它的“正确”方法。
有人可以定义“POCO”到底是什么意思吗?我越来越频繁地遇到这个术语,我想知道它是否仅与普通类有关还是意味着更多? 最佳答案 “普通旧式 C# 对象” 只是一个普通的类,没有描述基础结构问题或域对象不
在我经常看到的一些django模型中 myfield = models.CharField(_('myfield')) class_name = models.CharField(_('Type'),
每当 BOOL 数据类型不容易预定义时,我都会使用以下定义进行 boolean 运算, typedef unsigned char BOOL; (由于内存使用)。 我意识到出于性能原因,使用本地总线宽
l_ABC_BEANVector = utilRemote.fnGetVector("ABC_COVBEANVector"); 编码的含义是什么?任何帮助,我真的很感激。谢谢 最佳答案 唯一可以肯定地
我正在使用 javacc 开发一个项目,我遇到问题并需要一些帮助,我的文件中有这样的内容: STRING COPYRIGHT (C) 2003, 2004 SYNOPSYS, INC.; 我为单词 S
我想弄清楚基本的 IO定义了 Haskell 函数,所以我使用了 this reference然后我到了 putChar函数定义: putChar :: Char -> IO () putCha
我在具体类中使用 @property 定义 getter 时遇到问题。这是Python代码: from abc import ABCMeta, abstractproperty class abstr
我正在为大学用 C 语言编写一个小游戏,但我陷入了困境。我(在头文件中)有这个结构: typedef struct{ game_element field[MAX_ROWS][MAX_COLU
我一直在 .l 文件中创建标记定义。由于数据集数量庞大,它变得有点乏味。有没有办法读取文件中的所有单词,例如包含所有名词的 noun.txt 并给所有名词一个标记。 基本上,我想自动化这部分: %%
我是一名优秀的程序员,十分优秀!