user14621354
user14621354

Reputation:

GLFW (opengl) window closes when hovering mouse over the white window top handle

Whenever I am rendering a window for a test raytracer in opengl with the GLFW library for C++ , the window works fine up to a point where if I just hover , not outside of the window , but over its white top handle , whether it is to move the window or minimize it , the window and the whole program just crashes with no error output , even tho I am not using any try-catch block or any noexcept keyword inside the whole program , and I'm using std::shared_ptr for pointer management.

Here's the main function (variables written in caps that aren't from glfw or opengl are defined in another file , but not initialized):

int main() {
  if (!glfwInit()) ErrorExec("Couldn't init GLFW Engine");

  glfwWindowHint(GLFW_RESIZABLE,GLFW_FALSE);
  MAIN_WINDOW = glfwCreateWindow(WIDTH,HEIGHT,"Raytracer test" , NULL , NULL);
  if (!MAIN_WINDOW) ErrorExec("Couldn't init Window");
  glfwMakeContextCurrent(MAIN_WINDOW);

  _InitGlobalVars();
  _SetupMainPixels();
  _SetupSkyboxPixels();
  _SetupScene();

  glfwSetCursorPosCallback(MAIN_WINDOW,mousePositionCallback);

  while(!glfwWindowShouldClose(MAIN_WINDOW)) {
      _UpdateKeyboardInput();

      glClear(GL_COLOR_BUFFER_BIT);
      RenderScene(MAIN_SCENE,RAY_BOUNCE_COUNT);
      glDrawPixels(WIDTH,HEIGHT,GL_RGB,GL_UNSIGNED_BYTE,MAIN_PIXELS);

      glfwSwapBuffers(MAIN_WINDOW);
      glfwPollEvents();
};

  glfwTerminate();
  std::cout << "Exited ok!" << std::endl;
  return 1;
};

And here's the raytracing algorithm:

#pragma once

#include <vector>
#include <iostream>
#include <thread>
#include <memory>

#include "./Settings.hpp"
#include "./Vec3.hpp"
#include "./MathFunctions.hpp"
#include "./Pixels.hpp"
#include "./ErrorHandler.hpp"
#include "./Abstract.hpp"
#include "./Objects.hpp"
#include "./Scene.hpp"
#include "./GlobalVars.hpp"

struct ClosestReturn {
    Object* obj = nullptr;
    float dist = -1;
    int obj_index = -1;
};

//SCOPE
ClosestReturn findNearestObject(Ray& ray , Scene* scene);
Color colorAtScene(Ray& ray , Object& objHit , Vec3& hitPos , Scene* scene);
Color colorAtSkybox(Vec3& dir);
Color raytraceScene(Ray& ray , Scene* scene , float depth);
void renderScenePart(Scene* scene , unsigned int maxD , unsigned int minx , unsigned int miny , unsigned int maxx , unsigned int maxy , float AR);
void RenderScene(Scene* scene , int maxD);
//SCOPE

ClosestReturn findNearestObject(Ray& ray , Scene* scene) {
    Object* objHit = nullptr;
    float distMin = -1;

    int k = 0 , index = 0;

    for (Object* obj : scene->objects) {
        float dist = obj->getIntersection(ray);

        if (obj->isHittable() && dist>SURF_DIST && (objHit==nullptr || dist < distMin)) {
            distMin = dist;
            objHit = obj;
            index = k;
        };
        k++;
    };

    return {objHit , distMin , index};
};

Color colorAtScene(Ray& ray , Object* objHit , Vec3& hitPos , Scene* scene) {
    Material mat = objHit->getMaterial();
    hitPos = hitPos + (objHit->getNormal(hitPos,ray.dir) * (-abs(SURF_DIST)));
    Vec3 col = mat.col * mat.amb;
    for (Light* light : scene->lights) {
        Ray toLight = Ray(hitPos , (light->pos - hitPos).normalize());
        Vec3 normal = objHit->getNormal(hitPos,toLight.dir);
        ClosestReturn nearest = findNearestObject(toLight , scene);
        if (nearest.dist<0 && nearest.obj==nullptr) {
            //Light equation
            col = (col + (light->col * mat.diff * std::max(normal * toLight.dir,0.0f * static_cast<float>((float)1/LIGHT_SOFTNESS)) * static_cast<float>((float)1/(hitPos.distVec(light->pos)*LIGHT_DIST)))).constrainVec(0.0f,255.0f);
        };
    };

    return col.constrainVec(0.0f,255.0f);
};

