776 lines
28 KiB
C++
776 lines
28 KiB
C++
#define IMGUI_DISABLE_INCLUDE_IMCONFIG_H
|
|
|
|
#include <imgui.h>
|
|
//#include "imgui_impl_glfw.h"
|
|
#include "imgui_impl_glfw_gl3.h"
|
|
#include "imgui_dock.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <GL/glew.h> // extension loading
|
|
#include <GLFW/glfw3.h>
|
|
|
|
#include "mathGL.h"
|
|
|
|
static void error_callback(int error, const char* description)
|
|
{
|
|
fprintf(stderr, "Error %d: %s\n", error, description);
|
|
}
|
|
|
|
GLFWwindow* window;
|
|
int resx = 1280;
|
|
int resy = 720;
|
|
float prevx = -1, prevy = -1; // to track how much the mouse moved between frames
|
|
float cam_x = -2.0, cam_y = -2.0; // world coordinates of lower-left corner of the window
|
|
float cam_height = 4.0;
|
|
float cam_width = cam_height*resx/float(resy);
|
|
|
|
|
|
// buffer object stuffs
|
|
GLuint cube_program;
|
|
GLuint VertexArrayID;
|
|
|
|
GLuint vertexbuffer;
|
|
GLuint elementbuffer;
|
|
int num_indices;
|
|
|
|
GLuint sizebuffer;
|
|
GLuint positionbuffer;
|
|
GLuint rotatebuffer;
|
|
GLuint startbuffer;
|
|
GLuint stopbuffer;
|
|
GLuint indexbuffer;
|
|
|
|
|
|
// Framebuffer stuff
|
|
GLuint framebuffer;
|
|
GLuint texture;
|
|
GLuint depthbuffer;
|
|
|
|
|
|
int textureX = resx;
|
|
int textureY = resy;
|
|
|
|
float rotateX = 10.0, rotateY = 0.0;
|
|
|
|
char *readFile(const char *filename);
|
|
void CompileShader(const char * file_path, GLuint ShaderID);
|
|
GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path);
|
|
|
|
void init_GLFW_GLEW();
|
|
void init_GL();
|
|
void init_ImGUI();
|
|
|
|
void draw_cube();
|
|
void cube_GUI();
|
|
int main_menu_GUI();
|
|
void do_GUI();
|
|
|
|
bool fullscreen = false;
|
|
|
|
int main(int, char**) {
|
|
init_GLFW_GLEW();
|
|
init_GL();
|
|
init_ImGUI();
|
|
|
|
// Main loop
|
|
while (!glfwWindowShouldClose(window)) {
|
|
glfwPollEvents();
|
|
|
|
glfwGetFramebufferSize(window, &resx, &resy);
|
|
ImGui_ImplGlfwGL3_NewFrame();
|
|
|
|
do_GUI();
|
|
|
|
// Rendering
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
glViewport(0, 0, resx, resy);
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
ImGui::Render();
|
|
glfwSwapBuffers(window);
|
|
}
|
|
|
|
ImGui::SaveDock();
|
|
|
|
// Cleanup
|
|
ImGui_ImplGlfwGL3_Shutdown();
|
|
glfwTerminate();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void init_GLFW_GLEW() {
|
|
// Setup window
|
|
glfwSetErrorCallback(error_callback);
|
|
if (!glfwInit()) {
|
|
fprintf(stderr, "Failed to initialize GLFW window\n"); fflush(stderr);
|
|
exit(-1);
|
|
}
|
|
|
|
glfwWindowHint(GLFW_SAMPLES, 4);
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
|
window = glfwCreateWindow(resx, resy, "ImGui OpenGL3 Docking", NULL, NULL);
|
|
if (!window) {
|
|
fprintf(stderr, "Failed to create window\n"); fflush(stderr);
|
|
exit(-2);
|
|
}
|
|
glfwMakeContextCurrent(window);
|
|
|
|
glewExperimental = true; // Needed for core profile
|
|
if (glewInit() != GLEW_OK) {
|
|
fprintf(stderr, "Failed to initialize GLEW\n"); fflush(stderr);
|
|
exit(-3);
|
|
}
|
|
|
|
glfwSwapInterval(1);
|
|
}
|
|
|
|
void init_GL() {
|
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
|
glEnable(GL_DEPTH_TEST);
|
|
glDepthFunc(GL_LEQUAL);
|
|
|
|
/////////////////////////
|
|
// Create and bind VBO //
|
|
/////////////////////////
|
|
glGenVertexArrays(1, &VertexArrayID);
|
|
glBindVertexArray(VertexArrayID);
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Create program for drawing cube, create VBOs and copy the data //
|
|
////////////////////////////////////////////////////////////////////
|
|
cube_program = LoadShaders("vertex_shader.vs", "fragment_shader.fs");
|
|
|
|
// Actually a cylinder with 20 triangles
|
|
const int n = 10;
|
|
num_indices = 2*n+2;
|
|
|
|
GLfloat cubeVertices[n*2*3];
|
|
GLubyte cubeIndices[2*n+2];
|
|
for (int i = 0; i < n; i++) {
|
|
float x = cos(2*PI*i/float(n));
|
|
float y = sin(2*PI*i/float(n));
|
|
cubeVertices[2*3*i + 0] = -1.0;
|
|
cubeVertices[2*3*i + 1] = x;
|
|
cubeVertices[2*3*i + 2] = y;
|
|
cubeVertices[2*3*i + 3] = 1.0;
|
|
cubeVertices[2*3*i + 4] = x;
|
|
cubeVertices[2*3*i + 5] = y;
|
|
|
|
cubeIndices[2*i+0] = 2*i + 0;
|
|
cubeIndices[2*i+1] = 2*i + 1;
|
|
|
|
}
|
|
cubeIndices[2*n+0] = 0;
|
|
cubeIndices[2*n+1] = 1;
|
|
|
|
|
|
/*
|
|
const GLfloat cubeVertices[] = {
|
|
-1.0, -1.0, 1.0,
|
|
1.0, -1.0, 1.0,
|
|
-1.0, 1.0, 1.0,
|
|
1.0, 1.0, 1.0,
|
|
-1.0, -1.0, -1.0,
|
|
1.0, -1.0, -1.0,
|
|
-1.0, 1.0, -1.0,
|
|
1.0, 1.0, -1.0,
|
|
};
|
|
|
|
const GLubyte cubeIndices[] = {
|
|
0, 1, 2, 3, 7, 1, 5, 4, 7, 6, 2, 4, 0, 1
|
|
};
|
|
*/
|
|
|
|
const GLfloat instanceSizes[] = {
|
|
1.0, 0.1, 0.1,
|
|
1.0, 0.2, 0.2,
|
|
1.0, 0.3, 0.3,
|
|
};
|
|
|
|
const GLfloat instancePositions[] {
|
|
0.0, 0.0, 0.0,
|
|
2.0, 0.0, 0.0,
|
|
1.0, sqrt(3), 0.0,
|
|
};
|
|
|
|
const GLfloat instanceRotate[] {
|
|
30.0, 150.0, 90.0
|
|
};
|
|
|
|
|
|
glGenBuffers(1, &vertexbuffer);
|
|
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), cubeVertices, GL_STATIC_DRAW);
|
|
glGenBuffers(1, &sizebuffer);
|
|
glBindBuffer(GL_ARRAY_BUFFER, sizebuffer);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(instanceSizes), instanceSizes, GL_STATIC_DRAW);
|
|
glGenBuffers(1, &positionbuffer);
|
|
glBindBuffer(GL_ARRAY_BUFFER, positionbuffer);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(instancePositions), instancePositions, GL_STATIC_DRAW);
|
|
glGenBuffers(1, &rotatebuffer);
|
|
glBindBuffer(GL_ARRAY_BUFFER, rotatebuffer);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(instanceRotate), instanceRotate, GL_STATIC_DRAW);
|
|
|
|
|
|
const GLfloat instanceStart[] = {
|
|
0.7, 0.0, 0.0, 0.0,
|
|
0.0, 0.5, 0.0, 0.0,
|
|
0.0, 0.2, 0.4, 0.6
|
|
};
|
|
|
|
const GLfloat instanceStop[] = {
|
|
1.0, 0.0, 0.0, 0.0,
|
|
0.3, 1.0, 0.0, 0.0,
|
|
0.1, 0.3, 0.5, 0.8
|
|
};
|
|
|
|
const GLfloat instanceIndex[] {
|
|
0.0, -1.0, -1.0, -1.0,
|
|
1.0, 0.0, -1.0, -1.0,
|
|
0.0, 2.0, 3.0, 4.0
|
|
};
|
|
|
|
glGenBuffers(1, &startbuffer);
|
|
glBindBuffer(GL_ARRAY_BUFFER, startbuffer);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(instanceStart), instanceStart, GL_STATIC_DRAW);
|
|
glGenBuffers(1, &stopbuffer);
|
|
glBindBuffer(GL_ARRAY_BUFFER, stopbuffer);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(instanceStop), instanceStop, GL_STATIC_DRAW);
|
|
glGenBuffers(1, &indexbuffer);
|
|
glBindBuffer(GL_ARRAY_BUFFER, indexbuffer);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(instanceIndex), instanceIndex, GL_STATIC_DRAW);
|
|
|
|
glGenBuffers(1, &elementbuffer);
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
|
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cubeIndices), cubeIndices, GL_STATIC_DRAW);
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// Create and bind framebuffer, attach a depth buffer to it //
|
|
// Create the texture to render to, and attach it to the framebuffer //
|
|
////////////////////////////////////////////////////////////////////////
|
|
glGenFramebuffers(1, &framebuffer);
|
|
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
|
|
|
glGenRenderbuffers(1, &depthbuffer);
|
|
glBindRenderbuffer(GL_RENDERBUFFER, depthbuffer);
|
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, resx, resy);
|
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuffer);
|
|
|
|
glGenTextures(1, &texture);
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, resx, resy, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0);
|
|
GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
|
|
glDrawBuffers(1, DrawBuffers);
|
|
|
|
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
|
printf("Error in setting up the framebuffer\n");
|
|
}
|
|
}
|
|
|
|
|
|
void init_ImGUI() {
|
|
///////////////////////////////////////////////////////////
|
|
// Style setup for ImGui. Colors copied from Stylepicker //
|
|
///////////////////////////////////////////////////////////
|
|
ImGuiStyle& style = ImGui::GetStyle();
|
|
style.WindowPadding = ImVec2(4.0f, 4.0f);
|
|
style.WindowRounding = 2.0f;
|
|
style.FramePadding = ImVec2(3.0f, 3.0f);
|
|
style.FrameRounding = 2.0f;
|
|
|
|
style.Colors[ImGuiCol_Text] = ImVec4(0.97f, 0.97f, 0.97f, 1.00f);
|
|
style.Colors[ImGuiCol_TextDisabled] = ImVec4(0.56f, 0.56f, 0.54f, 1.00f);
|
|
style.Colors[ImGuiCol_WindowBg] = ImVec4(0.15f, 0.16f, 0.13f, 1.00f);
|
|
style.Colors[ImGuiCol_ChildWindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
|
style.Colors[ImGuiCol_PopupBg] = ImVec4(0.24f, 0.24f, 0.23f, 1.00f);
|
|
style.Colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 0.65f);
|
|
style.Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
|
style.Colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.20f, 0.18f, 1.00f);
|
|
style.Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.24f, 0.24f, 0.23f, 1.00f);
|
|
style.Colors[ImGuiCol_FrameBgActive] = ImVec4(0.24f, 0.24f, 0.23f, 1.00f);
|
|
style.Colors[ImGuiCol_TitleBg] = ImVec4(0.27f, 0.27f, 0.54f, 0.83f);
|
|
style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f);
|
|
style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.32f, 0.32f, 0.63f, 0.87f);
|
|
style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.30f, 0.30f, 0.30f, 1.00f);
|
|
style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.21f, 0.21f, 0.20f, 1.00f);
|
|
style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.30f, 0.30f, 0.30f, 1.00f);
|
|
style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.30f, 0.30f, 0.30f, 1.00f);
|
|
style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.30f, 0.30f, 0.30f, 1.00f);
|
|
style.Colors[ImGuiCol_ComboBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.99f);
|
|
style.Colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);
|
|
style.Colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
|
|
style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f);
|
|
style.Colors[ImGuiCol_Button] = ImVec4(0.32f, 0.32f, 0.32f, 1.00f);
|
|
style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.48f, 0.48f, 0.48f, 1.00f);
|
|
style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.65f, 0.65f, 0.65f, 1.00f);
|
|
style.Colors[ImGuiCol_Header] = ImVec4(0.26f, 0.26f, 0.26f, 1.00f);
|
|
style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.35f, 0.35f, 0.35f, 1.00f);
|
|
style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.53f, 0.87f, 0.80f);
|
|
style.Colors[ImGuiCol_Column] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
|
|
style.Colors[ImGuiCol_ColumnHovered] = ImVec4(0.70f, 0.60f, 0.60f, 1.00f);
|
|
style.Colors[ImGuiCol_ColumnActive] = ImVec4(0.90f, 0.70f, 0.70f, 1.00f);
|
|
style.Colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
|
|
style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(1.00f, 1.00f, 1.00f, 0.60f);
|
|
style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(1.00f, 1.00f, 1.00f, 0.90f);
|
|
style.Colors[ImGuiCol_CloseButton] = ImVec4(0.50f, 0.50f, 0.90f, 0.50f);
|
|
style.Colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.70f, 0.70f, 0.90f, 0.60f);
|
|
style.Colors[ImGuiCol_CloseButtonActive] = ImVec4(0.70f, 0.70f, 0.70f, 1.00f);
|
|
style.Colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
|
|
style.Colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
|
|
style.Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
|
|
style.Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
|
|
style.Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
|
|
style.Colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
|
|
|
|
// Setup ImGui binding
|
|
ImGui_ImplGlfwGL3_Init(window, true);
|
|
|
|
///////////////////////////////////////
|
|
// Load docks from imgui_dock.layout //
|
|
///////////////////////////////////////
|
|
ImGui::LoadDock();
|
|
}
|
|
|
|
void draw_cube() {
|
|
/*
|
|
const GLfloat instanceStart[] = {
|
|
0.7, 0.0, 0.0, 0.0,
|
|
0.0, 0.5, 0.0, 0.0,
|
|
0.0, 0.2, 0.4, 0.6
|
|
};
|
|
|
|
const GLfloat instanceStop[] = {
|
|
1.0, 0.0, 0.0, 0.0,
|
|
0.3, 1.0, 0.0, 0.0,
|
|
0.1, 0.3, 0.5, 0.8
|
|
};
|
|
|
|
const GLfloat instanceIndex[] {
|
|
0.0, -1.0, -1.0, -1.0,
|
|
1.0, 0.0, -1.0, -1.0,
|
|
0.0, 2.0, 3.0, 4.0
|
|
};
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, startbuffer);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(instanceStart), 0, GL_STATIC_DRAW);
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(instanceStart), instanceStart);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, stopbuffer);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(instanceStop), 0, GL_STATIC_DRAW);
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(instanceStop), instanceStop);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, indexbuffer);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(instanceIndex), 0, GL_STATIC_DRAW);
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(instanceIndex), instanceIndex);
|
|
*/
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Draw a cube to a framebuffer texture using orthogonal projection //
|
|
// with camera looking along the negative Z axis //
|
|
// The cube rotates around a random axis //
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
|
glViewport(0,0,textureX,textureY);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
glUseProgram(cube_program);
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// View matrix is identity matrix for 2D, //
|
|
// camera movement put in orthogonal projection matrix instead //
|
|
/////////////////////////////////////////////////////////////////
|
|
mat4 View = mat4(1.0f);
|
|
mat4 Projection = ortho(cam_x, cam_x + cam_width, cam_y, cam_y + cam_height, -10, 10);
|
|
//mat4 View = view(vec3(1,0,0), vec3(0,1,0), vec3(0,0,-1), vec3(cam_x,cam_y,6));
|
|
//mat4 Projection = projection(60, resx/float(resy), 0.01, 10.0);
|
|
|
|
////////////////////////////////
|
|
// same RNG seed every frame //
|
|
// "minimal standard" LCG RNG //
|
|
////////////////////////////////
|
|
mat4 Model = rotate(vec3(1.0, 0.0, 0.0), rotateX)*rotate(vec3(0.0, 1.0, 0.0), rotateY);
|
|
|
|
mat4 MVP = Projection*View*Model;
|
|
glUniformMatrix4fv(glGetUniformLocation(cube_program, "MVP"), 1, GL_FALSE, &MVP.M[0][0]);
|
|
|
|
// Draw!
|
|
glEnableVertexAttribArray(0);
|
|
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
|
|
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,(void*)0);
|
|
|
|
glEnableVertexAttribArray(1);
|
|
glBindBuffer(GL_ARRAY_BUFFER, sizebuffer);
|
|
glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,0,(void*)0);
|
|
|
|
glEnableVertexAttribArray(2);
|
|
glBindBuffer(GL_ARRAY_BUFFER, positionbuffer);
|
|
glVertexAttribPointer(2,3,GL_FLOAT,GL_FALSE,0,(void*)0);
|
|
|
|
glEnableVertexAttribArray(3);
|
|
glBindBuffer(GL_ARRAY_BUFFER, rotatebuffer);
|
|
glVertexAttribPointer(3,1,GL_FLOAT,GL_FALSE,0,(void*)0);
|
|
|
|
glEnableVertexAttribArray(4);
|
|
glBindBuffer(GL_ARRAY_BUFFER, startbuffer);
|
|
glVertexAttribPointer(4,4,GL_FLOAT,GL_FALSE,0,(void*)0);
|
|
|
|
glEnableVertexAttribArray(5);
|
|
glBindBuffer(GL_ARRAY_BUFFER, stopbuffer);
|
|
glVertexAttribPointer(5,4,GL_FLOAT,GL_FALSE,0,(void*)0);
|
|
|
|
glEnableVertexAttribArray(6);
|
|
glBindBuffer(GL_ARRAY_BUFFER, indexbuffer);
|
|
glVertexAttribPointer(6,4,GL_FLOAT,GL_FALSE,0,(void*)0);
|
|
|
|
glVertexAttribDivisor(0, 0);
|
|
glVertexAttribDivisor(1, 1);
|
|
glVertexAttribDivisor(2, 1);
|
|
glVertexAttribDivisor(3, 1);
|
|
glVertexAttribDivisor(4, 1);
|
|
glVertexAttribDivisor(5, 1);
|
|
glVertexAttribDivisor(6, 1);
|
|
|
|
//glDrawElements(GL_TRIANGLE_STRIP, 14, GL_UNSIGNED_BYTE, (void*)0);
|
|
glDrawElementsInstanced(GL_TRIANGLE_STRIP, num_indices, GL_UNSIGNED_BYTE, (void*)0, 3);
|
|
glDisableVertexAttribArray(0);
|
|
glDisableVertexAttribArray(1);
|
|
glDisableVertexAttribArray(2);
|
|
glDisableVertexAttribArray(3);
|
|
glDisableVertexAttribArray(4);
|
|
glDisableVertexAttribArray(5);
|
|
glDisableVertexAttribArray(6);
|
|
}
|
|
|
|
void cube_GUI() {
|
|
/////////////////////////////////////////////////////
|
|
// Get available size of the current window (dock) //
|
|
// and adjust the texture size if it has changed //
|
|
// keep cam_height constant //
|
|
/////////////////////////////////////////////////////
|
|
ImVec2 size = ImGui::GetContentRegionAvail();
|
|
if (textureX != size.x || textureY != size.y) {
|
|
textureX = size.x;
|
|
textureY = size.y;
|
|
cam_width = cam_height*textureX/float(textureY);
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textureX, textureY, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
|
|
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, textureX, textureY);
|
|
}
|
|
|
|
draw_cube();
|
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
static ImVec2 imagePos = ImVec2(textureX/2, textureY/2); // If mouse cursor is outside the screen, use center of image as zoom point
|
|
ImVec2 cursorPos = ImGui::GetCursorScreenPos(); // "cursor" is where imgui will draw the image
|
|
ImVec2 mousePos = io.MousePos;
|
|
|
|
//////////////////////////////////////////////////////
|
|
// Draw the image/texture, filling the whole window //
|
|
//////////////////////////////////////////////////////
|
|
//ImGui::Image(reinterpret_cast<ImTextureID>(texture), size, ImVec2(0, 0), ImVec2(1, -1));
|
|
ImGui::Image((ImTextureID)((size_t)texture), size, ImVec2(0, 0), ImVec2(1, -1));
|
|
|
|
|
|
bool isHovered = ImGui::IsItemHovered();
|
|
bool isLeftClicked = ImGui::IsMouseClicked(0, false);
|
|
bool isRightClicked = ImGui::IsMouseClicked(1, false);
|
|
bool isFocused = ImGui::IsWindowFocused();
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// So we can move the camera while the mouse cursor is outside the docking window //
|
|
// but the button is not released yet //
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
static bool clickedLeftWhileHovered = false;
|
|
static bool clickedRightWhileHovered = false;
|
|
if (isHovered && isLeftClicked) {
|
|
clickedLeftWhileHovered = true;
|
|
}
|
|
if (isHovered && isRightClicked) {
|
|
clickedRightWhileHovered = true;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Only do input if the window containing the image is in focus (activaed) //
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
if (isFocused) {
|
|
ImVec2 mouseDelta = io.MouseDelta;
|
|
|
|
if (clickedLeftWhileHovered) {
|
|
clickedLeftWhileHovered = io.MouseDown[0];
|
|
if (io.MouseDown[0]) {
|
|
cam_x -= mouseDelta.x/size.x*cam_width;
|
|
cam_y += mouseDelta.y/size.y*cam_height;
|
|
}
|
|
}
|
|
if (clickedRightWhileHovered) {
|
|
clickedRightWhileHovered = io.MouseDown[1];
|
|
if (io.MouseDown[1]) {
|
|
float degreesPerPixel = 1.0;
|
|
rotateX += degreesPerPixel*mouseDelta.y;
|
|
rotateY += degreesPerPixel*mouseDelta.x;
|
|
}
|
|
}
|
|
|
|
float speed = 3; // 3 units per second
|
|
if (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL)) speed *= 0.1; // slow
|
|
if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT)) speed *= 10.0; // fast
|
|
|
|
float deltaMoveForward = speed*(glfwGetKey(window, GLFW_KEY_W) - glfwGetKey(window, GLFW_KEY_S));
|
|
float deltaMoveRight = speed*(glfwGetKey(window, GLFW_KEY_D) - glfwGetKey(window, GLFW_KEY_A));
|
|
float deltaMoveUp = speed*(glfwGetKey(window, GLFW_KEY_E) - glfwGetKey(window, GLFW_KEY_Q));
|
|
|
|
|
|
// move camera...
|
|
float dt = io.DeltaTime;
|
|
cam_x += dt*deltaMoveRight;
|
|
cam_y += dt*deltaMoveUp;
|
|
|
|
// Zoom...
|
|
if (isHovered) {
|
|
imagePos = ImVec2(mousePos.x - cursorPos.x, mousePos.y - cursorPos.y);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Zoom by keeping the mouse cursor at the same location //
|
|
// in world coordinates before and after zooming //
|
|
///////////////////////////////////////////////////////////
|
|
float zoomFactor = powf(0.95f,dt*deltaMoveForward);
|
|
float xend = cam_x + imagePos.x*(cam_width)/textureX;
|
|
float yend = cam_y + (textureY - imagePos.y)*cam_height/textureY;
|
|
cam_x = (1.0-zoomFactor)*xend + zoomFactor*cam_x;
|
|
cam_y = (1.0-zoomFactor)*yend + zoomFactor*cam_y;
|
|
|
|
cam_width *= zoomFactor;
|
|
cam_height *= zoomFactor;
|
|
|
|
if (ImGui::IsMouseDoubleClicked(0)) {
|
|
fullscreen = !fullscreen;
|
|
}
|
|
}
|
|
}
|
|
|
|
int main_menu_GUI() {
|
|
//////////////////////
|
|
// Placeholder menu //
|
|
//////////////////////
|
|
int menu_height = 0;
|
|
if (ImGui::BeginMainMenuBar())
|
|
{
|
|
if (ImGui::BeginMenu("File"))
|
|
{
|
|
if (ImGui::MenuItem("New")) {}
|
|
if (ImGui::MenuItem("Open", "Ctrl+O")) {}
|
|
if (ImGui::BeginMenu("Open Recent"))
|
|
{
|
|
ImGui::MenuItem("fish_hat.c");
|
|
ImGui::MenuItem("fish_hat.inl");
|
|
ImGui::MenuItem("fish_hat.h");
|
|
if (ImGui::BeginMenu("More.."))
|
|
{
|
|
ImGui::MenuItem("Hello");
|
|
ImGui::MenuItem("Sailor");
|
|
ImGui::EndMenu();
|
|
}
|
|
ImGui::EndMenu();
|
|
}
|
|
if (ImGui::BeginMenu("Disabled", false)) // Disabled
|
|
{
|
|
IM_ASSERT(0);
|
|
}
|
|
if (ImGui::MenuItem("Fullscreen", NULL, fullscreen)) {fullscreen = !fullscreen;}
|
|
if (ImGui::MenuItem("Quit", "Alt+F4")) {}
|
|
ImGui::EndMenu();
|
|
}
|
|
if (ImGui::BeginMenu("Edit"))
|
|
{
|
|
if (ImGui::MenuItem("Undo", "CTRL+Z")) {}
|
|
if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item
|
|
ImGui::Separator();
|
|
if (ImGui::MenuItem("Cut", "CTRL+X")) {}
|
|
if (ImGui::MenuItem("Copy", "CTRL+C")) {}
|
|
if (ImGui::MenuItem("Paste", "CTRL+V")) {}
|
|
ImGui::EndMenu();
|
|
}
|
|
menu_height = ImGui::GetWindowSize().y;
|
|
|
|
ImGui::EndMainMenuBar();
|
|
}
|
|
|
|
return menu_height;
|
|
}
|
|
|
|
void do_GUI() {
|
|
static bool show_scene1 = true;
|
|
static bool show_scene2 = true;
|
|
static bool show_scene3 = true;
|
|
static bool show_scene4 = true;
|
|
static bool show_scene5 = true;
|
|
static bool show_scene6 = true;
|
|
|
|
int menu_height = main_menu_GUI();
|
|
|
|
|
|
if (ImGui::GetIO().DisplaySize.y > 0) {
|
|
////////////////////////////////////////////////////
|
|
// Setup root docking window //
|
|
// taking into account menu height and status bar //
|
|
////////////////////////////////////////////////////
|
|
auto pos = ImVec2(0, menu_height);
|
|
auto size = ImGui::GetIO().DisplaySize;
|
|
size.y -= pos.y;
|
|
ImGui::RootDock(pos, ImVec2(size.x, size.y - 25.0f));
|
|
|
|
// Draw status bar (no docking)
|
|
ImGui::SetNextWindowSize(ImVec2(size.x, 25.0f), ImGuiSetCond_Always);
|
|
ImGui::SetNextWindowPos(ImVec2(0, size.y - 6.0f), ImGuiSetCond_Always);
|
|
ImGui::Begin("statusbar", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoResize);
|
|
ImGui::Text("FPS: %f", ImGui::GetIO().Framerate);
|
|
ImGui::End();
|
|
}
|
|
|
|
if (fullscreen) {
|
|
ImGui::SetNextWindowSize(ImVec2(resx, resy-menu_height), ImGuiSetCond_Always);
|
|
ImGui::SetNextWindowPos(ImVec2(0.0, menu_height), ImGuiSetCond_Always);
|
|
if (ImGui::Begin("Fullscreen", &fullscreen, ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoTitleBar)) {
|
|
ImVec2 size = ImGui::GetContentRegionAvail();
|
|
if (textureX != size.x || textureY != size.y) {
|
|
textureX = size.x;
|
|
textureY = size.y;
|
|
cam_width = cam_height*textureX/float(textureY);
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textureX, textureY, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
|
|
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, textureX, textureY);
|
|
}
|
|
cube_GUI();
|
|
|
|
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
|
|
fullscreen = false;
|
|
}
|
|
}
|
|
ImGui::End();
|
|
} else {
|
|
|
|
// Draw docking windows
|
|
if (ImGui::BeginDock("Docks", &show_scene1)) {
|
|
ImGui::Print(); // print docking information
|
|
}
|
|
ImGui::EndDock();
|
|
if (ImGui::BeginDock("Dummy1", &show_scene2)) {
|
|
ImGui::Text("Placeholder!");
|
|
}
|
|
ImGui::EndDock();
|
|
if(ImGui::BeginDock("Dummy2", &show_scene3)) {
|
|
ImGui::Text("Placeholder!");
|
|
}
|
|
ImGui::EndDock();
|
|
if(ImGui::BeginDock("Cube", &show_scene4, ImGuiWindowFlags_NoScrollbar)) {
|
|
cube_GUI();
|
|
}
|
|
ImGui::EndDock();
|
|
if(ImGui::BeginDock("Dummy3", &show_scene5)) {
|
|
ImGui::Text("Placeholder!");
|
|
}
|
|
ImGui::EndDock();
|
|
|
|
if (ImGui::BeginDock("StyleEditor", &show_scene6)) {
|
|
ImGui::ShowStyleEditor();
|
|
}
|
|
ImGui::EndDock();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
char *readFile(const char *filename) {
|
|
/////////////////////////////////////////////////////////////
|
|
// Read content of "filename" and return it as a c-string. //
|
|
/////////////////////////////////////////////////////////////
|
|
printf("Reading %s\n", filename);
|
|
FILE *f = fopen(filename, "rb");
|
|
|
|
fseek(f, 0, SEEK_END);
|
|
long fsize = ftell(f);
|
|
fseek(f, 0, SEEK_SET);
|
|
printf("Filesize = %d\n", int(fsize));
|
|
|
|
char *string = (char*)malloc(fsize + 1);
|
|
fread(string, fsize, 1, f);
|
|
string[fsize] = '\0';
|
|
fclose(f);
|
|
|
|
return string;
|
|
}
|
|
|
|
|
|
void CompileShader(const char * file_path, GLuint ShaderID) {
|
|
GLint Result = GL_FALSE;
|
|
int InfoLogLength;
|
|
|
|
char *ShaderCode = readFile(file_path);
|
|
|
|
// Compile Shader
|
|
printf("Compiling shader : %s\n", file_path);
|
|
glShaderSource(ShaderID, 1, (const char**)&ShaderCode , NULL);
|
|
glCompileShader(ShaderID);
|
|
|
|
// Check Shader
|
|
glGetShaderiv(ShaderID, GL_COMPILE_STATUS, &Result);
|
|
glGetShaderiv(ShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
|
|
|
if ( Result == GL_FALSE ){
|
|
char ShaderErrorMessage[9999];
|
|
glGetShaderInfoLog(ShaderID, InfoLogLength, NULL, ShaderErrorMessage);
|
|
printf("%s", ShaderErrorMessage);
|
|
}
|
|
}
|
|
|
|
GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path) {
|
|
printf("Creating shaders\n");
|
|
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
CompileShader(vertex_file_path, VertexShaderID);
|
|
CompileShader(fragment_file_path, FragmentShaderID);
|
|
|
|
|
|
printf("Create and linking program\n");
|
|
GLuint program = glCreateProgram();
|
|
glAttachShader(program, VertexShaderID);
|
|
glAttachShader(program, FragmentShaderID);
|
|
glLinkProgram(program);
|
|
|
|
// Check the program
|
|
GLint Result = GL_FALSE;
|
|
int InfoLogLength;
|
|
|
|
glGetProgramiv(program, GL_LINK_STATUS, &Result);
|
|
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
|
|
|
if ( InfoLogLength > 0 ){
|
|
GLchar ProgramErrorMessage[9999];
|
|
glGetProgramInfoLog(program, InfoLogLength, NULL, &ProgramErrorMessage[0]);
|
|
printf("%s\n", &ProgramErrorMessage[0]); fflush(stdout);
|
|
}
|
|
|
|
glDeleteShader(VertexShaderID);
|
|
glDeleteShader(FragmentShaderID);
|
|
|
|
return program;
|
|
}
|