<commit_before>
#include "test_suite.h"

int main(int argc, char **argv) {
  bool run_benchmark_all = false;
  bool run_test = false;
  bool run_benchmark_bwtree = false;
  bool run_benchmark_bwtree_full = false;
  bool run_stress = false;
  bool run_epoch_test = false;
  bool run_infinite_insert_test = false;
  bool run_email_test = false;
  bool run_mixed_test = false;

  int opt_index = 1;
  while(opt_index < argc) {
    char *opt_p = argv[opt_index];

    if(strcmp(opt_p, "--benchmark-all") == 0) {
      run_benchmark_all = true;
    } else if(strcmp(opt_p, "--test") == 0) {
      run_test = true;
    } else if(strcmp(opt_p, "--benchmark-bwtree") == 0) {
      run_benchmark_bwtree = true;
    } else if(strcmp(opt_p, "--benchmark-bwtree-full") == 0) {
      run_benchmark_bwtree_full = true;
    } else if(strcmp(opt_p, "--stress-test") == 0) {
      run_stress = true;
    } else if(strcmp(opt_p, "--epoch-test") == 0) {
      run_epoch_test = true;
    } else if(strcmp(opt_p, "--infinite-insert-test") == 0) {
      run_infinite_insert_test = true;
    } else if(strcmp(opt_p, "--email-test") == 0) {
      run_email_test = true;
    } else if(strcmp(opt_p, "--mixed-test") == 0) {
      run_mixed_test = true;
    } else {
      printf("ERROR: Unknown option: %s\n", opt_p);

      return 0;
    }

    opt_index++;
  }

  bwt_printf("RUN_BENCHMARK_ALL = %d\n", run_benchmark_all);
  bwt_printf("RUN_BENCHMARK_BWTREE = %d\n", run_benchmark_bwtree);
  bwt_printf("RUN_BENCHMARK_BWTREE_FULL = %d\n", run_benchmark_bwtree_full);
  bwt_printf("RUN_TEST = %d\n", run_test);
  bwt_printf("RUN_STRESS = %d\n", run_stress);
  bwt_printf("RUN_EPOCH_TEST = %d\n", run_epoch_test);
  bwt_printf("RUN_INFINITE_INSERT_TEST = %d\n", run_infinite_insert_test);
  bwt_printf("RUN_EMAIL_TEST = %d\n", run_email_test);
  bwt_printf("RUN_MIXED_TEST = %d\n", run_mixed_test);
  bwt_printf("======================================\n");

  //////////////////////////////////////////////////////
  // Next start running test cases
  //////////////////////////////////////////////////////

  TreeType *t1 = nullptr;

  if(run_mixed_test == true) {
    print_flag = true;
    t1 = new TreeType{KeyComparator{1},
                      KeyEqualityChecker{1}};
    print_flag = false;

    printf("Starting mixed testing...\n");
    LaunchParallelTestID(mixed_thread_num, MixedTest1, t1);
    printf("Finished mixed testing\n");

    PrintStat(t1);

    MixedGetValueTest(t1);

    print_flag = true;
    delete t1;
    print_flag = false;
  }

  if(run_email_test == true) {
    print_flag = true;
    auto t2 = new BwTree<std::string, long int>{};
    print_flag = false;

    TestBwTreeEmailInsertPerformance(t2, "emails_dump.txt");

    // t2 has already been deleted for memory reason
  }

  if(run_infinite_insert_test == true) {
    print_flag = true;
    t1 = new TreeType{KeyComparator{1},
                      KeyEqualityChecker{1}};
    print_flag = false;

    InfiniteRandomInsertTest(t1);

    print_flag = true;
    delete t1;
    print_flag = false;
  }

  if(run_epoch_test == true) {
    print_flag = true;
    t1 = new TreeType{KeyComparator{1},
                      KeyEqualityChecker{1}};
    print_flag = false;

    TestEpochManager(t1);

    print_flag = true;
    delete t1;
    print_flag = false;
  }

  if(run_benchmark_bwtree == true ||
     run_benchmark_bwtree_full == true) {
    print_flag = true;
    t1 = new TreeType{KeyComparator{1},
                      KeyEqualityChecker{1}};

    int key_num = 3 * 1024 * 1024;

    if(run_benchmark_bwtree_full == true) {
      key_num *= 10;
    }

    bwt_printf("Using key size = %d (%f million)\n",
               key_num,
               key_num / (1024.0 * 1024.0));

    print_flag = false;

    if(run_benchmark_bwtree_full == true) {
      // First we rely on this test to fill bwtree with 30 million keys
      TestBwTreeMultiThreadInsertPerformance(t1, key_num);

      // And then do a multithreaded read
      TestBwTreeMultiThreadReadPerformance(t1, key_num);
    } else {
      // This function will delete all keys at the end, so the tree
      // is empty after it returns
      TestBwTreeInsertReadDeletePerformance(t1, key_num);

      delete t1;
      t1 = new TreeType{KeyComparator{1},
                        KeyEqualityChecker{1}};

      // Tests random insert using one thread
      RandomInsertSpeedTest(t1, key_num);

      delete t1;
      t1 = new TreeType{KeyComparator{1},
                        KeyEqualityChecker{1}};

      // Test random insert seq read
      RandomInsertSeqReadSpeedTest(t1, key_num);

      delete t1;
      t1 = new TreeType{KeyComparator{1},
                        KeyEqualityChecker{1}};

      // Test seq insert random read
      SeqInsertRandomReadSpeedTest(t1, key_num);

      // Use stree_multimap as a reference
      RandomBtreeMultimapInsertSpeedTest(key_num);

      // Use cuckoohash_map
      RandomCuckooHashMapInsertSpeedTest(key_num);
    }

    print_flag = true;
    delete t1;
    print_flag = false;
  }

  if(run_benchmark_all == true) {
    print_flag = true;
    t1 = new TreeType{KeyComparator{1},
                      KeyEqualityChecker{1}};

    int key_num = 1024 * 1024 * 3;
    bwt_printf("Using key size = %d (%f million)\n",
               key_num,
               key_num / (1024.0 * 1024.0));

    print_flag = false;

    TestStdMapInsertReadPerformance(key_num);
    TestStdUnorderedMapInsertReadPerformance(key_num);
    TestBTreeInsertReadPerformance(key_num);
    TestBTreeMultimapInsertReadPerformance(key_num);
    TestCuckooHashTableInsertReadPerformance(key_num);
    TestBwTreeInsertReadPerformance(t1, key_num);

    print_flag = true;
    delete t1;
    print_flag = false;
  }

  if(run_test == true) {
    print_flag = true;
    t1 = new TreeType{KeyComparator{1},
                      KeyEqualityChecker{1}};
    print_flag = false;

    //////////////
    // Test iterator
    //////////////

    printf("Testing iterator...\n");

    IteratorTest(t1);
    PrintStat(t1);

    printf("Finised testing iterator\n");

    //////////////////////
    // Test random insert
    //////////////////////

    printf("Testing random insert...\n");

    // Do not print here otherwise we could not see result
    delete t1;
    t1 = new TreeType{KeyComparator{1},
                      KeyEqualityChecker{1}};

    LaunchParallelTestID(8, RandomInsertTest, t1);
    RandomInsertVerify(t1);

    printf("Finished random insert testing. Delete the tree.\n");

    delete t1;
    t1 = new TreeType{KeyComparator{1},
                      KeyEqualityChecker{1}};

    ////////////////////////////
    // Test mixed insert/delete
    ////////////////////////////

    LaunchParallelTestID(basic_test_thread_num, MixedTest1, t1);
    printf("Finished mixed testing\n");

    PrintStat(t1);

    MixedGetValueTest(t1);

    LaunchParallelTestID(basic_test_thread_num, InsertTest2, t1);
    printf("Finished inserting all keys\n");

    PrintStat(t1);

    InsertGetValueTest(t1);
    printf("Finished verifying all inserted values\n");

    LaunchParallelTestID(basic_test_thread_num, DeleteTest1, t1);
    printf("Finished deleting all keys\n");

    PrintStat(t1);

    DeleteGetValueTest(t1);
    printf("Finished verifying all deleted values\n");

    LaunchParallelTestID(basic_test_thread_num, InsertTest1, t1);
    printf("Finished inserting all keys\n");

    PrintStat(t1);

    InsertGetValueTest(t1);
    printf("Finished verifying all inserted values\n");

    LaunchParallelTestID(basic_test_thread_num, DeleteTest2, t1);
    printf("Finished deleting all keys\n");

    PrintStat(t1);

    DeleteGetValueTest(t1);
    printf("Finished verifying all deleted values\n");

    LaunchParallelTestID(basic_test_thread_num, InsertTest1, t1);
    printf("Finished inserting all keys\n");

    PrintStat(t1);

    InsertGetValueTest(t1);
    printf("Finished verifying all inserted values\n");

    LaunchParallelTestID(basic_test_thread_num, DeleteTest1, t1);
    printf("Finished deleting all keys\n");

    PrintStat(t1);

    DeleteGetValueTest(t1);
    printf("Finished verifying all deleted values\n");

    LaunchParallelTestID(basic_test_thread_num, InsertTest2, t1);
    printf("Finished inserting all keys\n");

    PrintStat(t1);

    InsertGetValueTest(t1);
    printf("Finished verifying all inserted values\n");

    LaunchParallelTestID(basic_test_thread_num, DeleteTest2, t1);
    printf("Finished deleting all keys\n");

    PrintStat(t1);

    DeleteGetValueTest(t1);
    printf("Finished verifying all deleted values\n");

    print_flag = true;
    delete t1;
    print_flag = false;
  }

  if(run_stress == true) {
    print_flag = true;
    t1 = new TreeType{KeyComparator{1},
                      KeyEqualityChecker{1}};
    print_flag = false;

    LaunchParallelTestID(8, StressTest, t1);

    print_flag = true;
    delete t1;
    print_flag = false;
  }

  return 0;
}

<commit_msg>Fixing main.cpp as constructor changes<commit_after>
#include "test_suite.h"