Color colorAtSkybox(Vec3& dir) {

    // AUX => return (Color(mapVal(dir.x,-1,1,0,255),mapVal(dir.y,-1,1,0,255),mapVal(dir.z,-2,2,0,255)).constrainVec(0.0f,255.0f));

    int v = static_cast<int>(mapVal(static_cast<float>(0.5f + (atan2f(dir.z , dir.x) / (float)(2.0f * PI))),1,0,0,SKYBOX_WIDTH));
    int u = static_cast<int>(mapVal(static_cast<float>(0.5f - (asinf(dir.y) / (float)PI)),1,0,0,SKYBOX_HEIGHT));

    return (Color)GetSkyboxPixel(u,v);
};

Color raytraceScene(Ray& ray , Scene* scene , float depth) {
    depth = constrainVal(depth,0,10);
    Vec3 col = Vec3(0,0,0);

    ClosestReturn nearest = findNearestObject(ray,scene);

    if (nearest.obj==nullptr || nearest.obj_index < 0 || nearest.dist <= 0) return colorAtSkybox(ray.dir);
    float distHit = nearest.dist;
    Object* objHit = nearest.obj;

    Vec3 hitPos = ray.atLength(distHit);
    Vec3 hitNormal = objHit->getNormal(hitPos,ray.dir).normalize();

    col = col + (colorAtScene(ray,objHit,hitPos,scene));

    if (depth > 0) {
        Vec3 new_pos = hitPos + (hitNormal * (abs(SURF_DIST)));
        Vec3 new_dir = ray.dir.normalize().reflect(hitNormal);
        Ray new_ray = Ray(new_pos,new_dir);
        col = col + (raytraceScene(new_ray,scene,(depth-1)) * objHit->getMaterial().ref);
    };

    return ((col + (PIXEL_SKIP * 10)).constrainVec(0.0f,255.0f));
};

void renderScenePart(Scene* scene , unsigned int maxD , unsigned int minx , unsigned int miny , unsigned int maxx , unsigned int maxy , float AR) {
    for (unsigned int wy = miny ; wy < maxy ; wy+=PIXEL_SKIP) {
        float ry = static_cast<float>(mapVal(wy,0,HEIGHT,-1,1));

        for (unsigned int wx = minx ; wx < maxx ; wx+=PIXEL_SKIP) {
            float rx = static_cast<float>(mapVal(wx,0,WIDTH,-1-AR,1+AR));

            Ray shootRay = Ray(scene->camera.pos , Vec3(rx,ry,CAMERA_FOV).normalize().rotate(scene->camera.dir.x , scene->camera.dir.y));
            SetMainPixel(wx,wy,(raytraceScene(shootRay,scene,maxD)).constrainVec(0.0f,255.0f));
        };
        
    };
};

void RenderScene(Scene* scene , unsigned int maxD) {
    unsigned int partWidth = (unsigned int)WIDTH/THREAD_COUNT_SQ;
    unsigned int partHeight = (unsigned int)HEIGHT/THREAD_COUNT_SQ;
    float ar = (float)WIDTH/HEIGHT;

    std::thread threads[THREAD_COUNT];

    int k = 0;
    for (unsigned int y = 0 ; y < THREAD_COUNT_SQ ; y++) {
        for (unsigned int x = 0 ; x < THREAD_COUNT_SQ ; x++) {
            threads[k] = std::thread(renderScenePart,std::ref(scene),maxD,x*partWidth,y*partHeight,x*partWidth + partWidth , y*partHeight + partHeight , ar);
            //threads[k].join();
            k++;
        };
    };

    for (std::thread& t : threads) {
        t.join();
    };
};

This last one is the one whose causing the problem. I'm compiling the main file using g++ Main.cpp -o main.exe -lgdi32 -lopengl32 -lglfw3dll -lglu32 -pthread -Wall -Wextra using the MinGW compiler. Thanks in advance!

Upvotes: 0

Views: 376

Answers (1)

user14621354
user14621354

Reputation:

I think I sort of tracked down what the problem was, thanks to Retired Ninja in the comment section. I reduced the code to just a few lines, forgetting about the mesh system and all that stuff. Apparently, when I grab the window, the main thread seems to sleep until I am done moving it, and in the ray-trace algorithm I am instantiating new threads, so when the main one sleeps, most of the times it doesn't await (aka "join()") for them, and because I am passing pointers to those threads, those seem to fill up the memory and crash. I have added a system to also sleep the working threads while the main one is doing so and it works like a charm!. Now I gotta see how to do it in cuda XD. Nevertheless , thank you all!

Upvotes: 1

Related Questions