174 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			174 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
/*
 | 
						|
 * --------------------------------------------------------------------------
 | 
						|
 *
 | 
						|
 *    ___________                      ____   ____.__                    
 | 
						|
 *    \__    ___/______________________\   \ /   /|__| _________________ 
 | 
						|
 *      |    |_/ __ \_  __ \_  __ \__  \\   Y   / |  |/  ___/  _ \_  __ \
 | 
						|
 *      |    |\  ___/|  | \/|  | \// __ \\     /  |  |\___ (  <_> )  | \/
 | 
						|
 *      |____| \___  >__|   |__|  (____  /\___/   |__/____  >____/|__|   
 | 
						|
 *                 \/                  \/                 \/             
 | 
						|
 * 
 | 
						|
 *                               TerraVisor
 | 
						|
 *                     Dynamic Terrain Visualization
 | 
						|
 * 
 | 
						|
 * --------------------------------------------------------------------------
 | 
						|
 * Author: Jack Christensen
 | 
						|
 * Version: 0.0.1
 | 
						|
 *
 | 
						|
 * Description:
 | 
						|
 * TerraVisor is a dynamic terrain visualization tool that uses real-world elevation
 | 
						|
 * data to render high-fidelity 3D landscapes. It leverages tessellation shaders
 | 
						|
 * to provide detailed and adaptive terrain rendering.
 | 
						|
 *
 | 
						|
 * License:
 | 
						|
 * This project is licensed under the GNU General Public License v3.0.
 | 
						|
 * See the COPYING file for more details.
 | 
						|
 */
 | 
						|
 | 
						|
#include <GL/glew.h>
 | 
						|
#include <GLFW/glfw3.h>
 | 
						|
#include <iostream>
 | 
						|
#include <string>
 | 
						|
#include <sstream>
 | 
						|
#include <chrono>
 | 
						|
#include <thread>
 | 
						|
 | 
						|
#include <imgui.h>
 | 
						|
#include <imgui_impl_glfw.h>
 | 
						|
#include <imgui_impl_opengl3.h>
 | 
						|
 | 
						|
#include <FreeImage.h>
 | 
						|
 | 
						|
#include "config.h"
 | 
						|
#include "callbacks.h"
 | 
						|
#include "scene.h"
 | 
						|
 | 
						|