int main(int argc, char **argv) {
  bool run_benchmark_all = false;
  bool run_test = false;
  bool run_benchmark_bwtree = false;
  bool run_benchmark_bwtree_full = false;
  bool run_stress = false;
  bool run_epoch_test = false;
  bool run_infinite_insert_test = false;
  bool run_email_test = false;
  bool run_mixed_test = false;

  int opt_index = 1;
  while(opt_index < argc) {
    char *opt_p = argv[opt_index];

    if(strcmp(opt_p, "--benchmark-all") == 0) {
      run_benchmark_all = true;
    } else if(strcmp(opt_p, "--test") == 0) {
      run_test = true;
    } else if(strcmp(opt_p, "--benchmark-bwtree") == 0) {
      run_benchmark_bwtree = true;
    } else if(strcmp(opt_p, "--benchmark-bwtree-full") == 0) {
      run_benchmark_bwtree_full = true;
    } else if(strcmp(opt_p, "--stress-test") == 0) {
      run_stress = true;
    } else if(strcmp(opt_p, "--epoch-test") == 0) {
      run_epoch_test = true;
    } else if(strcmp(opt_p, "--infinite-insert-test") == 0) {
      run_infinite_insert_test = true;
    } else if(strcmp(opt_p, "--email-test") == 0) {
      run_email_test = true;
    } else if(strcmp(opt_p, "--mixed-test") == 0) {
      run_mixed_test = true;
    } else {
      printf("ERROR: Unknown option: %s\n", opt_p);

      return 0;
    }

    opt_index++;
  }

  bwt_printf("RUN_BENCHMARK_ALL = %d\n", run_benchmark_all);
  bwt_printf("RUN_BENCHMARK_BWTREE = %d\n", run_benchmark_bwtree);
  bwt_printf("RUN_BENCHMARK_BWTREE_FULL = %d\n", run_benchmark_bwtree_full);
  bwt_printf("RUN_TEST = %d\n", run_test);
  bwt_printf("RUN_STRESS = %d\n", run_stress);
  bwt_printf("RUN_EPOCH_TEST = %d\n", run_epoch_test);
  bwt_printf("RUN_INFINITE_INSERT_TEST = %d\n", run_infinite_insert_test);
  bwt_printf("RUN_EMAIL_TEST = %d\n", run_email_test);
  bwt_printf("RUN_MIXED_TEST = %d\n", run_mixed_test);
  bwt_printf("======================================\n");

  //////////////////////////////////////////////////////
  // Next start running test cases
  //////////////////////////////////////////////////////

  TreeType *t1 = nullptr;

  if(run_mixed_test == true) {
    print_flag = true;
    t1 = new TreeType{true,
                      KeyComparator{1},
                      KeyEqualityChecker{1}};
    print_flag = false;

    printf("Starting mixed testing...\n");
    LaunchParallelTestID(mixed_thread_num, MixedTest1, t1);
    printf("Finished mixed testing\n");

    PrintStat(t1);

    MixedGetValueTest(t1);

    print_flag = true;
    delete t1;
    print_flag = false;
  }

  if(run_email_test == true) {
    print_flag = true;
    auto t2 = new BwTree<std::string, long int>{};
    print_flag = false;

    TestBwTreeEmailInsertPerformance(t2, "emails_dump.txt");

    // t2 has already been deleted for memory reason
  }

  if(run_infinite_insert_test == true) {
    print_flag = true;
    t1 = new TreeType{true,
                      KeyComparator{1},
                      KeyEqualityChecker{1}};
    print_flag = false;

    InfiniteRandomInsertTest(t1);

    print_flag = true;
    delete t1;
    print_flag = false;
  }

  if(run_epoch_test == true) {
    print_flag = true;
    t1 = new TreeType{true,
                      KeyComparator{1},
                      KeyEqualityChecker{1}};
    print_flag = false;

    TestEpochManager(t1);

    print_flag = true;
    delete t1;
    print_flag = false;
  }

  if(run_benchmark_bwtree == true ||
     run_benchmark_bwtree_full == true) {
    print_flag = true;
    t1 = new TreeType{true,
                      KeyComparator{1},
                      KeyEqualityChecker{1}};

    int key_num = 3 * 1024 * 1024;

    if(run_benchmark_bwtree_full == true) {
      key_num *= 10;
    }

    bwt_printf("Using key size = %d (%f million)\n",
               key_num,
               key_num / (1024.0 * 1024.0));

    print_flag = false;

    if(run_benchmark_bwtree_full == true) {
      // First we rely on this test to fill bwtree with 30 million keys
      TestBwTreeMultiThreadInsertPerformance(t1, key_num);

      // And then do a multithreaded read
      TestBwTreeMultiThreadReadPerformance(t1, key_num);
    } else {
      // This function will delete all keys at the end, so the tree
      // is empty after it returns
      TestBwTreeInsertReadDeletePerformance(t1, key_num);

      delete t1;
      t1 = new TreeType{true,
                        KeyComparator{1},
                        KeyEqualityChecker{1}};

      // Tests random insert using one thread
      RandomInsertSpeedTest(t1, key_num);

      delete t1;
      t1 = new TreeType{true,
                        KeyComparator{1},
                        KeyEqualityChecker{1}};

      // Test random insert seq read
      RandomInsertSeqReadSpeedTest(t1, key_num);

      delete t1;
      t1 = new TreeType{true,
                        KeyComparator{1},
                        KeyEqualityChecker{1}};

      // Test seq insert random read
      SeqInsertRandomReadSpeedTest(t1, key_num);

      // Use stree_multimap as a reference
      RandomBtreeMultimapInsertSpeedTest(key_num);

      // Use cuckoohash_map
      RandomCuckooHashMapInsertSpeedTest(key_num);
    }

    print_flag = true;
    delete t1;
    print_flag = false;
  }

  if(run_benchmark_all == true) {
    print_flag = true;
    t1 = new TreeType{true,
                      KeyComparator{1},
                      KeyEqualityChecker{1}};

    int key_num = 1024 * 1024 * 3;
    bwt_printf("Using key size = %d (%f million)\n",
               key_num,
               key_num / (1024.0 * 1024.0));

    print_flag = false;

    TestStdMapInsertReadPerformance(key_num);
    TestStdUnorderedMapInsertReadPerformance(key_num);
    TestBTreeInsertReadPerformance(key_num);
    TestBTreeMultimapInsertReadPerformance(key_num);
    TestCuckooHashTableInsertReadPerformance(key_num);
    TestBwTreeInsertReadPerformance(t1, key_num);

    print_flag = true;
    delete t1;
    print_flag = false;
  }

  if(run_test == true) {
    print_flag = true;
    t1 = new TreeType{true,
                      KeyComparator{1},
                      KeyEqualityChecker{1}};
    print_flag = false;

    //////////////
    // Test iterator
    //////////////

    printf("Testing iterator...\n");

    IteratorTest(t1);
    PrintStat(t1);

    printf("Finised testing iterator\n");

    //////////////////////
    // Test random insert
    //////////////////////

    printf("Testing random insert...\n");

    // Do not print here otherwise we could not see result
    delete t1;
    t1 = new TreeType{true,
                      KeyComparator{1},
                      KeyEqualityChecker{1}};

    LaunchParallelTestID(8, RandomInsertTest, t1);
    RandomInsertVerify(t1);

    printf("Finished random insert testing. Delete the tree.\n");

    delete t1;
    t1 = new TreeType{true,
                      KeyComparator{1},
                      KeyEqualityChecker{1}};

    ////////////////////////////
    // Test mixed insert/delete
    ////////////////////////////

    LaunchParallelTestID(basic_test_thread_num, MixedTest1, t1);
    printf("Finished mixed testing\n");

    PrintStat(t1);

    MixedGetValueTest(t1);

    LaunchParallelTestID(basic_test_thread_num, InsertTest2, t1);
    printf("Finished inserting all keys\n");

    PrintStat(t1);

    InsertGetValueTest(t1);
    printf("Finished verifying all inserted values\n");

    LaunchParallelTestID(basic_test_thread_num, DeleteTest1, t1);
    printf("Finished deleting all keys\n");

    PrintStat(t1);

    DeleteGetValueTest(t1);
    printf("Finished verifying all deleted values\n");

    LaunchParallelTestID(basic_test_thread_num, InsertTest1, t1);
    printf("Finished inserting all keys\n");

    PrintStat(t1);

    InsertGetValueTest(t1);
    printf("Finished verifying all inserted values\n");

    LaunchParallelTestID(basic_test_thread_num, DeleteTest2, t1);
    printf("Finished deleting all keys\n");

    PrintStat(t1);

    DeleteGetValueTest(t1);
    printf("Finished verifying all deleted values\n");

    LaunchParallelTestID(basic_test_thread_num, InsertTest1, t1);
    printf("Finished inserting all keys\n");

    PrintStat(t1);

    InsertGetValueTest(t1);
    printf("Finished verifying all inserted values\n");

    LaunchParallelTestID(basic_test_thread_num, DeleteTest1, t1);
    printf("Finished deleting all keys\n");

    PrintStat(t1);

    DeleteGetValueTest(t1);
    printf("Finished verifying all deleted values\n");

    LaunchParallelTestID(basic_test_thread_num, InsertTest2, t1);
    printf("Finished inserting all keys\n");

    PrintStat(t1);

    InsertGetValueTest(t1);
    printf("Finished verifying all inserted values\n");

    LaunchParallelTestID(basic_test_thread_num, DeleteTest2, t1);
    printf("Finished deleting all keys\n");

    PrintStat(t1);

    DeleteGetValueTest(t1);
    printf("Finished verifying all deleted values\n");

    print_flag = true;
    delete t1;
    print_flag = false;
  }

  if(run_stress == true) {
    print_flag = true;

    // NOTE: For stress test we must start the GC thread in order
    // to let the tree run indefinitely
    t1 = new TreeType{true,
                      KeyComparator{1},
                      KeyEqualityChecker{1}};
    print_flag = false;

    LaunchParallelTestID(8, StressTest, t1);

    print_flag = true;
    delete t1;
    print_flag = false;
  }

  return 0;
}

<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <SDL.h>
#include <glm/glm.hpp>
#include "gl_core_4_4.h"
#include "util.h"

/*
 * The OpenGL DrawElementsIndirectCommand struct described in the docs
 */
struct DrawElementsIndirectCommand {
	GLuint count, instance_count, first_index,
		base_vertex, base_instance;

	DrawElementsIndirectCommand(GLuint count, GLuint instance_count, GLuint first_index,
		GLuint base_vertex, GLuint base_instance)
		: count(count), instance_count(instance_count), first_index(first_index),
		base_vertex(base_vertex), base_instance(base_instance)
	{}
};

//Our two "models" packed into a single buffer, really just two tris w/ different colors
const std::array<glm::vec3, 6> triangles_verts{
	//The first "model", lower left tri
	glm::vec3{-1.f, -1.f, 0.f},	glm::vec3{1.f, -1.f, 0.f}, glm::vec3{-1.f, 1.f, 0.f},
	//The second "model", upper right tri
	glm::vec3{1.f, -1.f, 0.f}, glm::vec3{1.f, 1.f, 0.f}, glm::vec3{-1.f, 1.f, 0.f}
};
//The element buffers for both "models" packed into one buffer
const std::array<GLushort, 6> triangles_indices{
	0, 1, 2,
	3, 4, 5
};
//Our attributes buffer for the two instances of our "models"
const std::array<glm::vec3, 2> triangle_attribs{
	glm::vec3{1.f, 0.f, 0.f}, glm::vec3{0.f, 0.f, 1.f}
};

int main(int, char**){
	if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
		std::cerr << "SDL_Init error: " << SDL_GetError() << "\n";
		return 1;
	}

	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 4);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
#ifdef DEBUG
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
#endif

	SDL_Window *win = SDL_CreateWindow("3D Tiles", SDL_WINDOWPOS_CENTERED,
		SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_OPENGL);
	SDL_GLContext context = SDL_GL_CreateContext(win);
	SDL_GL_SetSwapInterval(1);

	if (ogl_LoadFunctions() == ogl_LOAD_FAILED){
		std::cerr << "ogl load failed\n";
		SDL_GL_DeleteContext(context);
		SDL_DestroyWindow(win);
		SDL_Quit();
		return 1;
	}
	glClearColor(0.f, 0.f, 0.f, 1.f);
	glClearDepth(1.f);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);

	std::cout << "OpenGL Version: " << glGetString(GL_VERSION) << "\n"
		<< "OpenGL Vendor: " << glGetString(GL_VENDOR) << "\n"
		<< "OpenGL Renderer: " << glGetString(GL_RENDERER) << "\n"
		<< "GLSL Version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << "\n";

#ifdef DEBUG
	glEnable(GL_DEBUG_OUTPUT);
	glDebugMessageCallback(util::gldebug_callback, NULL);
	glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
#endif

	GLuint vao;
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	//Vertex buffer, element buffer and instance attribute buffer
	GLuint vbo, ebo, attribs;
	glGenBuffers(1, &vbo);
	glGenBuffers(1, &ebo);
	glGenBuffers(1, &attribs);

	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(triangles_verts), triangles_verts.data(), GL_STATIC_DRAW);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(triangles_indices), triangles_indices.data(), GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, attribs);
	glBufferData(GL_ARRAY_BUFFER, sizeof(triangle_attribs), triangle_attribs.data(), GL_STATIC_DRAW);
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glVertexAttribDivisor(1, 1);

	const std::string shader_path = util::get_resource_path("shaders");
	GLuint shader = util::load_program({std::make_tuple(GL_VERTEX_SHADER, shader_path + "vmdei_test.glsl"),
		std::make_tuple(GL_FRAGMENT_SHADER, shader_path + "fmdei_test.glsl")});
	glUseProgram(shader);

	std::array<DrawElementsIndirectCommand, 2> draw_commands{
		DrawElementsIndirectCommand{3, 1, 0, 0, 0},
		DrawElementsIndirectCommand{3, 1, 3, 0, 1}
	};
	GLuint draw_cmd_buf;
	glGenBuffers(1, &draw_cmd_buf);
	glBindBuffer(GL_DRAW_INDIRECT_BUFFER, draw_cmd_buf);
	glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(draw_commands), draw_commands.data(), GL_STATIC_DRAW);

	SDL_Event e;
	bool quit = false;
	while (!quit){
		while (SDL_PollEvent(&e)){
			if (e.type == SDL_QUIT || (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE)){
				quit = true;
			}
		}
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, NULL, 2, sizeof(DrawElementsIndirectCommand));

		SDL_GL_SwapWindow(win);
	}

	glDeleteProgram(shader);
	glDeleteVertexArrays(1, &vao);
	glDeleteBuffers(1, &draw_cmd_buf);
	glDeleteBuffers(1, &vbo);
	glDeleteBuffers(1, &ebo);
	glDeleteBuffers(1, &attribs);

	SDL_GL_DeleteContext(context);
	SDL_DestroyWindow(win);
	SDL_Quit();
	return 0;
}

<commit_msg>Fix some tabbing<commit_after>#include <iostream>
#include <string>
#include <SDL.h>
#include <glm/glm.hpp>
#include "gl_core_4_4.h"
#include "util.h"

/*
 * The OpenGL DrawElementsIndirectCommand struct described in the docs
 */
struct DrawElementsIndirectCommand {
	GLuint count, instance_count, first_index,
		base_vertex, base_instance;

	DrawElementsIndirectCommand(GLuint count, GLuint instance_count, GLuint first_index,
		GLuint base_vertex, GLuint base_instance)
		: count(count), instance_count(instance_count), first_index(first_index),
		base_vertex(base_vertex), base_instance(base_instance)
	{}
};

