I am working on a a basic program with the goal of drawing basic shapes on a grid. so far I have made a grid that will size properly based on the resolution of the window and a dot that will show what grid point your mouse is over. Right now I am working on the system to record mouse clicks and use that to draw a line between two selected points, this is where the problem starts. here is the code.
EditorWindow.cpp
#include "EditorWindow.h"
EditorWindow::EditorWindow(GLFWwindow *window)
{
glfwGetWindowSize(window, &width, &height);
EditorWindow::graphInit(width, height);
EditorWindow::gridDotInit();
}
float EditorWindow::gridNormal(float x, float max)
{
x = 2 * x;
x = x / max;
x = x - 1;
return x;
}
void EditorWindow::graphInit(int resWidth, int resHeight)
{
int logx = 0;
int logy = 0;
for (int i = gridSize; i < resWidth; i += gridSize)
{
float x = gridNormal(i, resWidth);
vertacies.push_back(x);
vertacies.push_back(1);
vertacies.push_back(0);
vertacies.push_back(x);
vertacies.push_back(-1);
vertacies.push_back(0);
}
for (int i = gridSize; i < resHeight; i += gridSize)
{
float x = gridNormal(i, resHeight);
vertacies.push_back(1);
vertacies.push_back(x);
vertacies.push_back(0);
vertacies.push_back(-1);
vertacies.push_back(x);
vertacies.push_back(0);
}
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertacies.size() * sizeof(float), vertacies.data(), GL_STATIC_DRAW);
glBindVertexArray(VAO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
}
void EditorWindow::drawGraph(Shader &shader)
{
//shader.setVec4("FragColor", glm::vec4(0.2, 0.2, 0.2, 1.0));
shader.use();
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBindVertexArray(VAO);
glDrawArrays(GL_LINES, 0, vertacies.size()/2);
}
void EditorWindow::mousePos(GLFWwindow* window)
{
glfwGetCursorPos(window, &mouseX, &mouseY);
//std::cout << mouseX << ", " << mouseY << std::endl;
}
void EditorWindow::gridDotInit()
{
//float gridX = x / gridSize;
//float gridY = y / gridSize;
glGenVertexArrays(1, &dotVAO);
glGenBuffers(1, &dotVBO);
glBindBuffer(GL_ARRAY_BUFFER, dotVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(gridDotVert), gridDotVert, GL_DYNAMIC_DRAW);
glBindVertexArray(dotVAO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
}
void EditorWindow::drawGridDot(Shader& shader)
{
//std::cout << gridX << ", " << gridY << std::endl;
glm::vec4 vec(0.0f, 0.0f, 0.0f, 1.0f);
glm::mat4 trans = glm::mat4(1.0f);
trans = glm::translate(trans, graphPoint());
vec = trans * vec;
//std::cout << posX << ", " << posY << std::endl;
//std::cout << vec.x << ", " << vec.y << std::endl;
//shader.setVec4("FragColor", glm::vec4(1.0, 0.0, 0.0, 1.0));
shader.use();
glUniformMatrix4fv(glGetUniformLocation(shader.ID, "transform"), 1, GL_FALSE, glm::value_ptr(trans));
glBindBuffer(GL_ARRAY_BUFFER, dotVBO);
//glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(gridDotVert), gridDotVert);
glBindVertexArray(dotVAO);
glPointSize(5.0);
glDrawArrays(GL_POINTS, 0, 1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void EditorWindow::genLine(glm::vec3 pos1, glm::vec3 pos2)
{
lineArray.push_back(pos1.x);
lineArray.push_back(pos1.y);
lineArray.push_back(pos1.z);
lineArray.push_back(pos2.x);
lineArray.push_back(pos2.y);
lineArray.push_back(pos2.z);
lineNumber++;
std::cout << lineNumber << std::endl;
genLineBuffers();
}
void EditorWindow::destroyLine(int line)
{
int x = line * 3;
for (int y = 0; y < 3; y++)
{
lineArray.erase(lineArray.begin() + x + y);
}
lineNumber--;
}
void EditorWindow::genLineBuffers()
{
//glDeleteBuffers(1, &lineVBO);
//glDeleteBuffers(1, &lineVAO);
glGenBuffers(1, &lineVAO);
glGenBuffers(1, &lineVBO);
glBindBuffer(GL_ARRAY_BUFFER, lineVBO);
glBufferData(GL_ARRAY_BUFFER, lineArray.size() * sizeof(float), lineArray.data(), GL_DYNAMIC_DRAW);
glBindVertexArray(lineVAO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
}
void EditorWindow::drawLines(Shader& shader)
{
if(lineArray.size() == 6)
{
shader.use();
glBindBuffer(GL_ARRAY_BUFFER, lineVBO);
glBindVertexArray(lineVAO);
glDrawArrays(GL_LINES, 0, lineArray.size() / 2);
std::cout << "One is the loneliest number" << std::endl;
}
}
glm::vec3 EditorWindow::getLine(int line)
{
glm::vec3 result;
int x = line * 3;
for (int y = 0; y < 3; y++)
{
result.x = lineArray[x + y];
result.y = lineArray[x + y];
result.z = lineArray[x + y];
}
return result;
}
glm::vec3 EditorWindow::graphPoint()
{
float gridX = std::round(mouseX / gridSize);
float gridY = std::round(mouseY / gridSize);
gridX = gridX * gridSize;
gridY = gridY * gridSize;
float posX = gridNormal(gridX, width);
float posY = gridNormal(gridY, height);
posY = posY * -1;
return glm::vec3(posX, posY, 0.0);
}
void EditorWindow::brush(GLFWwindow* window)
{
if (pointStored)
{
pos2 = graphPoint();
genLine(pos1, pos2);
pointStored = false;
std::cout << pos2.x << " ," << pos2.y << std::endl;
}
else
{
pos1 = graphPoint();
pointStored = true;
std::cout << pos1.x << " ," << pos1.y << std::endl;
}
}
void EditorWindow::inputMonitor(GLFWwindow* window)
{
static int oldState = GLFW_RELEASE;
int newState = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT);
if (newState == GLFW_RELEASE && oldState == GLFW_PRESS) {
brush(window);
}
oldState = newState;
static int oldState1 = GLFW_RELEASE;
int newState1 = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT);
if (newState1 == GLFW_RELEASE && oldState1 == GLFW_PRESS) {
float* lineData = lineArray.data();
try
{
std::cout << *lineData << std::endl;
}
catch(float well)
{
std::cout << "nullPtr: " << well << std::endl;
}
}
oldState1 = newState1;
}
EditorWindow.h
#pragma once
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include<iostream>
#include<vector>
#include "Shader.h"
class EditorWindow
{
public:
unsigned int VBO, VAO;
unsigned int dotVBO, dotVAO;
unsigned int lineVBO, lineVAO;
int lineNumber = 0;
std::vector<float> vertacies;
glm::vec3 pos1 = glm::vec3(0.0, 0.0, 0.0);
glm::vec3 pos2 = glm::vec3(0.0, 0.0, 0.0);
double mouseX, mouseY;
int gridSize = 40;
int width, height;
bool pointStored = false;
float gridDotVert[3] =
{
0.0f, 0.0f, 0.0f
};
std::vector<float> lineArray;
glm::mat4 worldPosition = glm::mat4(1.0f);
EditorWindow(GLFWwindow *window);
float gridNormal(float x, float max);
void drawGraph(Shader& shader);
void mousePos(GLFWwindow* window);
void drawGridDot(Shader& shader);
void genLine(glm::vec3 pos1, glm::vec3 pos2);
void destroyLine(int line);
void genLineBuffers();
void drawLines(Shader& shader);
glm::vec3 getLine(int line);
glm::vec3 graphPoint();
void inputMonitor(GLFWwindow* window);
void brush(GLFWwindow* window);
private:
void graphInit(int resWidth, int resHeight);
void gridDotInit();
};
Main.cpp
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include<iostream>
#include "EditorWindow.h"
#include "Shader.h"
void processInput(GLFWwindow* window);
bool running;
int width = 1000;
int height = 720;
int main() {
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, false);
GLFWwindow* window = glfwCreateWindow(width, height, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
EditorWindow Editor(window);
Shader gridShader("grid.vs", "grid.fs");
Shader dotShader("dot.vs", "dot.fs");
Shader lineShader("line.vs", "line.fs");
float vertacies[] =
{
1.0f, 0.5f, 0.0f,
-1.0f, 0.5f, 0.0f
};
while (!glfwWindowShouldClose(window))
{
glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
processInput(window);
Editor.mousePos(window);
Editor.inputMonitor(window);
Editor.drawGraph(gridShader);
Editor.drawGridDot(dotShader);
Editor.drawLines(lineShader);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
if (glfwGetKey(window, GLFW_MOUSE_BUTTON_1) == GLFW_PRESS)
{
std::cout << "12" << std::endl;
}
}
I am currently trying to regen the VBO every time I add a line, I am pretty sure this is the problem but I can’t find a solution with my rudimentary knowledge of both c++ and openGL. That said I don’t know what I don’t know. I have read the learnOpenGL pdf and parts of the openGL documentation but any more resources I could use to check against would be welcome.
Timothy Durham is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.