EDIT * Ich neu angeordnet die Initialisierungsliste, wie von Much_a_chos vorgeschlagen, so dass das Window-Objekt vor dem Game-Objekt initialisiert wird, sicherzustellen, dass Glew zuerst initialisiert wird. Dies führte jedoch nicht:OpenGL Sigsegv Fehler im Klassenkonstruktor
//Rearranged initialization list
class TempCore
{
public:
TempCore(Game* g) :
win(new Window(800, 800, "EngineTry", false)), gamew(g) {}
~TempCore() { if(gamew) delete gamew; }
...
};
Und hier ist der Code, den ich in der Mesh-Konstruktor geändert, wenn die oben nicht funktioniert:
Mesh::Mesh(Vertex* vertices, unsigned int numVerts)
{
m_drawCount = numVerts;
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK){
exit(-150); //application stops and exits here with the code -150
}
glGenVertexArrays(1, &m_vertexArrayObject);
glBindVertexArray(m_vertexArrayObject);
...
}
Was passiert, wenn ich kompiliert und ausgeführt ist überraschend. Das Programm wird am if(glewInit() != GLEW_OK)
Ich kopiert aus dem Window-Konstruktor. Aus irgendeinem Grund initialisiert glew ordnungsgemäß im Window-Konstruktor (der vor dem Game-Konstruktor aufgerufen wird), aber es kann nicht initialisiert werden, wenn es das zweite Mal im Mesh-Konstruktor aufgerufen wird. Ich gehe davon aus, dass es eine schlechte Praxis ist, mehr als einmal in einem Programm glewInit()
aufzurufen, aber ich denke nicht, dass es scheitern sollte, wenn ich das tat. Weiß jemand, was passieren könnte? Mache ich einen Fehler beim Aufruf von glewInit()
mehr als einmal?
* END OF EDIT
Ich verfolge ein 3D Game Engine Development tutorial und ich habe einen seltsamen Fehler in meinem Code gestoßen, die ich weiter unten zeigen wird. Ich versuche meine eigene Spiel-Engine rein aus pädagogischen Gründen zu machen. Ich verwende Code-Blöcke 13.12 als meine IDE und mingw-w64 v4.0 als meinen Compiler. Ich verwende auch SDL2, glew, Assimp und boost als meine Drittanbieter-Bibliotheken.
Ich entschuldige mich im Voraus für die zahlreichen Code-Extrakte, aber ich fügte hinzu, was ich dachte, was notwendig war, um den Zusammenhang des Fehlers zu verstehen.
Ich habe eine Core
Klasse für mein Spiel-Engine, die die Hauptschleife und Updates und macht dementsprechend hält, als auch die Game
Klasse update()
und render()
Methoden in den Prozess aufrufen. Die Game-Klasse ist als Halter für alle Assets im Spiel gedacht und wird die Basisklasse für alle Spiele sein, die mit der Engine erstellt wurden. Sie enthält also Mesh-, Textur- und Kamera-Referenzen. Die Spielklassen update()
, render()
und input()
Methoden sind alle virtuell, da die Klasse Game
abgeleitet werden soll.
Mein Problem ist: wenn ich das Spiel Membervariable in der Core
Klasse initialisieren, erhalte ich eine SIGSEGV (das heißt Segmentierungsfehler) in dem Mesh
Konstruktor des Objekts an dem glGenVertexArrays
Anruf. Allerdings, wenn ich meine Game
Objekt aus der Core
Klasse und direkt in die Hauptmethode (so änderte ich es von einem Klassenmitglied zu einem einfachen Bereich Variable in der Hauptmethode), zusammen mit den notwendigen Teilen aus der Core
Klasse , dann läuft es perfekt und macht mein rudimentäres Dreieckbeispiel. Dies ist ein Fehler, auf den ich nie gestoßen bin und ich würde jede Hilfe, die ich bekommen kann, sehr schätzen.
Im Folgenden ein Auszug aus meinem morphed Code ist das perfekt und machte das Dreieck lautete:
int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{
Window win(800, 800, "EngineTry", false); //Creates an SDL implemented window with a GL_context
Game* gamew = new Game;
const double frameTime = 1.0/500; //500 = maximum fps
double lastTime = FTime::getTime(); //gets current time in milliseconds
double unprocessedTime = 0.0;
int frames = 0;
double frameCounter = 0;
while(win.isRunning()){
bool _render = false;
double startTime = FTime::getTime();
double passedTime = startTime - lastTime;
lastTime = startTime;
unprocessedTime += passedTime/(double)FTime::SECOND;
frameCounter += passedTime;
while(unprocessedTime > frameTime){
if(!win.isRunning())
exit(0);
_render = true;
unprocessedTime -= frameTime;
FTime::delta = frameTime;
gamew->input();
Input::update();
gamew->update();
if(frameCounter >= FTime::SECOND)
{
std::cout << "FPS: " << frames << std::endl;
frames = 0;
frameCounter = 0;
}
}
if(_render){
RenderUtil::clearScreen(); //simple wrapper to the glClear function
gamew->render();
win.Update();
frames++;
}else{
Sleep(1);
}
}
delete gamew;
return 0;
}
Hier ein Auszug meiner modifizierten Core
Klasse, die nicht (führt den SIGSEGV im Mesh
Konstruktor) funktioniert
class TempCore
{
public:
TempCore(Game* g) :
gamew(g), win(800, 800, "EngineTry", false) {}
~TempCore() { if(gamew) delete gamew; }
void start();
private:
Window win;
Game* gamew;
};
int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{
TempCore m_core(new Game());
m_core.start();
return 0;
}
void TempCore::start()
{
const double frameTime = 1.0/500;
double lastTime = FTime::getTime();
double unprocessedTime = 0.0;
int frames = 0;
double frameCounter = 0;
while(win.isRunning()){
bool _render = false;
double startTime = FTime::getTime();
double passedTime = startTime - lastTime;
lastTime = startTime;
unprocessedTime += passedTime/(double)FTime::SECOND;
frameCounter += passedTime;
while(unprocessedTime > frameTime){
if(!win.isRunning())
exit(0);
_render = true;
unprocessedTime -= frameTime;
FTime::delta = frameTime;
gamew->input();
Input::update();
gamew->update();
if(frameCounter >= FTime::SECOND){
//double totalTime = ((1000.0 * frameCounter)/((double)frames));
//double totalMeasuredTime = 0.0;
std::cout << "Frames: " << frames << std::endl;
//m_frames_per_second = frames;
frames = 0;
frameCounter = 0;
}
}
if(_render){
RenderUtil::clearScreen();
gamew->render();
win.Update();
frames++;
}else{
Sleep(1);
}
}
}
Mesh-Konstruktor, wo die SIGSEGV in der obigen TestCore
Implementierung erfolgt:
Mesh::Mesh(Vertex* vertices, unsigned int numVerts)
{
m_drawCount = numVerts;
glGenVertexArrays(1, &m_vertexArrayObject); //sigsegv occurs here
glBindVertexArray(m_vertexArrayObject);
std::vector<glm::vec3> positions;
std::vector<glm::vec2> texCoords;
positions.reserve(numVerts);
texCoords.reserve(numVerts);
for(unsigned i = 0; i < numVerts; i++){
positions.push_back(vertices[i].pos);
texCoords.push_back(vertices[i].texCoord);
}
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[POSITION_VB]);
glBufferData(GL_ARRAY_BUFFER, numVerts*sizeof(positions[0]), &positions[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[TEXCOORD_VB]);
glBufferData(GL_ARRAY_BUFFER, numVerts*sizeof(texCoords[0]), &texCoords[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBindVertexArray(0);
}
Der Game
Konstruktor, das Mesh
Objekt initialisiert:
Vertex vertices[] = { Vertex(-0.5f, -0.5f, 0, 0, 0),
Vertex(0, 0.5f, 0, 0.5f, 1.0f),
Vertex(0.5f, -0.5f, 0, 1.0f, 0)};
//Vertex is basically a struct with a glm::vec3 for position and a glm::vec2 for texture coordinate
Game::Game() :
m_mesh(vertices, sizeof(vertices)/sizeof(vertices[0])),
m_shader("res\\shaders\\basic_shader"),
m_texture("res\\textures\\mist_tree.jpg")
{
}
Die Window
Klasse Konstruktor, glew
initialisiert:
Window::Window(int width, int height, const std::string& title, bool full_screen) :
m_fullscreen(full_screen)
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
//SDL_Window* in private of class declaration
m_window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
//SDL_GLContext in private of class declaration
m_glContext = SDL_GL_CreateContext(m_window);
std::cout << "GL Version: " << glGetString(GL_VERSION) << std::endl;
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK || !glVersionAbove(3.0)){
std::cerr << "Glew failed to initialize...\n";
exit(-150);
}
}
@much_a_chos danke nochmal für die Hilfe – searchnot
Und @ vu1p3n0x sowie – searchnot
Sorry für die Verzögerung der Antwort, froh, dass Sie das Problem gefunden haben und wir Ihnen helfen konnten! – lordjohncena