//Our two "models" packed into a single buffer, really just two tris
const std::array<glm::vec3, 6> triangles_verts{
	//The first "model", lower left tri
	glm::vec3{-1.f, -1.f, 0.f}, glm::vec3{1.f, -1.f, 0.f}, glm::vec3{-1.f, 1.f, 0.f},
	//The second "model", upper right tri
	glm::vec3{1.f, -1.f, 0.f}, glm::vec3{1.f, 1.f, 0.f}, glm::vec3{-1.f, 1.f, 0.f}
};
//The element buffers for both "models" packed into one buffer
const std::array<GLushort, 6> triangles_indices{
	0, 1, 2,
	3, 4, 5
};
//Our attributes buffer for the two instances of our "models"
const std::array<glm::vec3, 2> triangle_attribs{
	glm::vec3{1.f, 0.f, 0.f}, glm::vec3{0.f, 0.f, 1.f}
};

int main(int, char**){
	if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
		std::cerr << "SDL_Init error: " << SDL_GetError() << "\n";
		return 1;
	}

	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 4);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
#ifdef DEBUG
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
#endif

	SDL_Window *win = SDL_CreateWindow("3D Tiles", SDL_WINDOWPOS_CENTERED,
		SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_OPENGL);
	SDL_GLContext context = SDL_GL_CreateContext(win);
	SDL_GL_SetSwapInterval(1);

	if (ogl_LoadFunctions() == ogl_LOAD_FAILED){
		std::cerr << "ogl load failed\n";
		SDL_GL_DeleteContext(context);
		SDL_DestroyWindow(win);
		SDL_Quit();
		return 1;
	}
	glClearColor(0.f, 0.f, 0.f, 1.f);
	glClearDepth(1.f);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);

	std::cout << "OpenGL Version: " << glGetString(GL_VERSION) << "\n"
		<< "OpenGL Vendor: " << glGetString(GL_VENDOR) << "\n"
		<< "OpenGL Renderer: " << glGetString(GL_RENDERER) << "\n"
		<< "GLSL Version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << "\n";

#ifdef DEBUG
	glEnable(GL_DEBUG_OUTPUT);
	glDebugMessageCallback(util::gldebug_callback, NULL);
	glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
#endif

	GLuint vao;
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	//Vertex buffer, element buffer and instance attribute buffer
	GLuint vbo, ebo, attribs;
	glGenBuffers(1, &vbo);
	glGenBuffers(1, &ebo);
	glGenBuffers(1, &attribs);

	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(triangles_verts), triangles_verts.data(), GL_STATIC_DRAW);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(triangles_indices), triangles_indices.data(), GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, attribs);
	glBufferData(GL_ARRAY_BUFFER, sizeof(triangle_attribs), triangle_attribs.data(), GL_STATIC_DRAW);
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glVertexAttribDivisor(1, 1);

	const std::string shader_path = util::get_resource_path("shaders");
	GLuint shader = util::load_program({std::make_tuple(GL_VERTEX_SHADER, shader_path + "vmdei_test.glsl"),
		std::make_tuple(GL_FRAGMENT_SHADER, shader_path + "fmdei_test.glsl")});
	glUseProgram(shader);

	std::array<DrawElementsIndirectCommand, 2> draw_commands{
		DrawElementsIndirectCommand{3, 1, 0, 0, 0},
		DrawElementsIndirectCommand{3, 1, 3, 0, 1}
	};
	GLuint draw_cmd_buf;
	glGenBuffers(1, &draw_cmd_buf);
	glBindBuffer(GL_DRAW_INDIRECT_BUFFER, draw_cmd_buf);
	glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(draw_commands), draw_commands.data(), GL_STATIC_DRAW);

	SDL_Event e;
	bool quit = false;
	while (!quit){
		while (SDL_PollEvent(&e)){
			if (e.type == SDL_QUIT || (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE)){
				quit = true;
			}
		}
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, NULL, 2, sizeof(DrawElementsIndirectCommand));

		SDL_GL_SwapWindow(win);
	}

	glDeleteProgram(shader);
	glDeleteVertexArrays(1, &vao);
	glDeleteBuffers(1, &draw_cmd_buf);
	glDeleteBuffers(1, &vbo);
	glDeleteBuffers(1, &ebo);
	glDeleteBuffers(1, &attribs);

	SDL_GL_DeleteContext(context);
	SDL_DestroyWindow(win);
	SDL_Quit();
	return 0;
}

<|endoftext|>


<commit_before>#include "main.h"
#include "gamescene.h"
#include "yaml_config.h"

#include <iostream>
#include <stdlib.h>

#define SCREEN_WIDTH 1024
#define SCREEN_HEIGHT 768

#define INIT_FAILED             (-1)
#define WINDOW_INIT_FAILED      (-2)
#define RENDERER_INIT_FAILED    (-3)
#define IMAGE_INIT_FAILED       (-4)

Main::Main() {}
Main::~Main() {}

SDL_Renderer *Main::renderer;

/**
 * Initialize SDL2 and handle any errors that might pop up
 */
void Main::initSDL() {
    int init = SDL_Init(SDL_INIT_EVERYTHING);
    if (init != 0) {
        std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
        this->quit(INIT_FAILED);
    }

    this->window = SDL_CreateWindow("Hello World!", 100, 100, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
    if (this->window == NULL || strlen(SDL_GetError()) != 0){
        std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
        this->quit(WINDOW_INIT_FAILED);
    }

    printf("NumRenderDrivers: %d\n", SDL_GetNumRenderDrivers());
    /* Without this I can't make any renderer work, my best guess is that this is a bug and will
       be fixed sooner or later */
    SDL_GL_LoadLibrary("/usr/lib/libGL.so");
    std::cout << "SDL_GL_LoadLibrary: " << SDL_GetError() << std::endl;

    Main::renderer = SDL_CreateRenderer(this->window, 1, SDL_RENDERER_ACCELERATED);
    if (Main::renderer == NULL || strlen(SDL_GetError()) != 0){
        std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
        this->quit(RENDERER_INIT_FAILED);
    }

    // load support for the JPG and PNG image formats
    int flags = IMG_INIT_JPG|IMG_INIT_PNG;
    int initted = IMG_Init(flags);
    if((initted&flags) != flags || strlen(IMG_GetError()) != 0) {
        printf("IMG_Init: Failed to init required jpg and png support!\n");
        printf("IMG_Init: %s\n", IMG_GetError());
        this->quit(IMAGE_INIT_FAILED); // we can't do shit like this...
    }

    // Set up the blank color
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);

    // any errors? display them now and quit.
    const char *errors = SDL_GetError();
    if(errors != NULL || strlen(errors) == 0) { // no problems at start up
        return;
    } else {
        printf("Initial errors: %s\n", errors);
        this->quit(INIT_FAILED);
    }
}

void Main::initGameScene() {
    scene = new GameScene();
}

/**
 * Main loop responsible for running updates on the scene and rendering the scene.
 * Keeps track of frame time as well for fancy graphs :)
 */
void Main::loop() {
    bool running = true;
    Uint32 current_time, old_time;
    current_time = SDL_GetTicks();
    SDL_Event e;
    while (running) {
        old_time = current_time;
        current_time = SDL_GetTicks();
        Uint32 delta = current_time - old_time;

        while (SDL_PollEvent(&e)){
            //If user closes the window
            if (e.type == SDL_QUIT){
                running = false;
                break;
            }
            if (e.type == SDL_KEYDOWN) {
                if(e.key.keysym.sym == SDLK_ESCAPE) {
                    running = false;
                    break;
                }
            }
            scene->onInput(e);
        }

        // clear the screen with black
        SDL_RenderClear(Main::renderer);

        // update
        this->scene->update(delta);
        this->scene->updatePhysics(delta);

        scene->renderScene();

        // Swap buffers
        SDL_RenderPresent(Main::renderer);
    }
}

/**
 * Clean up and quit. This should always be executed just before quiting the game.
 */
void Main::cleanup() {
    delete scene;
    SDL_DestroyRenderer(Main::renderer);
    SDL_DestroyWindow(this->window);
    IMG_Quit();
    SDL_Quit();
}

void Main::quit(int code) {
    cleanup();
    if (code == 0) {
        exit(EXIT_SUCCESS);
    } else {
        printf("Exit error code: %d\n", code);
        exit(EXIT_FAILURE);
    }
}

int main() {
    Main *main = new Main();
    main->initSDL();
    main->initGameScene();
    main->loop();
    main->cleanup();
    delete main;
}
<commit_msg>convert delta to a float and change it to milliseconds per second<commit_after>#include "main.h"
#include "gamescene.h"
#include "yaml_config.h"

#include <iostream>
#include <stdlib.h>

#define SCREEN_WIDTH 1024
#define SCREEN_HEIGHT 768

#define INIT_FAILED             (-1)
#define WINDOW_INIT_FAILED      (-2)
#define RENDERER_INIT_FAILED    (-3)
#define IMAGE_INIT_FAILED       (-4)

Main::Main() {}
Main::~Main() {}

SDL_Renderer *Main::renderer;

/**
 * Initialize SDL2 and handle any errors that might pop up
 */
void Main::initSDL() {
    int init = SDL_Init(SDL_INIT_EVERYTHING);
    if (init != 0) {
        std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
        this->quit(INIT_FAILED);
    }

    this->window = SDL_CreateWindow("Hello World!", 100, 100, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
    if (this->window == NULL || strlen(SDL_GetError()) != 0){
        std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
        this->quit(WINDOW_INIT_FAILED);
    }

    printf("NumRenderDrivers: %d\n", SDL_GetNumRenderDrivers());
    /* Without this I can't make any renderer work, my best guess is that this is a bug and will
       be fixed sooner or later */
    SDL_GL_LoadLibrary("/usr/lib/libGL.so");
    std::cout << "SDL_GL_LoadLibrary: " << SDL_GetError() << std::endl;

    Main::renderer = SDL_CreateRenderer(this->window, 1, SDL_RENDERER_ACCELERATED);
    if (Main::renderer == NULL || strlen(SDL_GetError()) != 0){
        std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
        this->quit(RENDERER_INIT_FAILED);
    }

    // load support for the JPG and PNG image formats
    int flags = IMG_INIT_JPG|IMG_INIT_PNG;
    int initted = IMG_Init(flags);
    if((initted&flags) != flags || strlen(IMG_GetError()) != 0) {
        printf("IMG_Init: Failed to init required jpg and png support!\n");
        printf("IMG_Init: %s\n", IMG_GetError());
        this->quit(IMAGE_INIT_FAILED); // we can't do shit like this...
    }

    // Set up the blank color
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);

    // any errors? display them now and quit.
    const char *errors = SDL_GetError();
    if(errors != NULL || strlen(errors) == 0) { // no problems at start up
        return;
    } else {
        printf("Initial errors: %s\n", errors);
        this->quit(INIT_FAILED);
    }
}

void Main::initGameScene() {
    scene = new GameScene();
}

/**
 * Main loop responsible for running updates on the scene and rendering the scene.
 * Keeps track of frame time as well for fancy graphs :)
 */
void Main::loop() {
    bool running = true;
    float current_time, old_time;
    current_time = SDL_GetTicks();
    SDL_Event e;
    while (running) {
        old_time = current_time;
        current_time = (float)SDL_GetTicks();
        float delta = (current_time - old_time) / 1000; // get milliseconds per second

        while (SDL_PollEvent(&e)){
            //If user closes the window
            if (e.type == SDL_QUIT){
                running = false;
                break;
            }
            if (e.type == SDL_KEYDOWN) {
                if(e.key.keysym.sym == SDLK_ESCAPE) {
                    running = false;
                    break;
                }
            }
            scene->onInput(e);
        }

        // clear the screen with black
        SDL_RenderClear(Main::renderer);

        // update
        this->scene->update(delta);
        this->scene->updatePhysics(delta);

        scene->renderScene();

        // Swap buffers
        SDL_RenderPresent(Main::renderer);
    }
}

/**
 * Clean up and quit. This should always be executed just before quiting the game.
 */
void Main::cleanup() {
    delete scene;
    SDL_DestroyRenderer(Main::renderer);
    SDL_DestroyWindow(this->window);
    IMG_Quit();
    SDL_Quit();
}

void Main::quit(int code) {
    cleanup();
    if (code == 0) {
        exit(EXIT_SUCCESS);
    } else {
        printf("Exit error code: %d\n", code);
        exit(EXIT_FAILURE);
    }
}