namespace {
 | 
						|
 | 
						|
const int kInitWindowWidth = 1280;
 | 
						|
const int kInitWindowHeight = 720;
 | 
						|
 | 
						|
const int kTargetFps = 60;
 | 
						|
const auto kFrameDuration = std::chrono::milliseconds(1000 / kTargetFps);
 | 
						|
 | 
						|
bool InitializeGlfw() {
 | 
						|
    if (!glfwInit()) {
 | 
						|
        std::cerr << "Failed to initialize GLFW" << std::endl;
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
GLFWwindow* CreateGlfwWindow() {
 | 
						|
#ifdef _DEBUG
 | 
						|
    glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
 | 
						|
#endif
 | 
						|
 | 
						|
    std::stringstream ss;
 | 
						|
    ss << PROJECT_NAME << " " << PROJECT_VERSION_MAJOR << "." << PROJECT_VERSION_MINOR << "." << PROJECT_VERSION_PATCH;
 | 
						|
 | 
						|
    std::string title = ss.str();
 | 
						|
    GLFWwindow* window = glfwCreateWindow(kInitWindowWidth, kInitWindowHeight, title.c_str(), nullptr, nullptr);
 | 
						|
    if (!window) {
 | 
						|
        std::cerr << "Failed to create GLFW window" << std::endl;
 | 
						|
        glfwTerminate();
 | 
						|
        return nullptr;
 | 
						|
    }
 | 
						|
 | 
						|
    glfwMakeContextCurrent(window);
 | 
						|
    return window;
 | 
						|
}
 | 
						|
 | 
						|
bool InitializeGlew() {
 | 
						|
    glewExperimental = GL_TRUE;
 | 
						|
    if (glewInit() != GLEW_OK) {
 | 
						|
        std::cerr << "Failed to initialize GLEW" << std::endl;
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
void InitializeImGui(GLFWwindow* window) {
 | 
						|
    IMGUI_CHECKVERSION();
 | 
						|
    ImGui::CreateContext();
 | 
						|
    ImGui_ImplGlfw_InitForOpenGL(window, true);
 | 
						|
    ImGui_ImplOpenGL3_Init("#version 150");
 | 
						|
}
 | 
						|
 | 
						|
void CleanupImGui() {
 | 
						|
    ImGui_ImplOpenGL3_Shutdown();
 | 
						|
    ImGui_ImplGlfw_Shutdown();
 | 
						|
    ImGui::DestroyContext();
 | 
						|
}
 | 
						|
 | 
						|
void MainLoop(GLFWwindow* window, Scene& scene) {
 | 
						|
    auto last_frame_time = std::chrono::high_resolution_clock::now();
 | 
						|
 | 
						|
    while (!glfwWindowShouldClose(window)) {
 | 
						|
        auto frame_start = std::chrono::high_resolution_clock::now();
 | 
						|
 | 
						|
        scene.Idle();
 | 
						|
        scene.Display(window);
 | 
						|
        
 | 
						|
        glfwPollEvents();
 | 
						|
 | 
						|
        auto frame_end = std::chrono::high_resolution_clock::now();
 | 
						|
        auto frame_duration = frame_end - frame_start;
 | 
						|
 | 
						|
        if (frame_duration < kFrameDuration) {
 | 
						|
            std::this_thread::sleep_for(kFrameDuration - frame_duration);
 | 
						|
        }
 | 
						|
 | 
						|
        auto current_frame_time = std::chrono::high_resolution_clock::now();
 | 
						|
        auto actual_frame_duration = std::chrono::duration_cast<std::chrono::milliseconds>(current_frame_time - last_frame_time).count();
 | 
						|
 | 
						|
        last_frame_time = current_frame_time;
 | 
						|
    }
 | 
						|
} 
 | 
						|
 | 
						|
void TestLoop(GLFWwindow* window, Scene& scene) {
 | 
						|
    auto start = std::chrono::steady_clock::now();
 | 
						|
 | 
						|
    while (!glfwWindowShouldClose(window)) {
 | 
						|
        scene.Idle();
 | 
						|
        scene.Display(window);        
 | 
						|
        glfwPollEvents();
 | 
						|
 | 
						|
        auto now = std::chrono::steady_clock::now();
 | 
						|
        if(std::chrono::duration_cast<std::chrono::seconds>(now - start).count() > 5) {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
} 
 | 
						|
 | 
						|
} // namespace
 | 
						|
 | 
						|
int main() {
 | 
						|
    if (!InitializeGlfw()) return -1;
 | 
						|
 | 
						|
    GLFWwindow* window = CreateGlfwWindow();
 | 
						|
    if (!window) return -1;
 | 
						|
 | 
						|
    if (!InitializeGlew()) return -1;
 | 
						|
 | 
						|
    Scene scene(kInitWindowWidth, kInitWindowHeight);
 | 
						|
    Callbacks::Register(window, &scene);
 | 
						|
    scene.Init();
 | 
						|
    InitializeImGui(window);
 | 
						|
    FreeImage_Initialise();
 | 
						|
 | 
						|
    // Check if we're in test mode
 | 
						|
    const char* testEnv = std::getenv("TEST_MODE");
 | 
						|
    if(testEnv) {
 | 
						|
        TestLoop(window, scene);
 | 
						|
    } else {
 | 
						|
        MainLoop(window, scene);
 | 
						|
    }
 | 
						|
 | 
						|
    CleanupImGui();
 | 
						|
    glfwDestroyWindow(window);
 | 
						|
    glfwTerminate();
 | 
						|
  
 | 
						|
    return 0;
 | 
						|
}
 |