int main() {
    Main *main = new Main();
    main->initSDL();
    main->initGameScene();
    main->loop();
    main->cleanup();
    delete main;
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <cstdint>
#include "SDL.h"
#include <string>

#define internal static
#define local_persist static
#define global_variable static

#define uint8_t  uint8
#define uint16_t uint16
#define uint32_t uint32
#define uint64_t uint64

#define int8_t int8
#define int16_t int16
#define int32_t int32
#define int64_t int64

global_variable SDL_Window* globalWindow = 0; //TODO: Inspect if the window really needs to be global or not
global_variable SDL_Renderer* globalRenderer = 0;
global_variable SDL_Texture* globalTexture = 0;

internal void close() { //Safely handles the closing of the whole program
	SDL_DestroyWindow(globalWindow);
	SDL_Quit();
}

internal void logErrorSDL(std::string text) { //Helps cut down on frantical copy-pasting of code. Keyboard manufacturers hate him!
	printf("%s\n SDL_Error:%s\n", text.c_str(), SDL_GetError());
}

internal bool init(std::string title, int width, int height) { //Initializes SDL and handles all errors
	//TODO: initialize SDL
	if (SDL_Init(SDL_INIT_VIDEO) < 0) { //TODO: Probably will be replaced by SDL_INIT_EVERYTHING
		logErrorSDL("Failed to initialize SDL!");
	} else {
		globalWindow = SDL_CreateWindow(title.c_str(),
										SDL_WINDOWPOS_CENTERED,
										SDL_WINDOWPOS_CENTERED,
										width,
										height,
										0); //TODO: Add SDL_WINDOW_FULLSCREEN
		if (globalWindow == 0) {
			logErrorSDL("SDL error while creating a window!");
		} else {
			globalRenderer = SDL_CreateRenderer(globalWindow,
												-1,
												SDL_RENDERER_ACCELERATED);
			if (globalRenderer == 0) {
				logErrorSDL("Failed to create renderer!");
			} else {
				//TODO: IMG_Init in case the program will use textures as well
			}
		}
	}
}

int main(int argc, char* args[]) {
	bool isGameRunning = true;

	//TODO: Read in these values from a file
	std::string gameTitle = "Unknown Pong";
	int windowWidth = 800;
	int windowHeight = 600;

	while (isGameRunning) { //This is the main game loop

	}

	close();
	return 0;
}<commit_msg>Added more features<commit_after>#include <stdio.h>
#include <cstdint>
#include "SDL.h"
#include <string>

#define internal static
#define local_persist static
#define global_variable static

#define uint8 uint8_t
#define uint16 uint16_t
#define uint32 uint32_t
#define uint64 uint64_t

#define int8 int8_t
#define int16 int16_t
#define int32 int32_t
#define int64 int64_t

#define MILLISECONDS_IN_A_SECOND 1000

enum gameCommandsEnum {
	GAMECOMMAND_UP,
	GAMECOMMAND_DOWN,
	GAMECOMMAND_ACTION, //Brings the pads closer to each other
	GAMECOMMAND_MAXACTIONS //Isn't a command by itself - is used in order to determine how many gameCommands there are
};

enum timerParam {
	TIMER_FPS,
	TIMER_TICKS
};

global_variable SDL_Window* globalWindow = 0; //TODO: Inspect if the window really needs to be global or not
global_variable SDL_Renderer* globalRenderer = 0;
global_variable SDL_Texture* globalTexture = 0;

global_variable bool gameCommands[GAMECOMMAND_MAXACTIONS] = {}; //This array contains what game commands the user is inputting currently

//Enum to store all possible actions the user could take.

//Safely handles the closing of the whole program
internal void close() {
	SDL_DestroyWindow(globalWindow);
	SDL_Quit();
}

//Helps cut down on frantical copy-pasting of code. Keyboard manufacturers hate him!
internal void logErrorSDL(std::string text) {
	printf("%s\n SDL_Error:%s\n", text.c_str(), SDL_GetError()); //TODO: Replace printf with an actual file logger
}

//Initializes SDL and handles all errors
internal bool init(std::string title, int width, int height) {
	bool success = true;
	if (SDL_Init(SDL_INIT_VIDEO) < 0) { //TODO: Probably will be replaced by SDL_INIT_EVERYTHING
		logErrorSDL("Failed to initialize SDL!");
		success = false;
	} else {
		globalWindow = SDL_CreateWindow(title.c_str(),
										SDL_WINDOWPOS_CENTERED,
										SDL_WINDOWPOS_CENTERED,
										width,
										height,
										0); //TODO: Add SDL_WINDOW_FULLSCREEN
		if (globalWindow == 0) {
			logErrorSDL("SDL error while creating a window!");
			success = false;
		} else {
			globalRenderer = SDL_CreateRenderer(globalWindow,
												-1,
												SDL_RENDERER_ACCELERATED);
			if (globalRenderer == 0) {
				logErrorSDL("Failed to create renderer!");
				success = false;
			} else {
				//TODO: IMG_Init in case the program will use textures as well
			}
		}
	}
	return success;
}

internal uint32 timerCallback(uint32 interval, void *param) {
	SDL_Event event;
	SDL_UserEvent userEvent = {};
	userEvent.type = SDL_USEREVENT;
	userEvent.code = (int32)param;

	event.type = SDL_USEREVENT;
	event.user = userEvent;

	SDL_PushEvent(&event);
	return interval;

}

internal void initTimers(int fpsLimit) {
	int fpsDelay = MILLISECONDS_IN_A_SECOND / fpsLimit; //The amount of milliseconds that should pass between each frame
	if (SDL_AddTimer(fpsDelay, timerCallback, (int32 *)TIMER_FPS) == 0) {
		logErrorSDL("Error while creating the FPS timer!");
	}
}

//TODO: Customizable controls
internal void handleKeyboardInput(const uint8* keyboardState) {
	if (keyboardState[SDL_SCANCODE_UP]) { //TODO: FIX ERROR!!!!
		gameCommands[GAMECOMMAND_UP] = 1;
		printf("up\n");
	} else {
		gameCommands[GAMECOMMAND_UP] = 0;
	}
	if (keyboardState[SDL_SCANCODE_DOWN]) {
		gameCommands[GAMECOMMAND_DOWN] = 1;
		printf("down\n");
	} else {
		gameCommands[GAMECOMMAND_DOWN] = 0;
	}
	if (keyboardState[SDL_SCANCODE_SPACE]) {
		gameCommands[GAMECOMMAND_ACTION] = 1;
		printf("space\n");
	} else {
		gameCommands[GAMECOMMAND_ACTION] = 0;
	}
}

int main(int argc, char* args[]) {

	bool isGameRunning = true;

	//TODO: Read in these values from a file
	std::string gameTitle = "Unknown Pong";
	int windowWidth = 800;
	int windowHeight = 600;
	int fpsLimit = 144;

	init(gameTitle, windowWidth, windowHeight);
	initTimers(fpsLimit);

	const uint8* keyboardState = SDL_GetKeyboardState(0); //Updates every time SDL_PollEvent() is called

	//This is the main game loop
	while (isGameRunning) {
		SDL_Event sdlEvent;

		while (SDL_PollEvent(&sdlEvent)) {
			switch (sdlEvent.type) {
				case SDL_USEREVENT:
					if (sdlEvent.user.code == TIMER_FPS) {
						handleKeyboardInput(keyboardState);
					} else if (sdlEvent.user.code == TIMER_TICKS) {
						//TODO: Implement ticks
					}
					break;
				case SDL_QUIT:
					isGameRunning = false;
					break;
			}
		}

	}

	close();
	return 0;
}<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// Reaper
///
/// Copyright (c) 2015-2019 Thibault Schueller
/// This file is distributed under the MIT License
////////////////////////////////////////////////////////////////////////////////

#include "common/DebugLog.h"
#include "common/ReaperRoot.h"

#include "renderer/Renderer.h"
#include "renderer/vulkan/Test.h"
#include "renderer/vulkan/VulkanRenderer.h"

#include "core/Profile.h"

// Log all of stdout and stderr to a file
#define REAPER_LOG_OUTPUT 1

int main(int /*ac*/, char** /*av*/)
{
#if REAPER_LOG_OUTPUT
    Assert(freopen("stdout.txt", "w", stdout));
    Assert(freopen("stderr.txt", "w", stderr));
#endif

#if defined(REAPER_USE_MICROPROFILE)
    MicroProfileOnThreadCreate("Main");
    MicroProfileSetEnableAllGroups(true);
    MicroProfileSetForceMetaCounters(true);
    MicroProfileStartContextSwitchTrace();
#endif

    {
        using namespace Reaper;

        ReaperRoot root = {};

        root.log = new DebugLog();

        log_info(root, "engine: startup");
        {
            if (create_renderer(root))
            {
                vulkan_test(root, *root.renderer->backend);
                destroy_renderer(root);
            }
        }
        log_info(root, "engine: shutdown");

        delete root.log;
        root.log = nullptr;
    }

#if defined(REAPER_USE_MICROPROFILE)
    MicroProfileDumpFileImmediately("profile.html", nullptr, nullptr);
    MicroProfileShutdown();
#endif

#if REAPER_LOG_OUTPUT
    Assert(fclose(stdout) == 0);
    Assert(fclose(stderr) == 0);
#endif

    return 0;
}
<commit_msg>core: disable output logging<commit_after>////////////////////////////////////////////////////////////////////////////////
/// Reaper
///
/// Copyright (c) 2015-2019 Thibault Schueller
/// This file is distributed under the MIT License
////////////////////////////////////////////////////////////////////////////////

#include "common/DebugLog.h"
#include "common/ReaperRoot.h"

#include "renderer/Renderer.h"
#include "renderer/vulkan/Test.h"
#include "renderer/vulkan/VulkanRenderer.h"

#include "core/Profile.h"

// Log all of stdout and stderr to a file
// FIXME does not work, disabled
#define REAPER_LOG_OUTPUT 0

int main(int /*ac*/, char** /*av*/)
{
#if REAPER_LOG_OUTPUT
    Assert(freopen("stdout.txt", "w", stdout));
    Assert(freopen("stderr.txt", "w", stderr));
#endif

#if defined(REAPER_USE_MICROPROFILE)
    MicroProfileOnThreadCreate("Main");
    MicroProfileSetEnableAllGroups(true);
    MicroProfileSetForceMetaCounters(true);
    MicroProfileStartContextSwitchTrace();
#endif

    {
        using namespace Reaper;

        ReaperRoot root = {};

        root.log = new DebugLog();

        log_info(root, "engine: startup");
        {
            if (create_renderer(root))
            {
                vulkan_test(root, *root.renderer->backend);
                destroy_renderer(root);
            }
        }
        log_info(root, "engine: shutdown");

        delete root.log;
        root.log = nullptr;
    }

#if defined(REAPER_USE_MICROPROFILE)
    MicroProfileDumpFileImmediately("profile.html", nullptr, nullptr);
    MicroProfileShutdown();
#endif

#if REAPER_LOG_OUTPUT
    Assert(fclose(stdout) == 0);
    Assert(fclose(stderr) == 0);
#endif

    return 0;
}
<|endoftext|>


<commit_before>
#include <iostream>
#include <vector>

struct ModelInputData
{
    double start_army_size;             // > 0
    double start_enemy_size;            // > 0
    double army_skill;                  // 0 < x <= 1
    double enemy_skill;                 // 0 < x <= 1
    double start_ammo;                  // > 0
    double ammo_diffusion_coeffient;    // > 0
    double battlefield_size;            // > 0
    double front_line_fraction;         // 0 < x <= 1

    double delta_time;                  // > 0
    double delta_x;                     // > 0

    /**
     * @brief ModelInputData default input data
     */
    ModelInputData()
    {
        start_army_size             = 100.0;
        start_enemy_size            = 100.0;
        army_skill                  = 0.5;
        enemy_skill                 = 0.5;
        start_ammo                  = 1000;
        ammo_diffusion_coeffient    = 1.0;
        battlefield_size            = 10;
        front_line_fraction         = 0.1;

        delta_time                  = 0.1;
        delta_x                     = 1;
    }
};

struct ModelInfo
{
    double time             = 0.0;

    double new_army_size    = 0.0;
    double old_army_size    = 0.0;

    double new_enemy_size   = 0.0;
    double old_enemy_size   = 0.0;

    std::vector<double> new_ammo_amount;
    std::vector<double> old_ammo_amount;

    ModelInfo(const ModelInputData& input_data)
    {
        old_army_size = input_data.start_army_size;
        old_enemy_size = input_data.start_enemy_size;

        new_ammo_amount.resize(input_data.battlefield_size / input_data.delta_x);
        old_ammo_amount.resize(new_ammo_amount.size());
    }
};

std::ostream& operator<< (std::ostream& out, const ModelInputData& input_data);

int main(int argc, char *argv[])
{
    ModelInputData model_input;
    ModelInfo model_info(model_input);

    std::cout << model_input << std::endl;

    return EXIT_SUCCESS;
}

std::ostream& operator<< (std::ostream& out, const ModelInputData& input_data)
{
    out << "-------------------------------------------------" << std::endl;
    out << "--- GentlesmanBattle Input Data" << std::endl;
    out << "-------------------------------------------------" << std::endl;
    out << "- Start Army Size    : " << input_data.start_army_size << std::endl;
    out << "- Start Enemy Size   : " << input_data.start_enemy_size << std::endl;
    out << "- Army Skill         : " << input_data.army_skill << std::endl;
    out << "- Enemy Skill        : " << input_data.enemy_skill << std::endl;
    out << "- Start Ammo         : " << input_data.start_ammo << std::endl;
    out << "- Ammo Diffusion Coef: " << input_data.ammo_diffusion_coeffient << std::endl;
    out << "- Battle Field Size  : " << input_data.battlefield_size << std::endl;
    out << "- Front Line Fraction: " << input_data.front_line_fraction << std::endl;
    out << "- Delta Time         : " << input_data.delta_time << std::endl;
    out << "- Delta X            : " << input_data.delta_x << std::endl;
    out << "--------------------------------------------------" << std::endl;

    return out;
}

std::ostream& operator<< (std::ostream& out, const ModelInfo& model_info)
{
    return out;
}

<commit_msg>Simulação inicial da batalha<commit_after>
#include <iostream>
#include <fstream>
#include <vector>
#include <stdexcept>
#include <limits>

struct ModelInputData
{
    double start_army_size;             // > 0
    double start_enemy_size;            // > 0
    double loose_battle_fraction;       // 0 < x < 1:   Porcentagem do exército que define derrota
    double army_skill;                  // 0 < x <= 1
    double enemy_skill;                 // 0 < x <= 1
    double start_ammo;                  // > 0
    double ammo_diffusion_coeffient;    // > 0
    double battlefield_size;            // > 0
    double front_line_fraction;         // 0 < x <= 1

    double delta_time;                  // > 0
    double delta_x;                     // > 0

    /**
     * @brief ModelInputData default input data
     */
    ModelInputData()
    {
        start_army_size             = 100.0;
        start_enemy_size            = 100.0;
        loose_battle_fraction       = 0.1;
        army_skill                  = 0.5;
        enemy_skill                 = 0.5;
        start_ammo                  = 1000;
        ammo_diffusion_coeffient    = 1.0;
        battlefield_size            = 10;
        front_line_fraction         = 0.1;

        delta_time                  = 0.1;
        delta_x                     = 1;
    }
};

struct ModelInfo
{
    double time             = 0.0;

    double new_army_size    = 0.0;
    double old_army_size    = 0.0;

    double new_enemy_size   = 0.0;
    double old_enemy_size   = 0.0;

    std::vector<double> new_ammo_amount;
    std::vector<double> old_ammo_amount;

    const ModelInputData& model_input;

    ModelInfo(const ModelInputData& input_data) :
        model_input(input_data)
    {
        old_army_size = input_data.start_army_size;
        old_enemy_size = input_data.start_enemy_size;

        new_ammo_amount.resize(input_data.battlefield_size / input_data.delta_x);
        old_ammo_amount.resize(new_ammo_amount.size());
    }

    void advance_time(double delta_time)
    {
        double front_line_size = model_input.front_line_fraction * old_army_size;
        double available_ammo = old_ammo_amount.back();

        new_army_size = old_army_size - delta_time * model_input.enemy_skill * front_line_size;
        old_army_size = new_army_size;

        new_enemy_size = old_enemy_size - delta_time * model_input.army_skill * available_ammo * front_line_size * old_enemy_size;
        old_enemy_size = new_enemy_size;

        time += delta_time;
    }

    bool should_stop() const
    {
        return new_army_size <= model_input.start_army_size * model_input.loose_battle_fraction ||
                new_enemy_size <= model_input.start_enemy_size * model_input.loose_battle_fraction;
    }
};

std::ostream& operator<< (std::ostream& out, const ModelInputData& input_data);

struct ModelOutput
{
    std::string model_output_filename;
    std::fstream output_file;
    const ModelInfo& model_info;

    ModelOutput(const std::string& prefix, const ModelInfo& _model_info, const ModelInputData& model_input)
        : model_output_filename(prefix + "_gentlemans_battle.dat"),
          model_info(_model_info)
    {
        output_file.open(model_output_filename, std::ios::out);

        if(!output_file.is_open())
        {
            throw std::runtime_error("Cannot open outputfile: " + model_output_filename);;
        }

        output_file << model_input << std::endl << std::endl;
        output_file << "# Time  ArmySize    EnemySize" << std::endl;
    }

    void write()
    {
        output_file << model_info.time << "\t" <<
                       model_info.old_army_size << "\t" <<
                       model_info.old_enemy_size << std::endl;
    }
};

int main(int argc, char *argv[])
{
    ModelInputData model_input;
    ModelInfo model_info(model_input);
    ModelOutput model_output("", model_info, model_input);

    model_info.new_enemy_size = 100;

    do
    {
        model_output.write();
        model_info.advance_time(model_input.delta_time);
    }
    while(!model_info.should_stop());

    return EXIT_SUCCESS;
}

std::ostream& operator<< (std::ostream& out, const ModelInputData& input_data)
{
    out << "#-------------------------------------------------" << std::endl;
    out << "#--- GentlesmanBattle Input Data" << std::endl;
    out << "#-------------------------------------------------" << std::endl;
    out << "#- Start Army Size    : " << input_data.start_army_size << std::endl;
    out << "#- Start Enemy Size   : " << input_data.start_enemy_size << std::endl;
    out << "#- Army Skill         : " << input_data.army_skill << std::endl;
    out << "#- Enemy Skill        : " << input_data.enemy_skill << std::endl;
    out << "#- Start Ammo         : " << input_data.start_ammo << std::endl;
    out << "#- Ammo Diffusion Coef: " << input_data.ammo_diffusion_coeffient << std::endl;
    out << "#- Battle Field Size  : " << input_data.battlefield_size << std::endl;
    out << "#- Front Line Fraction: " << input_data.front_line_fraction << std::endl;
    out << "#- Delta Time         : " << input_data.delta_time << std::endl;
    out << "#- Delta X            : " << input_data.delta_x << std::endl;
    out << "#--------------------------------------------------" << std::endl;

    return out;
}

<|endoftext|>


<commit_before>#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <glm/mat4x4.hpp>
#include <glm/vec3.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include <cstdlib>
#include <cassert>

#include <map>
#include <string>
#include <iostream>
#include <fstream>

#include "chip8.hpp"
#include "keys.hpp"

static GLFWwindow *
setupWindow(int width, int height, const char * title);

static std::vector<uint8_t>
readAllBytes(const char * path);

static std::string
readAllChars(const char * path);

static cee::Keys
getKeyStates(GLFWwindow * window);

static GLuint
makeShader(GLenum type, const std::string & src);

static GLuint
makeProgram(std::vector<GLuint> shaders);

static std::map<int, uint8_t>
keyboardLayout
{
    {GLFW_KEY_X, 0},
    {GLFW_KEY_1, 1},
    {GLFW_KEY_2, 2},
    {GLFW_KEY_3, 3},
    {GLFW_KEY_Q, 4},
    {GLFW_KEY_W, 5},
    {GLFW_KEY_E, 6},
    {GLFW_KEY_A, 7},
    {GLFW_KEY_S, 8},
    {GLFW_KEY_D, 9},
    {GLFW_KEY_Z, 0xA},
    {GLFW_KEY_C, 0xB},
    {GLFW_KEY_4, 0xC},
    {GLFW_KEY_R, 0xD},
    {GLFW_KEY_F, 0xE},
    {GLFW_KEY_V, 0xF}
};

static inline float
mapRangeWidth(float index);

static inline float
mapRangeHeight(float index);

static std::map<GLFWwindow *, uint8_t>
lastKeyPressed;

static constexpr int
WIDTH = 800;

static constexpr int
HEIGHT = 400;

static constexpr float
PX_WIDTH = (1.0f / WIDTH) * (WIDTH / 64.0f);

static constexpr float
PX_HEIGHT = (1.0f / HEIGHT) * (HEIGHT / 32.0f);

int main(int argc, char ** argv)
{
    auto pathToRom = std::string();

    if (argc == 2)
    {
        pathToRom = argv[1];
    }
    else
    {
        printf("Chip8 Error: Wrong number of arguments\n");
        glfwTerminate();
        return -1;
    }

    cee::Chip8 chip;
    chip.loadProgram(readAllBytes(pathToRom.c_str()));

    auto window = setupWindow(WIDTH, HEIGHT, "Chip8 Emulator");

    constexpr GLfloat pxVerts[] =
    {
        -1.0f,  1.0f, 0.0f, // Top Left
         1.0f,  1.0f, 0.0f, // Top Right
        -1.0f, -1.0f, 0.0f, // Bottom Left
         1.0f, -1.0f, 0.0f  // Bottom Right
    };

    constexpr GLuint pxIndices[] =
    {
        0, 1, 2,
        2, 1, 3
    };

    // Initialize the VAO and other buffers associated
    // with drawing an emulated pixel.
    GLuint vao, vbo, ibo;
    glGenVertexArrays(1, &vao);

    glBindVertexArray(vao);
    {
        glGenBuffers(1, &vbo);
        glGenBuffers(1, &ibo);

        // VBO
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, sizeof(pxVerts), &pxVerts, GL_STATIC_DRAW);

        // IBO
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(pxIndices), &pxIndices, GL_STATIC_DRAW);

        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr);
        glEnableVertexAttribArray(0);
    }
    glBindVertexArray(0);

    // Current Vertex Shader
    const auto pxVertexSrc = readAllChars("data/shaders/px_vertex.glsl");
    const auto pxVertex = makeShader(GL_VERTEX_SHADER, pxVertexSrc);

    // Current Fragment Shader
    const auto pxFragmentSrc = readAllChars("data/shaders/px_fragment.glsl");
    const auto pxFragment = makeShader(GL_FRAGMENT_SHADER, pxFragmentSrc);

    // Current Shader Program
    const auto pxProgram = makeProgram({pxVertex, pxFragment});
    glUseProgram(pxProgram);

    glfwShowWindow(window);
    while (! glfwWindowShouldClose(window))
    {
        chip.updateKeys(getKeyStates(window));
        chip.updateCycle();

        // Clear back buffer and background color.
        glClear(GL_COLOR_BUFFER_BIT);
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

        glBindVertexArray(vao);
        const auto gfx = chip.getGfx();
        for (int i = 0; i < 32; ++i)
        {
            // Maps the width resolution [0-HEIGHT] to [-1.0-1.0]
            auto y = - mapRangeHeight(i);
            auto l = i * 64;

            for (int j = 0; j < 64; ++j)
            {
                if (gfx[l + j] == 1)
                {
                    // Maps the width resolution [0-WIDTH] to [-1.0-1.0]
                    auto x = mapRangeWidth(j);
                    auto ident = glGetUniformLocation(pxProgram, "PxModel");
                    auto model = glm::mat4(1.0f);
                    model = glm::translate(model, glm::vec3(x, y, 0.0f));
                    model = glm::scale(model, glm::vec3(PX_WIDTH, PX_HEIGHT, 1.0f));
                    glUniformMatrix4fv(ident, 1, GL_FALSE, glm::value_ptr(model));
                    glDrawElements(GL_TRIANGLES, sizeof(pxIndices), GL_UNSIGNED_INT, nullptr);
                }
            }
        }
        glBindVertexArray(0);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    // Cleanup resources
    glDeleteProgram(pxProgram);
    glDeleteShader(pxVertex);
    glDeleteShader(pxFragment);
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &ibo);
    glDeleteBuffers(1, &vbo);
    glfwTerminate();
    return 0;
}

GLFWwindow *
setupWindow(int width, int height, const char * title)
{
    glfwSetErrorCallback([](int err, const char * desc)
    {
        std::cerr << "GLFW Error: " << desc << "\n";
    });

    if (! glfwInit())
    {
        std::cerr << "GLEW Error: Could not initialise GLFW\n";
        std::exit(-1);
    }

    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

    auto window = glfwCreateWindow(width, height, title, nullptr, nullptr);

    glfwMakeContextCurrent(window);

    // Register window to its own last key press state.
    lastKeyPressed.emplace(window, GLFW_KEY_UNKNOWN);

    // Callback Parameters.
    // k: Key
    // s: Scan Code
    // a: Action
    // m: Key Mode
    glfwSetKeyCallback(window, [](GLFWwindow * w, int k, int s, int a, int m)
    {
        if (k == GLFW_KEY_ESCAPE && a == GLFW_PRESS)
        {
            glfwSetWindowShouldClose(w, GL_TRUE);
        }

        if (keyboardLayout.count(k) && a == GLFW_PRESS)
        {
            lastKeyPressed[w] = keyboardLayout[k];
        }
    });

    // Load GL extensions
    glewExperimental = GL_TRUE;
    if (glewInit() != GLEW_OK)
    {
        std::cerr << "GLEW Error: Could not initialise GLEW\n";
        std::exit(-1);
    }

    // Sync NDC Coordinates with window resolution
    {
        int w, h; // width, height
        glfwGetFramebufferSize(window, &w, &h);
        glViewport(0, 0, w, h);
    }

    return window;
}

cee::Keys
getKeyStates(GLFWwindow * window)
{
    cee::Keys keys;

    for (auto & pair : keyboardLayout)
    {
        auto state = pair.first;
        auto index = pair.second;
        auto offset = (1 << index);
        auto result = (glfwGetKey(window, state) == GLFW_PRESS ? offset : 0);
        keys.keysPressed |= result;
    }

    keys.lastKeyPressed = lastKeyPressed[window];

    return keys;
}

std::vector<uint8_t>
readAllBytes(const char * path)
{
    try
    {
        std::ifstream file;
        file.exceptions(std::ios::failbit);
        file.open(path, std::ios::binary|std::ios::ate);
        auto length = file.tellg();
        std::vector<uint8_t> result(length);
        file.seekg(0, std::ios::beg);
        file.read((char*)&result[0], length);
        file.close();
        return result;
    }
    catch (std::ios_base::failure & err)
    {
        std::cerr << "File Error: Can't open file with path: " << path << "\n";
    }
    catch (std::bad_alloc & err)
    {
        std::cerr << "File Error: Can't open file with path: " << path << "\n";
    }

    return {};
}

std::string
readAllChars(const char * path)
{
    try
    {
        std::ifstream file;
        file.exceptions(std::ios::failbit);
        file.open(path, std::ios::ate);
        auto length = file.tellg();
        std::string result(length, ' ');
        file.seekg(0, std::ios::beg);
        file.read(&result[0], length);
        file.close();
        return result;
    }
    catch (std::ios_base::failure & err)
    {
        std::cerr << "File Error: Can't open file with path: " << path << "\n";
    }
    catch (std::bad_alloc & err)
    {
        std::cerr << "File Error: Can't open file with path: " << path << "\n";
    }

    return "";
}

GLuint
makeShader(GLenum type, const std::string & src)
{
    const auto id = glCreateShader(type);
    const auto cp = src.c_str();
    glShaderSource(id, 1, &cp, nullptr);
    glCompileShader(id);
    return id;
}

GLuint
makeProgram(std::vector<GLuint> shaders)
{
    const auto id = glCreateProgram();

    for (const auto s : shaders)
        glAttachShader(id, s);

    glLinkProgram(id);
    return id;
}

static inline float
mapRangeWidth(float index)
{
    constexpr auto h = static_cast<float>(WIDTH);
    constexpr auto x = 2.0f / h;
    constexpr auto s = h / 64.0f;
    return (x * index * s) - 0.98f;
}

static inline float
mapRangeHeight(float index)
{
    constexpr auto h = static_cast<float>(HEIGHT);
    constexpr auto x = 2.0f / h;
    constexpr auto s = h / 32.0f;
    return (x * index * s) - 0.96f;
}
<commit_msg>Remove unnecessary keywords for consistency.<commit_after>#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <glm/mat4x4.hpp>
#include <glm/vec3.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include <cstdlib>
#include <cassert>

#include <map>
#include <string>
#include <iostream>
#include <fstream>

#include "chip8.hpp"
#include "keys.hpp"

static GLFWwindow *
setupWindow(int width, int height, const char * title);

static std::vector<uint8_t>
readAllBytes(const char * path);

static std::string
readAllChars(const char * path);

static cee::Keys
getKeyStates(GLFWwindow * window);

static GLuint
makeShader(GLenum type, const std::string & src);

static GLuint
makeProgram(std::vector<GLuint> shaders);

static std::map<int, uint8_t>
keyboardLayout
{
    {GLFW_KEY_X, 0},
    {GLFW_KEY_1, 1},
    {GLFW_KEY_2, 2},
    {GLFW_KEY_3, 3},
    {GLFW_KEY_Q, 4},
    {GLFW_KEY_W, 5},
    {GLFW_KEY_E, 6},
    {GLFW_KEY_A, 7},
    {GLFW_KEY_S, 8},
    {GLFW_KEY_D, 9},
    {GLFW_KEY_Z, 0xA},
    {GLFW_KEY_C, 0xB},
    {GLFW_KEY_4, 0xC},
    {GLFW_KEY_R, 0xD},
    {GLFW_KEY_F, 0xE},
    {GLFW_KEY_V, 0xF}
};

static inline float
mapRangeWidth(float index);

static inline float
mapRangeHeight(float index);

static std::map<GLFWwindow *, uint8_t>
lastKeyPressed;

static constexpr int
WIDTH = 800;

static constexpr int
HEIGHT = 400;

static constexpr float
PX_WIDTH = (1.0f / WIDTH) * (WIDTH / 64.0f);

static constexpr float
PX_HEIGHT = (1.0f / HEIGHT) * (HEIGHT / 32.0f);

int main(int argc, char ** argv)
{
    auto pathToRom = std::string();

    if (argc == 2)
    {
        pathToRom = argv[1];
    }
    else
    {
        printf("Chip8 Error: Wrong number of arguments\n");
        glfwTerminate();
        return -1;
    }

    cee::Chip8 chip;
    chip.loadProgram(readAllBytes(pathToRom.c_str()));

    auto window = setupWindow(WIDTH, HEIGHT, "Chip8 Emulator");

    constexpr GLfloat pxVerts[] =
    {
        -1.0f,  1.0f, 0.0f, // Top Left
         1.0f,  1.0f, 0.0f, // Top Right
        -1.0f, -1.0f, 0.0f, // Bottom Left
         1.0f, -1.0f, 0.0f  // Bottom Right
    };

    constexpr GLuint pxIndices[] =
    {
        0, 1, 2,
        2, 1, 3
    };

    // Initialize the VAO and other buffers associated
    // with drawing an emulated pixel.
    GLuint vao, vbo, ibo;
    glGenVertexArrays(1, &vao);

    glBindVertexArray(vao);
    {
        glGenBuffers(1, &vbo);
        glGenBuffers(1, &ibo);

        // VBO
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, sizeof(pxVerts), &pxVerts, GL_STATIC_DRAW);

        // IBO
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(pxIndices), &pxIndices, GL_STATIC_DRAW);

        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr);
        glEnableVertexAttribArray(0);
    }
    glBindVertexArray(0);

    // Current Vertex Shader
    const auto pxVertexSrc = readAllChars("data/shaders/px_vertex.glsl");
    const auto pxVertex = makeShader(GL_VERTEX_SHADER, pxVertexSrc);

    // Current Fragment Shader
    const auto pxFragmentSrc = readAllChars("data/shaders/px_fragment.glsl");
    const auto pxFragment = makeShader(GL_FRAGMENT_SHADER, pxFragmentSrc);

    // Current Shader Program
    const auto pxProgram = makeProgram({pxVertex, pxFragment});
    glUseProgram(pxProgram);

    glfwShowWindow(window);
    while (! glfwWindowShouldClose(window))
    {
        chip.updateKeys(getKeyStates(window));
        chip.updateCycle();

        // Clear back buffer and background color.
        glClear(GL_COLOR_BUFFER_BIT);
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

        glBindVertexArray(vao);
        const auto gfx = chip.getGfx();
        for (int i = 0; i < 32; ++i)
        {
            // Maps the width resolution [0-HEIGHT] to [-1.0-1.0]
            auto y = - mapRangeHeight(i);
            auto l = i * 64;

            for (int j = 0; j < 64; ++j)
            {
                if (gfx[l + j] == 1)
                {
                    // Maps the width resolution [0-WIDTH] to [-1.0-1.0]
                    auto x = mapRangeWidth(j);
                    auto ident = glGetUniformLocation(pxProgram, "PxModel");
                    auto model = glm::mat4(1.0f);
                    model = glm::translate(model, glm::vec3(x, y, 0.0f));
                    model = glm::scale(model, glm::vec3(PX_WIDTH, PX_HEIGHT, 1.0f));
                    glUniformMatrix4fv(ident, 1, GL_FALSE, glm::value_ptr(model));
                    glDrawElements(GL_TRIANGLES, sizeof(pxIndices), GL_UNSIGNED_INT, nullptr);
                }
            }
        }
        glBindVertexArray(0);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    // Cleanup resources
    glDeleteProgram(pxProgram);
    glDeleteShader(pxVertex);
    glDeleteShader(pxFragment);
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &ibo);
    glDeleteBuffers(1, &vbo);
    glfwTerminate();
    return 0;
}

GLFWwindow *
setupWindow(int width, int height, const char * title)
{
    glfwSetErrorCallback([](int err, const char * desc)
    {
        std::cerr << "GLFW Error: " << desc << "\n";
    });

    if (! glfwInit())
    {
        std::cerr << "GLEW Error: Could not initialise GLFW\n";
        std::exit(-1);
    }

    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

    auto window = glfwCreateWindow(width, height, title, nullptr, nullptr);

    glfwMakeContextCurrent(window);

    // Register window to its own last key press state.
    lastKeyPressed.emplace(window, GLFW_KEY_UNKNOWN);

    // Callback Parameters.
    // k: Key
    // s: Scan Code
    // a: Action
    // m: Key Mode
    glfwSetKeyCallback(window, [](GLFWwindow * w, int k, int s, int a, int m)
    {
        if (k == GLFW_KEY_ESCAPE && a == GLFW_PRESS)
        {
            glfwSetWindowShouldClose(w, GL_TRUE);
        }

        if (keyboardLayout.count(k) && a == GLFW_PRESS)
        {
            lastKeyPressed[w] = keyboardLayout[k];
        }
    });

    // Load GL extensions
    glewExperimental = GL_TRUE;
    if (glewInit() != GLEW_OK)
    {
        std::cerr << "GLEW Error: Could not initialise GLEW\n";
        std::exit(-1);
    }

    // Sync NDC Coordinates with window resolution
    {
        int w, h; // width, height
        glfwGetFramebufferSize(window, &w, &h);
        glViewport(0, 0, w, h);
    }

    return window;
}

cee::Keys
getKeyStates(GLFWwindow * window)
{
    cee::Keys keys;

    for (auto & pair : keyboardLayout)
    {
        auto state = pair.first;
        auto index = pair.second;
        auto offset = (1 << index);
        auto result = (glfwGetKey(window, state) == GLFW_PRESS ? offset : 0);
        keys.keysPressed |= result;
    }

    keys.lastKeyPressed = lastKeyPressed[window];

    return keys;
}

std::vector<uint8_t>
readAllBytes(const char * path)
{
    try
    {
        std::ifstream file;
        file.exceptions(std::ios::failbit);
        file.open(path, std::ios::binary|std::ios::ate);
        auto length = file.tellg();
        std::vector<uint8_t> result(length);
        file.seekg(0, std::ios::beg);
        file.read((char*)&result[0], length);
        file.close();
        return result;
    }
    catch (std::ios_base::failure & err)
    {
        std::cerr << "File Error: Can't open file with path: " << path << "\n";
    }
    catch (std::bad_alloc & err)
    {
        std::cerr << "File Error: Can't open file with path: " << path << "\n";
    }

    return {};
}

std::string
readAllChars(const char * path)
{
    try
    {
        std::ifstream file;
        file.exceptions(std::ios::failbit);
        file.open(path, std::ios::ate);
        auto length = file.tellg();
        std::string result(length, ' ');
        file.seekg(0, std::ios::beg);
        file.read(&result[0], length);
        file.close();
        return result;
    }
    catch (std::ios_base::failure & err)
    {
        std::cerr << "File Error: Can't open file with path: " << path << "\n";
    }
    catch (std::bad_alloc & err)
    {
        std::cerr << "File Error: Can't open file with path: " << path << "\n";
    }

    return "";
}

GLuint
makeShader(GLenum type, const std::string & src)
{
    const auto id = glCreateShader(type);
    const auto cp = src.c_str();
    glShaderSource(id, 1, &cp, nullptr);
    glCompileShader(id);
    return id;
}

GLuint
makeProgram(std::vector<GLuint> shaders)
{
    const auto id = glCreateProgram();

    for (const auto s : shaders)
        glAttachShader(id, s);

    glLinkProgram(id);
    return id;
}

float
mapRangeWidth(float index)
{
    constexpr auto h = static_cast<float>(WIDTH);
    constexpr auto x = 2.0f / h;
    constexpr auto s = h / 64.0f;
    return (x * index * s) - 0.98f;
}

float
mapRangeHeight(float index)
{
    constexpr auto h = static_cast<float>(HEIGHT);
    constexpr auto x = 2.0f / h;
    constexpr auto s = h / 32.0f;
    return (x * index * s) - 0.96f;
}
<|endoftext|>


<commit_before>/* -*- coding: utf-8 -*-
*   Copyright (c) 2010, Tim Kleinschmit.  This file is
*   licensed under the General Public License version 3 or later.
*   See the COPYRIGHT file.
*/

#include <QtGui/QApplication>
#include "mainwindow.h"
#include "iconloader.h"

int main(int argc, char *argv[])
{
#ifdef Q_OS_UNIX
    if (geteuid() == 0) {
        fprintf(stderr, qPrintable(QObject::tr("Simba is not supposed to be run as root").append("\n")));
        exit(0);
    }
#endif
    Q_INIT_RESOURCE(data);

    QApplication a(argc, argv);

    // QSettings stuff
    QCoreApplication::setApplicationName ("Simba");
    QCoreApplication::setApplicationVersion ("0.94");
    QCoreApplication::setOrganizationDomain ("azd325.github.com/simba/");
    QCoreApplication::setOrganizationName (QCoreApplication::applicationName ());

    // Icons
    IconLoader::Init();

    // delivery the cli argument
    MainWindow w(QCoreApplication::arguments());
    w.show();
    return a.exec();
}

<commit_msg>change ouput thin to qt methods<commit_after>/* -*- coding: utf-8 -*-
*   Copyright (c) 2010, Tim Kleinschmit.  This file is
*   licensed under the General Public License version 3 or later.
*   See the COPYRIGHT file.
*/

#include <QtGui/QApplication>
#include <QTranslator>
#include <QLibraryInfo>

#include "mainwindow.h"
#include "iconloader.h"

int main(int argc, char *argv[])
{
#ifdef Q_OS_UNIX
    if (geteuid() == 0) {
        qDebug ()<< QObject::tr("Simba is not supposed to be run as root\n");
        exit(0);
    }
#endif
    Q_INIT_RESOURCE(data);

    QApplication a(argc, argv);

    // check tray exist
    if (!QSystemTrayIcon::isSystemTrayAvailable()) {
        QMessageBox::critical(0, QObject::tr("Systray"), QObject::tr("I couldn't detect any system tray on this system."));
    }

    // install qt translator
    QTranslator qtTranslator;
    qtTranslator.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
    a.installTranslator(&qtTranslator);

    // QSettings stuff
    QCoreApplication::setApplicationName ("Simba");
    QCoreApplication::setApplicationVersion ("0.94");
    QCoreApplication::setOrganizationDomain ("azd325.github.com/simba/");
    QCoreApplication::setOrganizationName (QCoreApplication::applicationName ());

    // Icons
    IconLoader::Init();

    // delivery the cli argument
    MainWindow w(QCoreApplication::arguments());
    w.show();
    return a.exec();
}

<|endoftext|>


<commit_before>#include <iostream>
#include <vector>

#include "World.h"
#include "Renderer.h"
#include "ForwardRasterizer.h"
#include "DeferredRasterizer.h"
#include "Camera.h"
#include "Light.h"
#include "DirectionalLight.h"
#include "PointLight.h"
#include "OrthographicCamera.h"
#include "PerspectiveCamera.h"
#include "Constants.h"

// Forward declaration utils functions
void buildAlignedBox(std::vector<Point3D>& vertices, std::vector<Vector2D>& texture_coords, std::vector<uint32_t>& indices, const float side);
GeometryObject* buildPlainBox(Material* material, const RGBColor& color, const Point3D& center, const float side);
GeometryObject* buildTexturedBox(Material* material, const Point3D& center, const float side);

void buildHorizontalPlane(std::vector<Point3D>& vertices, std::vector<Vector2D>& texture_coords, std::vector<uint32_t>& indices, const float side);
GeometryObject* buildTexturedPlane(Material* material, const Point3D& center, const float side);
GeometryObject* buildPlainPlane(Material* material, const RGBColor& color, const Point3D& center, const float side);
GeometryObject* buildMultiColorBox(Material* material, const Point3D& center, const float side);

const std::vector<GeometryObject*> setupFlatScene();
const std::vector<GeometryObject*> setupTexturedScene();

Camera * camera;
Renderer * renderer;
int main (){
  std::vector<Light*> lights = {
    new DirectionalLight(Colors::WHITE, Vector3D(1, 0.5, -1))
  };
  const std::vector<GeometryObject*> objects_flat = setupFlatScene();
  const std::vector<GeometryObject*> objects_textured = setupTexturedScene();

  World * world = new World(objects_textured, lights, camera);
#ifdef _FORWARD
  renderer = new ForwardRasterizer(world);
#endif

#ifdef _DEFERRED
  renderer = new DeferredRasterizer(world);
#endif

#ifdef _ORTHOGRAPHIC
  camera = new OrthographicCamera(CAMERA_POS, CAMERA_TARGET, IMAGE_HEIGHT, IMAGE_WIDTH, renderer);
#endif

#ifdef _PERSPECTIVE
  camera = new PerspectiveCamera(CAMERA_POS, CAMERA_TARGET, IMAGE_HEIGHT, IMAGE_WIDTH, renderer);
#endif
  world->m_camera = camera;
  renderer->render();
  renderer->export_output(IMAGE_NAME);
  return 0;
}

const std::vector<GeometryObject*> setupFlatScene() {
  std::vector<GeometryObject*> objects;

  // Objects
  GeometryObject* ground = buildPlainPlane(Materials::FLAT_PLASTIC, Colors::GREY, Point3D(0, 0, 0), 500);
  objects.push_back(ground);

  GeometryObject* flat_box = buildPlainBox(Materials::FLAT_PLASTIC, Colors::RED, Point3D(0, 0, 0), 100);
  flat_box->translate(Vector3D(150, 50, 100));
  flat_box->rotate(0, 45, 0);
  objects.push_back(flat_box);

  GeometryObject* flat_box2 = buildPlainBox(Materials::FLAT_PLASTIC, Colors::CYAN, Point3D(150, 125, 100), 50);
  objects.push_back(flat_box2);

  GeometryObject* flying_box = buildPlainBox(Materials::FLAT_PLASTIC, Colors::YELLOW, Point3D(-100, 120, 75), 75);
  flying_box->rotate(45, -45, 45);
  objects.push_back(flying_box);

  GeometryObject* multicolor_box = buildMultiColorBox(Materials::FLAT_PLASTIC, Point3D(-100, 50, -90), 100);
  multicolor_box->rotate(0, -45, 0);
  objects.push_back(multicolor_box);

  GeometryObject* small_box2 = buildPlainBox(Materials::FLAT_PLASTIC, Colors::PURPLE, Point3D(150, 75, -220), 75);
  objects.push_back(small_box2);
  return objects;
}

const std::vector<GeometryObject*> setupTexturedScene() {
  std::vector<GeometryObject*> objects;

  // Objects
  GeometryObject* ground = buildTexturedPlane(Materials::BRICK, Point3D(0, 0, 0), 500);
  objects.push_back(ground);

  GeometryObject* flat_box = buildTexturedBox(Materials::BOX, Point3D(0, 0, 0), 100);
  flat_box->translate(Vector3D(150, 50, 100));
  flat_box->rotate(0, 45, 0);
  objects.push_back(flat_box);

  GeometryObject* flat_box2 = buildTexturedBox(Materials::BOX, Point3D(150, 125, 100), 50);
  objects.push_back(flat_box2);

  GeometryObject* flying_box = buildTexturedBox(Materials::BOX, Point3D(-100, 120, 75), 75);
  flying_box->rotate(45, -45, 45);
  objects.push_back(flying_box);

  GeometryObject* small_box1 = buildTexturedBox(Materials::BOX, Point3D(-100, 50, -90), 100);
  small_box1->rotate(0, -45, 0);
  objects.push_back(small_box1);

  GeometryObject* small_box2 = buildTexturedBox(Materials::DEFAULT, Point3D(150, 75, -220), 75);
  objects.push_back(small_box2);

  return objects;
}

void buildAlignedBox(std::vector<Point3D>& vertices, std::vector<Vector2D>& texture_coords, std::vector<uint32_t>& indices, const float side) {
  const float half_diagonal = (side / 2) / sin(PI / 2); // Distance to center
                                                        // Front
  const Point3D v1(-half_diagonal, -half_diagonal, -half_diagonal);
  const Point3D v2(v1.x, v1.y + side, v1.z);
  const Point3D v3(v1.x + side, v1.y + side, v1.z);
  const Point3D v4(v1.x + side, v1.y, v1.z);
  // Back
  const Point3D v5(v1.x, v1.y, v1.z + side);
  const Point3D v6(v2.x, v2.y, v2.z + side);
  const Point3D v7(v3.x, v3.y, v3.z + side);
  const Point3D v8(v4.x, v4.y, v4.z + side);

  vertices = {
    // Front face
    v1, v2, v3, v4,

    // Back face
    v5, v6, v7, v8,

    // Top face
    v2, v6, v7, v3,

    // Bottom face
    v1, v5, v8, v4,

    // Left face
    v1, v2, v6, v5,

    // Right face
    v4, v3, v7, v8
  };

  texture_coords = {
    // Texture coordinates
    // Front face
    Vector2D(0, 0),
    Vector2D(0, 1),
    Vector2D(1, 1),
    Vector2D(1, 0),

    // Back face
    Vector2D(1, 1),
    Vector2D(1, 0),
    Vector2D(0, 0),
    Vector2D(0, 1),
    // Top face
    Vector2D(0, 0),
    Vector2D(0, 1),
    Vector2D(1, 1),
    Vector2D(1, 0),
    //// Bottom face
    Vector2D(0, 0),
    Vector2D(0, 1),
    Vector2D(1, 1),
    Vector2D(1, 0),
    //// Left face
    Vector2D(1, 0),
    Vector2D(1, 1),
    Vector2D(0, 1),
    Vector2D(0, 0),
    //// Right face
    Vector2D(0, 0),
    Vector2D(0, 1),
    Vector2D(1, 1),
    Vector2D(1, 0)
  };

  indices = {
    // Vertices indices
    // Front face
    0, 1, 2,
    2, 3, 0,

    // Back face
    6, 5, 4,
    4, 7, 6,

    // Top face
    8, 9, 10,
    10, 11, 8,

    // Bottom face
    14, 13, 12,
    12, 15, 14,

    // Left face
    16, 19, 18,
    18, 17, 16,

    // Right face
    20, 21, 22,
    22, 23, 20
  };
}

GeometryObject* buildPlainBox(Material* material, const RGBColor& color, const Point3D& center, const float side) {
  const std::vector<RGBColor> colors = std::vector<RGBColor>(24, color);

  std::vector<Point3D> vertices;
  std::vector<Vector2D> texture_coords;
  std::vector<uint32_t> indices;
  buildAlignedBox(vertices, texture_coords, indices, side);
  GeometryObject* box = new GeometryObject(material, vertices, colors, texture_coords, indices, center);

  return box;
}

GeometryObject* buildMultiColorBox(Material* material, const Point3D& center, const float side) {
  const std::vector<RGBColor> colors = {
    Colors::RED,
    Colors::GREEN,
    Colors::RED,
    Colors::BLUE,

    Colors::RED,
    Colors::GREEN,
    Colors::RED,
    Colors::BLUE,

    Colors::RED,
    Colors::GREEN,
    Colors::RED,
    Colors::BLUE,

    Colors::RED,
    Colors::GREEN,
    Colors::RED,
    Colors::BLUE,

    Colors::RED,
    Colors::GREEN,
    Colors::RED,
    Colors::BLUE,

    Colors::RED,
    Colors::GREEN,
    Colors::RED,
    Colors::BLUE,
  };

  std::vector<Point3D> vertices;
  std::vector<Vector2D> texture_coords;
  std::vector<uint32_t> indices;
  buildAlignedBox(vertices, texture_coords, indices, side);
  GeometryObject* box = new GeometryObject(material, vertices, colors, texture_coords, indices, center);

  return box;
}

GeometryObject* buildTexturedBox(Material* material, const Point3D& center, const float side) {
  std::vector<Point3D> vertices;
  std::vector<Vector2D> texture_coords;
  std::vector<uint32_t> indices;
  buildAlignedBox(vertices, texture_coords, indices, side);
  GeometryObject* box = new GeometryObject(material, vertices, std::vector<RGBColor>(), texture_coords, indices, center);
  return box;
}

void buildHorizontalPlane(std::vector<Point3D>& vertices, std::vector<Vector2D>& texture_coords, std::vector<uint32_t>& indices, const float side) {
  const float half_diagonal = (side / 2) / sin(PI / 2); // Distance to center

  const Point3D v1(-half_diagonal, 0, -half_diagonal);
  const Point3D v2(v1.x, v1.y, v1.z + side);
  const Point3D v3(v1.x + side, v1.y, v1.z + side);
  const Point3D v4(v1.x + side, v1.y, v1.z);

  vertices = {
    // Vertices positions
    v1, v2, v3, v4
  };

  texture_coords = {
    // Texture coordinates
    Vector2D(0, 0),
    Vector2D(0, 2),
    Vector2D(2, 2),
    Vector2D(2, 0),
  };

  indices = {
    // Indices
    0, 1, 2,
    2, 3, 0
  };
}

GeometryObject* buildPlainPlane(Material* material, const RGBColor& color, const Point3D& center, const float side) {
  const std::vector<RGBColor> colors = std::vector<RGBColor>(4, color);
  std::vector<Point3D> vertices;
  std::vector<Vector2D> texture_coords;
  std::vector<uint32_t> indices;
  buildHorizontalPlane(vertices, texture_coords, indices, side);
  GeometryObject* box = new GeometryObject(material, vertices, colors, texture_coords, indices, center);
  return box;
}

GeometryObject* buildTexturedPlane(Material* material, const Point3D& center, const float side) {
  std::vector<Point3D> vertices;
  std::vector<Vector2D> texture_coords;
  std::vector<uint32_t> indices;
  buildHorizontalPlane(vertices, texture_coords, indices, side);
  GeometryObject* box = new GeometryObject(material, vertices, std::vector<RGBColor>(), texture_coords, indices, center);
  return box;
}<commit_msg>Added shadows and moved some static geometry<commit_after>#include <iostream>
#include <vector>

#include "World.h"
#include "Renderer.h"
#include "ForwardRasterizer.h"
#include "DeferredRasterizer.h"
#include "Camera.h"
#include "Light.h"
#include "DirectionalLight.h"
#include "PointLight.h"
#include "OrthographicCamera.h"
#include "PerspectiveCamera.h"
#include "Constants.h"

// Forward declaration utils functions
void buildAlignedBox(std::vector<Point3D>& vertices, std::vector<Vector2D>& texture_coords, std::vector<uint32_t>& indices, const float side);
GeometryObject* buildPlainBox(Material* material, const RGBColor& color, const Point3D& center, const float side);
GeometryObject* buildTexturedBox(Material* material, const Point3D& center, const float side);

void buildHorizontalPlane(std::vector<Point3D>& vertices, std::vector<Vector2D>& texture_coords, std::vector<uint32_t>& indices, const float side);
GeometryObject* buildTexturedPlane(Material* material, const Point3D& center, const float side);
GeometryObject* buildPlainPlane(Material* material, const RGBColor& color, const Point3D& center, const float side);
GeometryObject* buildMultiColorBox(Material* material, const Point3D& center, const float side);

const std::vector<GeometryObject*> setupFlatScene();
const std::vector<GeometryObject*> setupTexturedScene();

Camera * camera;
Renderer * renderer;
int main (){
  std::vector<Light*> lights = {
    new DirectionalLight(Colors::WHITE, Vector3D(1, 0.4, -1))
  };
  const std::vector<GeometryObject*> objects_flat = setupFlatScene();
  const std::vector<GeometryObject*> objects_textured = setupTexturedScene();

  World * world = new World(objects_flat, lights, camera);
#ifdef _FORWARD
  renderer = new ForwardRasterizer(world);
#endif

#ifdef _DEFERRED
  renderer = new DeferredRasterizer(world);
#endif

#ifdef _ORTHOGRAPHIC
  camera = new OrthographicCamera(CAMERA_POS, CAMERA_TARGET, IMAGE_HEIGHT, IMAGE_WIDTH, renderer);
#endif

#ifdef _PERSPECTIVE
  camera = new PerspectiveCamera(CAMERA_POS, CAMERA_TARGET, IMAGE_HEIGHT, IMAGE_WIDTH, renderer);
#endif
  world->m_camera = camera;
  renderer->render();
  renderer->export_output(IMAGE_NAME);
  return 0;
}

const std::vector<GeometryObject*> setupFlatScene() {
  std::vector<GeometryObject*> objects;

  // Objects

  GeometryObject* ground = buildPlainPlane(Materials::FLAT_PLASTIC, Colors::GREY, Point3D(0, 0, 0), 500);
  objects.push_back(ground);

  GeometryObject* flat_box = buildPlainBox(Materials::FLAT_PLASTIC, Colors::RED, Point3D(0, 0, 0), 100);
  flat_box->translate(Vector3D(150, 50, 100));
  flat_box->rotate(0, 45, 0);
  objects.push_back(flat_box);

  GeometryObject* flat_box2 = buildPlainBox(Materials::FLAT_PLASTIC, Colors::CYAN, Point3D(150, 125, 100), 50);
  objects.push_back(flat_box2);

  GeometryObject* flying_box = buildPlainBox(Materials::FLAT_PLASTIC, Colors::YELLOW, Point3D(-100, 120, 75), 75);
  flying_box->rotate(45, -45, 45);
  objects.push_back(flying_box);

  GeometryObject* multicolor_box = buildMultiColorBox(Materials::FLAT_PLASTIC, Point3D(-100, 50, -90), 100);
  multicolor_box->rotate(0, -45, 0);
  objects.push_back(multicolor_box);

  GeometryObject* small_box2 = buildPlainBox(Materials::FLAT_PLASTIC, Colors::PURPLE, Point3D(150, 37.5, -220), 75);
  objects.push_back(small_box2);
  return objects;
}

const std::vector<GeometryObject*> setupTexturedScene() {
  std::vector<GeometryObject*> objects;

  // Objects
  GeometryObject* ground = buildTexturedPlane(Materials::BRICK, Point3D(0, 0, 0), 500);
  objects.push_back(ground);

  GeometryObject* flat_box = buildTexturedBox(Materials::BOX, Point3D(0, 0, 0), 100);
  flat_box->translate(Vector3D(150, 50, 100));
  flat_box->rotate(0, 45, 0);
  objects.push_back(flat_box);

  GeometryObject* flat_box2 = buildTexturedBox(Materials::BOX, Point3D(150, 125, 100), 50);
  objects.push_back(flat_box2);

  GeometryObject* flying_box = buildTexturedBox(Materials::BOX, Point3D(-100, 120, 75), 75);
  flying_box->rotate(45, -45, 45);
  objects.push_back(flying_box);

  GeometryObject* small_box1 = buildTexturedBox(Materials::BOX, Point3D(-100, 50, -90), 100);
  small_box1->rotate(0, -45, 0);
  objects.push_back(small_box1);

  GeometryObject* default_box = buildTexturedBox(Materials::DEFAULT, Point3D(150, 37.5, -220), 75);
  objects.push_back(default_box);

  return objects;
}

void buildAlignedBox(std::vector<Point3D>& vertices, std::vector<Vector2D>& texture_coords, std::vector<uint32_t>& indices, const float side) {
  const float half_diagonal = (side / 2) / sin(PI / 2); // Distance to center
                                                        // Front
  const Point3D v1(-half_diagonal, -half_diagonal, -half_diagonal);
  const Point3D v2(v1.x, v1.y + side, v1.z);
  const Point3D v3(v1.x + side, v1.y + side, v1.z);
  const Point3D v4(v1.x + side, v1.y, v1.z);
  // Back
  const Point3D v5(v1.x, v1.y, v1.z + side);
  const Point3D v6(v2.x, v2.y, v2.z + side);
  const Point3D v7(v3.x, v3.y, v3.z + side);
  const Point3D v8(v4.x, v4.y, v4.z + side);

  vertices = {
    // Front face
    v1, v2, v3, v4,

    // Back face
    v5, v6, v7, v8,

    // Top face
    v2, v6, v7, v3,

    // Bottom face
    v1, v5, v8, v4,

    // Left face
    v1, v2, v6, v5,

    // Right face
    v4, v3, v7, v8
  };

  texture_coords = {
    // Texture coordinates
    // Front face
    Vector2D(0, 0),
    Vector2D(0, 1),
    Vector2D(1, 1),
    Vector2D(1, 0),

    // Back face
    Vector2D(1, 1),
    Vector2D(1, 0),
    Vector2D(0, 0),
    Vector2D(0, 1),
    // Top face
    Vector2D(0, 0),
    Vector2D(0, 1),
    Vector2D(1, 1),
    Vector2D(1, 0),
    //// Bottom face
    Vector2D(0, 0),
    Vector2D(0, 1),
    Vector2D(1, 1),
    Vector2D(1, 0),
    //// Left face
    Vector2D(1, 0),
    Vector2D(1, 1),
    Vector2D(0, 1),
    Vector2D(0, 0),
    //// Right face
    Vector2D(0, 0),
    Vector2D(0, 1),
    Vector2D(1, 1),
    Vector2D(1, 0)
  };

  indices = {
    // Vertices indices
    // Front face
    0, 1, 2,
    2, 3, 0,

    // Back face
    6, 5, 4,
    4, 7, 6,

    // Top face
    8, 9, 10,
    10, 11, 8,

    // Bottom face
    14, 13, 12,
    12, 15, 14,

    // Left face
    16, 19, 18,
    18, 17, 16,

    // Right face
    20, 21, 22,
    22, 23, 20
  };
}

GeometryObject* buildPlainBox(Material* material, const RGBColor& color, const Point3D& center, const float side) {
  const std::vector<RGBColor> colors = std::vector<RGBColor>(24, color);

  std::vector<Point3D> vertices;
  std::vector<Vector2D> texture_coords;
  std::vector<uint32_t> indices;
  buildAlignedBox(vertices, texture_coords, indices, side);
  GeometryObject* box = new GeometryObject(material, vertices, colors, texture_coords, indices, center);

  return box;
}

GeometryObject* buildMultiColorBox(Material* material, const Point3D& center, const float side) {
  const std::vector<RGBColor> colors = {
    Colors::GREEN,
    Colors::YELLOW,
    Colors::WHITE,
    Colors::CYAN,

    Colors::BLACK,
    Colors::BLACK,
    Colors::BLACK,
    Colors::BLACK,

    Colors::YELLOW,
    Colors::RED,
    Colors::PURPLE,
    Colors::WHITE,

    Colors::BLACK,
    Colors::BLACK,
    Colors::BLACK,
    Colors::BLACK,

    Colors::BLACK,
    Colors::BLACK,
    Colors::BLACK,
    Colors::BLACK,

    Colors::CYAN,
    Colors::WHITE,
    Colors::PURPLE,
    Colors::BLUE,
  };

  std::vector<Point3D> vertices;
  std::vector<Vector2D> texture_coords;
  std::vector<uint32_t> indices;
  buildAlignedBox(vertices, texture_coords, indices, side);
  GeometryObject* box = new GeometryObject(material, vertices, colors, texture_coords, indices, center);

  return box;
}

GeometryObject* buildTexturedBox(Material* material, const Point3D& center, const float side) {
  std::vector<Point3D> vertices;
  std::vector<Vector2D> texture_coords;
  std::vector<uint32_t> indices;
  buildAlignedBox(vertices, texture_coords, indices, side);
  GeometryObject* box = new GeometryObject(material, vertices, std::vector<RGBColor>(), texture_coords, indices, center);
  return box;
}

void buildHorizontalPlane(std::vector<Point3D>& vertices, std::vector<Vector2D>& texture_coords, std::vector<uint32_t>& indices, const float side) {
  const float half_diagonal = (side / 2) / sin(PI / 2); // Distance to center

  const Point3D v1(-half_diagonal, 0, -half_diagonal);
  const Point3D v2(v1.x, v1.y, v1.z + side);
  const Point3D v3(v1.x + side, v1.y, v1.z + side);
  const Point3D v4(v1.x + side, v1.y, v1.z);

  vertices = {
    // Vertices positions
    v1, v2, v3, v4
  };

  texture_coords = {
    // Texture coordinates
    Vector2D(0, 0),
    Vector2D(0, 2),
    Vector2D(2, 2),
    Vector2D(2, 0),
  };

  indices = {
    // Indices
    0, 1, 2,
    2, 3, 0
  };
}

GeometryObject* buildPlainPlane(Material* material, const RGBColor& color, const Point3D& center, const float side) {
  const std::vector<RGBColor> colors = std::vector<RGBColor>(4, color);
  std::vector<Point3D> vertices;
  std::vector<Vector2D> texture_coords;
  std::vector<uint32_t> indices;
  buildHorizontalPlane(vertices, texture_coords, indices, side);
  GeometryObject* box = new GeometryObject(material, vertices, colors, texture_coords, indices, center);
  return box;
}

GeometryObject* buildTexturedPlane(Material* material, const Point3D& center, const float side) {
  std::vector<Point3D> vertices;
  std::vector<Vector2D> texture_coords;
  std::vector<uint32_t> indices;
  buildHorizontalPlane(vertices, texture_coords, indices, side);
  GeometryObject* box = new GeometryObject(material, vertices, std::vector<RGBColor>(), texture_coords, indices, center);
  return box;
}<|endoftext|>