Ive been working in glfw c++ and want to get input from the mouse wheel by using the glfwSetScrollCallback() and I put it in a window class that I created because it requires a glfw window. I created a scroll_callback function that adjusts the fov for the camera that I initialize in a camera class. The glfwSetScrollCallback() uses that static void of my scroll_callback function in my camera class. However, I cant seem how to initialize a the fov variable in my camera.h and use it in the static void in my camera.cpp. I tried changing it to a static public variable because I need to call it in my main class but it didnt work. Any thoughts thank you!!!
camera.h
#pragma once
#include <GL\glew.h>
#include <glm\glm.hpp>
#include <glm\gtc\matrix_transform.hpp>
#include <GLFW\glfw3.h>
class Camera
{
public:
Camera();
Camera(glm::vec3 startPosition, glm::vec3 startUp, GLfloat startYaw, GLfloat startPitch, GLfloat startMoveSpeed, GLfloat startTurnSpeed);
void keyControl(bool* keys, GLfloat deltaTime);
void mouseControl(GLfloat xChange, GLfloat yChange);
static float fov;
glm::mat4 calculateViewMatrix();
~Camera();
static void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
private:
glm::vec3 position;
glm::vec3 front;
glm::vec3 up;
glm::vec3 right;
glm::vec3 worldUp;
GLfloat yaw;
GLfloat pitch;
GLfloat moveSpeed;
GLfloat turnSpeed;
void update();
};
Camera.cpp
#include "Camera.h"
#include <iostream>
Camera::Camera() {}
Camera::Camera(glm::vec3 startPosition, glm::vec3 startUp, GLfloat startYaw, GLfloat startPitch, GLfloat startMoveSpeed, GLfloat startTurnSpeed)
{
position = startPosition;
worldUp = startUp;
yaw = startYaw;
pitch = startPitch;
front = glm::vec3(0.0f, 0.0f, -1.0f);
moveSpeed = startMoveSpeed;
turnSpeed = startTurnSpeed;
update();
}
void Camera::keyControl(bool* keys, GLfloat deltaTime)
{
GLfloat velocity = moveSpeed * deltaTime;
if (keys[GLFW_KEY_W] || keys[GLFW_KEY_UP])
{
position += front * velocity;
}
if (keys[GLFW_KEY_S] || keys[GLFW_KEY_DOWN])
{
position -= front * velocity;
}
if (keys[GLFW_KEY_A] || keys[GLFW_KEY_LEFT])
{
position -= right * velocity;
}
if (keys[GLFW_KEY_D] || keys[GLFW_KEY_RIGHT])
{
position += right * velocity;
}
}
void Camera::mouseControl(GLfloat xChange, GLfloat yChange)
{
xChange *= turnSpeed;
yChange *= turnSpeed;
yaw += xChange;
pitch += yChange;
if (pitch > 89.0f)
{
pitch = 89.0f;
}
if (pitch < -89.0f)
{
pitch = -89.0f;
}
update();
}
void Camera::scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
if (fov > 1.0f && fov < 45.0f)
fov -= yoffset;
else if (fov <= 1.0f)
fov = 1.0f;
else if (fov >= 45.0f)
fov = 45.0f;
}
glm::mat4 Camera::calculateViewMatrix()
{
return glm::lookAt(position, position + front, up);
}
void Camera::update()
{
front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
front.y = sin(glm::radians(pitch));
front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
front = glm::normalize(front);
right = glm::normalize(glm::cross(front, worldUp));
up = glm::normalize(glm::cross(right, front));
}
Camera::~Camera()
{
}
window.cpp
#include "Window.h"
#include "Camera.h"
#include <iostream>
Window::Window()
{
width = 800;
height = 800;
for (size_t i = 0; i < 1024; i++)
{
keys[i] = 0;
}
}
Window::Window(GLint windowWidth, GLint windowHeight)
{
width = windowWidth;
height = windowHeight;
for (size_t i = 0; i < 1024; i++)
{
keys[i] = 0;
}
}
int Window::Initialise()
{
if (!glfwInit())
{
printf("Error Initialising GLFW");
glfwTerminate();
return 1;
}
// Setup GLFW Windows Properties
// OpenGL version
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
// Core Profile
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Allow forward compatiblity
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
// Create the window
mainWindow = glfwCreateWindow(width, height, "Test Window", NULL, NULL);
if (!mainWindow)
{
printf("Error creating GLFW window!");
glfwTerminate();
return 1;
}
// Get buffer size information
glfwGetFramebufferSize(mainWindow, &bufferWidth, &bufferHeight);
// Set the current context
glfwMakeContextCurrent(mainWindow);
// Handle Key + Mouse Input
createCallbacks();
glfwSetScrollCallback(mainWindow, Camera::scroll_callback);
glfwSetInputMode(mainWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// Allow modern extension access
glewExperimental = GL_TRUE;
GLenum error = glewInit();
if (error != GLEW_OK)
{
printf("Error: %s", glewGetErrorString(error));
glfwDestroyWindow(mainWindow);
glfwTerminate();
return 1;
}
glEnable(GL_DEPTH_TEST);
// Create Viewport
glViewport(0, 0, bufferWidth, bufferHeight);
glfwSetWindowUserPointer(mainWindow, this);
}
void Window::createCallbacks()
{
glfwSetKeyCallback(mainWindow, handleKeys);
glfwSetCursorPosCallback(mainWindow, handleMouse);
}
GLfloat Window::getXChange()
{
GLfloat theChange = xChange;
xChange = 0.0f;
return theChange;
}
GLfloat Window::getYChange()
{
GLfloat theChange = yChange;
yChange = 0.0f;
return theChange;
}
void Window::handleKeys(GLFWwindow* window, int key, int code, int action, int mode)
{
Window* theWindow = static_cast<Window*>(glfwGetWindowUserPointer(window));
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, GL_TRUE);
}
if (key >= 0 && key < 1024)
{
if (action == GLFW_PRESS)
{
theWindow->keys[key] = true;
}
else if (action == GLFW_RELEASE)
{
theWindow->keys[key] = false;
}
}
}
void Window::handleMouse(GLFWwindow* window, double xPos, double yPos)
{
Window* theWindow = static_cast<Window*>(glfwGetWindowUserPointer(window));
if (theWindow->mouseFirstMoved)
{
theWindow->lastX = xPos;
theWindow->lastY = yPos;
theWindow->mouseFirstMoved = false;
}
theWindow->xChange = xPos - theWindow->lastX;
theWindow->yChange = theWindow->lastY - yPos;
theWindow->lastX = xPos;
theWindow->lastY = yPos;
}
Window::~Window()
{
glfwDestroyWindow(mainWindow);
glfwTerminate();
}
Related
I am currently developing a test project for OpenGL to discover its possibilities.
I am experiencing a weird bug with GLFW 4.0 apparently called "mouse drift" (from different github issues). It means that even though my mouse is not moving, the glfw input callback will still be called with small x and y values (generally 1 or -1).
I provided my code here : https://github.com/Lygaen/testgl (not ads or promoting, just giving the link to the full project to help reproduce). I am using a basic GLFW, GLAD and GLM framework.
My goal is to calculate the delta position of the mouse, to have correct camera movement.
Thank you for any help that you could provide !
Here is the code that calculates input :
window.h
#ifndef __WINDOW_H__
#define __WINDOW_H__
#include <string>
#include <glad/gl.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <vector>
class Window
{
private:
GLFWwindow *window;
bool correctlyLoaded;
static void resizeCallback(GLFWwindow *, int, int);
public:
Window(const std::string &, int, int);
~Window();
const bool hasCorrectlyLoaded();
const bool shouldClose();
const void pollEvents();
const void exitNextFrame();
};
class Input
{
private:
static char *keyStates;
static bool *mouseStates;
static glm::dvec2 pos;
static glm::dvec2 delta;
static std::vector<int> pressed;
static void keyCallback(GLFWwindow *, int, int, int, int);
static void mouseCallback(GLFWwindow *, double, double);
static void mouseButtonCallback(GLFWwindow *, int, int, int);
public:
static const bool isPressed(int);
static const bool isDown(int);
static const bool isReleased(int);
static const glm::dvec2 getMousePosition();
static const glm::dvec2 getMouseDelta();
static const bool isMouseButtonDown(int);
static const void setCallbacks(GLFWwindow *);
static const void loopClear();
static const void terminate();
};
#endif // __WINDOW_H__
window.cpp
#include "window.h"
#include <spdlog/spdlog.h>
#include <algorithm>
Window::Window(const std::string &title, int width, int height)
{
correctlyLoaded = false;
if (!glfwInit())
{
spdlog::default_logger()->critical("Could not load GLFW");
return;
}
spdlog::default_logger()->info("Loaded GLFW {}", glfwGetVersionString());
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr);
if (!window)
{
spdlog::default_logger()->critical("Failed to create GLFW window !");
return;
}
glfwMakeContextCurrent(window);
if (!gladLoadGL(glfwGetProcAddress))
{
spdlog::default_logger()->critical("Failed to load OpenGL !");
return;
}
spdlog::default_logger()->info("Loaded OpenGL {}", glfwGetVersionString());
glViewport(0, 0, width, height);
glEnable(GL_MULTISAMPLE);
glfwSetFramebufferSizeCallback(window, Window::resizeCallback);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
Input::setCallbacks(window);
correctlyLoaded = true;
}
Window::~Window()
{
glfwTerminate();
}
void Window::resizeCallback(GLFWwindow *, int width, int height)
{
glViewport(0, 0, width, height);
}
const bool Window::hasCorrectlyLoaded()
{
return correctlyLoaded;
}
const bool Window::shouldClose()
{
return glfwWindowShouldClose(window);
}
const void Window::pollEvents()
{
Input::loopClear();
glfwSwapBuffers(window);
glfwPollEvents();
}
const void Window::exitNextFrame()
{
glfwSetWindowShouldClose(window, true);
}
char *Input::keyStates;
bool *Input::mouseStates;
glm::tvec2<double> Input::pos;
glm::tvec2<double> Input::delta;
std::vector<int> Input::pressed;
void Input::keyCallback(GLFWwindow *, int key, int /*scancode*/, int action, int /*mods*/)
{
if (key < 0 || key > GLFW_KEY_LAST)
return;
keyStates[key] = action;
if (action == GLFW_PRESS)
{
pressed.push_back(key);
}
}
void Input::mouseCallback(GLFWwindow *window, double nXPos, double nYPos)
{
glm::dvec2 newPos = {nXPos, nYPos};
delta = newPos - pos;
pos = newPos;
glfwSetCursorPos(window, 0, 0);
}
void Input::mouseButtonCallback(GLFWwindow *window, int button, int action, int /*mods*/)
{
if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
return;
mouseStates[button] = action;
}
const bool Input::isPressed(int key)
{
return std::count(pressed.begin(), pressed.end(), key);
}
const bool Input::isDown(int key)
{
return keyStates[key] != GLFW_RELEASE;
}
const bool Input::isReleased(int key)
{
return keyStates[key] == GLFW_RELEASE;
}
const glm::dvec2 Input::getMousePosition()
{
return pos;
}
const glm::dvec2 Input::getMouseDelta()
{
return delta;
}
const bool Input::isMouseButtonDown(int mouseButton)
{
return mouseStates[mouseButton] == GLFW_PRESS;
}
const void Input::setCallbacks(GLFWwindow *window)
{
keyStates = new char[GLFW_KEY_LAST];
mouseStates = new bool[GLFW_MOUSE_BUTTON_LAST];
glfwSetKeyCallback(window, Input::keyCallback);
glfwSetCursorPosCallback(window, Input::mouseCallback);
glfwSetMouseButtonCallback(window, Input::mouseButtonCallback);
}
const void Input::loopClear()
{
pressed.clear();
}
const void Input::terminate()
{
delete[] keyStates;
delete[] mouseStates;
}
main.cpp
#include <iostream>
#include "gui/window.h"
#include "gui/gl/shader.h"
#include <spdlog/spdlog.h>
#include <spdlog/fmt/bin_to_hex.h>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/scalar_multiplication.hpp>
glm::mat4 fpsView(glm::vec3 cam, float pitch, float yaw)
{
float cosPitch = cos(pitch);
float sinPitch = sin(pitch);
float cosYaw = cos(yaw);
float sinYaw = sin(yaw);
glm::vec3 xaxis = {cosYaw, 0, -sinYaw};
glm::vec3 yaxis = {sinYaw * sinPitch, cosPitch, cosYaw * sinPitch};
glm::vec3 zaxis = {sinYaw * cosPitch, -sinPitch, cosPitch * cosYaw};
// Create a 4x4 view matrix from the right, up, forward and eye position vectors
glm::mat4 viewMatrix = {
glm::vec4(xaxis.x, yaxis.x, zaxis.x, 0),
glm::vec4(xaxis.y, yaxis.y, zaxis.y, 0),
glm::vec4(xaxis.z, yaxis.z, zaxis.z, 0),
glm::vec4(-glm::dot(xaxis, cam), -glm::dot(yaxis, cam), -glm::dot(zaxis, cam), 1)};
return viewMatrix;
}
int main(int, char **)
{
#ifndef NDEBUG
spdlog::set_level(spdlog::level::trace);
#endif
Window window("Test GL", 800, 600);
if (!window.hasCorrectlyLoaded())
{
return 1;
}
float vertices[] = {
0.5f, 0.5f, 0.0f, // top right
0.5f, -0.5f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f // top left
};
unsigned int indices[] = {
// note that we start from 0!
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
Shader shader;
unsigned int VAO;
GL(glGenVertexArrays(1, &VAO));
GL(glBindVertexArray(VAO));
unsigned int VBO;
GL(glGenBuffers(1, &VBO));
GL(glBindBuffer(GL_ARRAY_BUFFER, VBO));
GL(glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW));
unsigned int EBO;
GL(glGenBuffers(1, &EBO));
GL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO));
GL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW));
GL(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void *)0));
GL(glEnableVertexAttribArray(0));
glm::mat4 Projection = glm::perspective(glm::radians(90.0f), (float)800 / (float)600, 0.1f, 100.0f);
glm::vec3 cam{4, 3, 3};
glm::vec2 dir{0, 0};
glm::mat4 Model = glm::mat4(1.0f);
while (!window.shouldClose())
{
GL(glClearColor(0.2f, 0.3f, 0.3f, 1.0f));
GL(glClear(GL_COLOR_BUFFER_BIT));
glm::mat4 View = fpsView(cam, dir.y, dir.x);
glm::mat4 mvp = Projection * View * Model;
shader.setUniform("MVP", &mvp);
shader.bind();
GL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO));
GL(glBindVertexArray(VAO));
GL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0));
GL(glBindVertexArray(0));
window.pollEvents();
if (Input::isPressed(GLFW_KEY_ESCAPE))
{
window.exitNextFrame();
}
if (Input::isPressed(GLFW_KEY_F6))
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
else if (Input::isReleased(GLFW_KEY_F6))
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
glm::dvec2 d = Input::getMouseDelta();
dir += d * 0.001;
}
spdlog::default_logger()->info("Quitting !");
}
I'm trying to make a color picker tool in OpenGL. It works you can use the code below. However there is one glaring issue, if you test the program you will find that if you click the black background, the color selected will become black. So my question is how do I change the code such that it recognizes which polygon I clicked or recognizes that I clicked on something or a polygon.
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <cmath>
#include <iterator>
//static void mouseButtonCallback(GLFWwindow* window, int button, int action, int mod);
static void mouse_cursor_callback(GLFWwindow* window, double xpos, double ypos);
float randfloat(){
float r = ((float)(rand() % 10))/10;
return r;
}
class RGB{
public:
float r;
float g;
float b;
void setColor(float _r, float _g, float _b){
r = _r;
g = _g;
b = _b;
}
};
RGB selected_col;
RGB mixColor(RGB color1, RGB color2){
float r = 0;
float g = 0;
float b = 0;
r = sqrt((pow(color1.r,2)+pow(color2.r,2))/2);
g = sqrt((pow(color1.g,2)+pow(color2.g,2))/2);
b = sqrt((pow(color1.b,2)+pow(color2.b,2))/2);
RGB a;
a.setColor(r,g,b);
return a;
}
int main() {
int side_count;
std::cout<<"Type the no. of sides: "<<std::endl;
std::cin>>side_count;
if(side_count < 3){
return 1;
}
srand((unsigned)time(0));
float rs[side_count];
float gs[side_count];
float bs[side_count];
RGB colors[side_count];
for (int i=0;i<side_count;i++)
{
rs[i] = randfloat();
gs[i] = randfloat();
bs[i] = randfloat();
colors[i].setColor(rs[i],gs[i],bs[i]);
}
GLFWwindow* window;
if (!glfwInit())
return 1;
window = glfwCreateWindow(400, 400, "Window", NULL, NULL);
//glfwSetMouseButtonCallback(window, mouseButtonCallback);
glfwSetCursorPosCallback(window, mouse_cursor_callback);
if (!window) {
glfwTerminate();
return 1;
}
glfwMakeContextCurrent(window);
if(glewInit()!=GLEW_OK)
std::cout<<"Error"<<std::endl;
RGB mcol = colors[1];
for(int i=0;i<side_count-1;i++)
{
mcol = mixColor(mcol, colors[i+1]);
}
while(!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
glColor3f(mcol.r,mcol.g,mcol.b);glVertex2f(0,0);
//glColor3f(1.0f,0.0f,0.0f);glVertex3f(-0.5f,0.0f,0.0f);
for(int i=0; i<=side_count;i++)
{
float r = rs[i%side_count];
float g = gs[i%side_count];
float b = bs[i%side_count];
float x = 0.5f * sin(2.0*M_PI*i/side_count);
float y = 0.5f * cos(2.0*M_PI*i/side_count);
glColor3f(r,g,b);glVertex2f(x,y);
}
glEnd();
glBegin(GL_QUADS);
glColor3f(selected_col.r, selected_col.g, selected_col.b);glVertex2f(-1.0f,0.5f);
glColor3f(selected_col.r, selected_col.g, selected_col.b);glVertex2f(-.5f,0.5f);
glColor3f(selected_col.r, selected_col.g, selected_col.b);glVertex2f(-.5f,1.5f);
glColor3f(selected_col.r, selected_col.g, selected_col.b);glVertex2f(-1.0f,1.5f);
glEnd();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
/*static void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods){
if(button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS){
double xPos, yPos;
glfwGetCursorPos(window, &xPos, &yPos);
//std::cout<<"X: "<<xPos<<" Y: "<<yPos<<std::endl;
double x=xPos;
int height,width;
glfwGetWindowSize(window, &width, &height);
double y = height - yPos;
unsigned char pixel[4];
glReadPixels(x, y, 1, 1, GL_RGB,GL_UNSIGNED_BYTE, &pixel);
selected_col.setColor((float)pixel[0]/255,(float)pixel[1]/255,(float)pixel[2]/255);
//std::cout<<"R: "<<selected_col.r<<" G: "<<selected_col.g<<" B: "<<selected_col.b<<std::endl;
}
}*/
void mouse_cursor_callback( GLFWwindow * window, double xpos, double ypos)
{
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_RELEASE)
{
return;
}
double xPos, yPos;
glfwGetCursorPos(window, &xPos, &yPos);
//std::cout<<"X: "<<xPos<<" Y: "<<yPos<<std::endl;
double x=xPos;
int height,width;
glfwGetWindowSize(window, &width, &height);
double y = height - yPos;
unsigned char pixel[4];
glReadPixels(x, y, 1, 1, GL_RGB,GL_UNSIGNED_BYTE, &pixel);
selected_col.setColor((float)pixel[0]/255,(float)pixel[1]/255,(float)pixel[2]/255);
//std::cout<<"R: "<<selected_col.r<<" G: "<<selected_col.g<<" B: "<<selected_col.b<<std::endl;
}
I want to move the object(6-point star with 2 triangles) with mouse clicking.
I wrote the following code, but there is no response.
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN) {
float x_min = (-x + 500) / 500;
float x_max = (x - 500) / 500;
float y_min = (-y + 500) / 500;
float y_max = (y - 500) / 500;
gluOrtho2D(x_min, x_max, y_min, y_max);
}
glutPostRedisplay();
break;
In the case GLUT_LEFT_BUTTON, I put minimum/maxmimum x and y position but nothing works when I clicked left mouse button.
Here is the full codes:
#include <stdlib.h>
#include <GL/glut.h>
float v1[3] = { -35.0f, 22.5f, 0.0f };
float v2[3] = { -35.0f, -22.5f, 0.0f };
float v3[3] = { 0.0f, 42.5f, 0.0f };
float v4[3] = { 0.0f, -42.5f, 0.0f };
float v5[3] = { 35.0f, 22.5f, 0.0f };
float v6[3] = { 35.0f, -22.5f, 0.0f };
static GLfloat spin = 0.0;
float x = 400.0f, y = 442.5f;
float x_position;
float y_position;
float color1[3] = { 1.0f, 1.0f, 1.0f };
float color2[3] = { 1.0f, 1.0f, 1.0f };
int mode = 1;
int rotate = 1;
void init(void);
void triangle_1(void);
void triangle_2(void);
void display(void);
void spinDisplay_1(void);
void spinDisplay_2(void);
void reshape(int, int);
void changeColor(int);
void mouse(int, int, int, int);
////////////////////////////////////////////////////////////////////
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(300, 300);
glutCreateWindow("6-Point Star");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMouseFunc(mouse);
glutMainLoop();
return 0;
}
////////////////////////////////////////////////////////////////////
void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
}
void triangle_1(void) { //// triangle_1 and triangle_2 make 6-point star ////
glColor3fv(color1);
glBegin(GL_TRIANGLE_FAN);
glVertex3fv(v1);
glVertex3fv(v4);
glVertex3fv(v5);
glEnd();
}
void triangle_2(void) {
glColor3fv(color2);
glBegin(GL_TRIANGLE_FAN);
glVertex3fv(v2);
glVertex3fv(v3);
glVertex3fv(v6);
glEnd();
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glTranslatef(x, y, 0.0f);
glRotatef(spin, 0.0, 0.0, 1.0);
triangle_1();
triangle_2();
glPopMatrix();
glutSwapBuffers();
}
void spinDisplay_1(void) {
spin = spin + 2.0;
if (spin > 360.0) {
spin = spin - 360.0;
}
glutPostRedisplay();
}
void spinDisplay_2(void) {
spin = spin - 2.0;
if (spin < 360.0) {
spin = spin + 360.0;
}
glutPostRedisplay();
}
void reshape(int w, int h) {
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 500.0, 0.0, 500.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void changeColor(int n) {
if (n == 1) {
color1[0] = 0.0f, color1[1] = 0.0f, color1[2] = 1.0f;
color2[0] = 0.0f, color2[1] = 1.0f, color2[2] = 0.0f;
}
else if (n == 2) {
color1[0] = 1.0f, color1[1] = 1.0f, color1[2] = 1.0f;
color2[0] = 1.0f, color2[1] = 1.0f, color2[2] = 1.0f;
}
}
void mouse(int button, int state, int x, int y) { /////// mouse event ////////
switch (button) {
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN) {
float x_min = (-x + 500) / 500;
float x_max = (x - 500) / 500;
float y_min = (-y + 500) / 500;
float y_max = (y - 500) / 500;
gluOrtho2D(x_min, x_max, y_min, y_max);
}
glutPostRedisplay();
break;
case GLUT_MIDDLE_BUTTON:
if (state == GLUT_DOWN) {
if (mode == 1) {
changeColor(mode);
mode = 2;
}
else if (mode == 2) {
changeColor(mode);
mode = 1;
}
}
break;
case GLUT_RIGHT_BUTTON:
if (state == GLUT_DOWN)
if (rotate == 1) {
glutIdleFunc(spinDisplay_1);
rotate = 2;
}
else if (rotate == 2) {
glutIdleFunc(spinDisplay_2);
rotate = 1;
}
break;
default:
break;
}
}
I want to move the object (6-point star with 2 triangles) with mouse clicking
If you want to left click and that position now being the center of the star, then you're overcomplicating things. You already have the star's position as global variables x and y. Thus in mouse() you just set those to the mouse position.
However remember to subtract the height of the window by y, since 0x0 is top left on the screen but bottom left in OpenGL.
if (state == GLUT_DOWN) {
::x = x;
::y = glutGet(GLUT_WINDOW_HEIGHT) - y;
}
Since mouse()'s x and y parameters shadows your global variables x and y, you have to prefix with ::. You could also rename mouse()'s parameters to say mx and my:
void mouse(int button, int state, int mx, int my) {
[...]
if (state == GLUT_DOWN) {
x = mx;
y = glutGet(GLUT_WINDOW_HEIGHT) - my;
}
Here's a GIF of clicking random places on the window:
Im having a problem with glutKeyboardUpFunc. Everytime I press a key and don't release it, the callback of glutKeyboardUpFunc stills gets called, the longer I hold the key the more times the callback executes.
Here is a quick example I put up:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include <time.h>
#include <GL/glut.h>
#define DEBUG 1
/* VARI�VEIS GLOBAIS */
typedef struct {
GLboolean doubleBuffer;
GLint delay;
} Estado;
typedef struct {
GLfloat x;
GLfloat y;
GLfloat height;
GLfloat width;
GLfloat y_accelaration;
} Plataforma;
//save stage coordinates
typedef struct {
GLfloat top;
GLfloat bottom;
GLfloat right;
GLfloat left;
} Screen;
Estado estado;
Screen ecra;
Plataforma plataforma;
GLfloat tab_speed = 2.0 / 20.0;
GLfloat y_accelaration = 0.001;
void Init(void) {
struct tm *current_time;
time_t timer = time(0);
estado.delay = 42;
estado.doubleBuffer = GL_TRUE;
plataforma.height = 0.3;
plataforma.width = 0.05;
plataforma.y_accelaration = 0;
plataforma.y = 0;
// L� hora do Sistema
current_time = localtime(&timer);
glClearColor(0.3, 0.3, 0.3, 0.0);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POLYGON_SMOOTH);
}
void Reshape(int width, int height) {
GLint size;
GLfloat ratio = (GLfloat) width / height;
GLfloat ratio1 = (GLfloat) height / width;
if (width < height)
size = width;
else
size = height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (width < height) {
ecra.left = -1;
ecra.right = 1;
ecra.bottom = -1 * ratio1;
ecra.top = 1 * ratio1;
gluOrtho2D(-1, 1, -1 * ratio1, 1 * ratio1);
} else {
ecra.left = -1 * ratio;
ecra.right = 1 * ratio;
ecra.bottom = -1;
ecra.top = 1;
gluOrtho2D(-1 * ratio, 1 * ratio, -1, 1);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void desenhar_plataforma(Plataforma pf) {
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_POLYGON);
glVertex2f(pf.x - pf.width / 2, pf.y - pf.height / 2);
glVertex2f(pf.x + pf.width / 2, pf.y - pf.height / 2);
glVertex2f(pf.x + pf.width / 2, pf.y + pf.height / 2);
glVertex2f(pf.x - pf.width / 2, pf.y + pf.height / 2);
glEnd();
}
void Draw(void) {
glClear(GL_COLOR_BUFFER_BIT);
plataforma.x = ecra.left + 0.1;
desenhar_plataforma(plataforma);
glFlush();
if (estado.doubleBuffer)
glutSwapBuffers();
}
void Key(unsigned char key, int x, int y) {
switch (key) {
case 'a':
plataforma.y += tab_speed;
glutPostRedisplay();
break;
case 's':
plataforma.y -= tab_speed;
glutPostRedisplay();
break;
}
}
void KeyUp(unsigned char key, int x, int y) {
if (DEBUG)
printf("Key Up %c\n", key);
}
int main(int argc, char **argv) {
estado.doubleBuffer = GL_TRUE;
glutInit(&argc, argv);
glutInitWindowPosition(0, 0);
glutInitWindowSize(800, 600);
glutInitDisplayMode(((estado.doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE) | GLUT_RGB);
if (glutCreateWindow("No Man's Pong") == GL_FALSE)
exit(1);
Init();
glutReshapeFunc(Reshape);
glutDisplayFunc(Draw);
// Callbacks de teclado
glutKeyboardFunc(Key);
glutKeyboardUpFunc(KeyUp);
glutMainLoop();
return 0;
}
Here's the ouput when pressing 'a':
Key Up a
Key Up a
Key Up a
Key Up a
Key Up a
Key Up a
Key Up a
......
Needless to say im not releasing 'a'.
Im using linux mint 17.3 and g++, shutting off key repeat or setting glutIgnoreKeyRepeat(true), stops this issue, but also makes glutKeyboardFunc execute only once per key press, and I realy don't want that.
Does anyone know how to fix this, or whats causing this?
I also compiled the same code under windows 8.1 and the keyUp only fires when there's an actual key release.
I have a very peculiar problem that I can not figure out. For my scene I have created a spline class which I use to generate points for which my camera traverses. This works fine and dandy when I create an instance of the spline class in my scene and use it. I have some functionality in my spline class for showing the points on the spline that use uniform data to draw their position and give them a color. This all works fine when I create an instance directly in my scene.
HOWEVER, I want to create multiple splines to have my camera traverse so I created a fairly simple management class to handle multiple splines. This works however for some reason I can not puzzle out why when I create an instance of a spline with the manager the uniform variables aren't working. Everything else works fine. When I say they don't work what I mean is that the getLocation functions work (they get the locationIDs as expected), the data to be sent is the same, there are no errors or warnings concerning the functions that are supposed to actually send the data down to their locations. The spline draws properly however they are always black and haven't been translated.
Here is my scene class. The constructors for both my manager and the spline class its self are exactly the same so in my ClothScene.hpp I can switch the type of the mSplineManager object from the manager class to the spline class and the uniform variables work fine.
#include "ClothScene.hpp"
#include <atlas/core/GLFW.hpp>
#include <atlas/core/Log.hpp>
#include <atlas/core/Macros.hpp>
#include <atlas/core/Float.hpp>
#include <iostream>
ClothScene::ClothScene() :
mIsPlaying(false),
mLastTime(0.0f),
mFPS(60.0f),
mTick(1.0f / mFPS),
mAnimTime(0.0f),
mAnimLength(10.0f),
mSplineManager(int(mAnimLength * mFPS)),
ballPosition{ -10.0f, 0.0f, 14.0f }
{
glEnable(GL_DEPTH_TEST);
auto mat = glm::translate(atlas::math::Matrix4(1.0f), ballPosition);
mBall.transformGeometry(mat);
}
ClothScene::~ClothScene() {
}
void ClothScene::mousePressEvent(int button, int action, int modifiers, double xPos, double yPos) {
USING_ATLAS_MATH_NS;
if (button == GLFW_MOUSE_BUTTON_LEFT && modifiers == GLFW_MOD_ALT)
{
if (action == GLFW_PRESS)
{
mIsDragging = true;
//Camera tilt up and down or turn left, right
mCamera.mouseDown(Point2(xPos, yPos), ClothCamera::CameraMovements::TUMBLE);
}
else
{
mIsDragging = false;
mCamera.mouseUp();
}
}
else if (button == GLFW_MOUSE_BUTTON_MIDDLE && modifiers == GLFW_MOD_ALT)
{
if (action == GLFW_PRESS)
{
mIsDragging = true;
//Camera move left, right, up, down
mCamera.mouseDown(Point2(xPos, yPos), ClothCamera::CameraMovements::TRACK);
}
else
{
mIsDragging = false;
mCamera.mouseUp();
}
}
else if (button == GLFW_MOUSE_BUTTON_RIGHT && modifiers == GLFW_MOD_ALT)
{
if (action == GLFW_PRESS)
{
// first click.
mIsDragging = true;
//Camera move back and forth
mCamera.mouseDown(Point2(xPos, yPos), ClothCamera::CameraMovements::DOLLY);
}
else
{
mIsDragging = false;
mCamera.mouseUp();
}
}
else if (action != GLFW_PRESS)
{
mIsDragging = false;
mCamera.mouseUp();
}
}
void ClothScene::mouseMoveEvent(double xPos, double yPos) {
mCamera.mouseUpdate(glm::vec2(xPos, yPos));
}
void ClothScene::keyPressEvent(int key, int scancode, int action, int mods) {
UNUSED(scancode);
UNUSED(mods);
if (action == GLFW_PRESS)
{
switch (key)
{
case GLFW_KEY_T:
mCamera.resetCamera();
break;
case GLFW_KEY_W:
mCamera.strafeCamera(0);
break;
case GLFW_KEY_S:
mCamera.strafeCamera(1);
break;
case GLFW_KEY_A:
mCamera.strafeCamera(2);
break;
case GLFW_KEY_D:
mCamera.strafeCamera(3);
break;
case GLFW_KEY_R:
mCamera.strafeCamera(4);
break;
case GLFW_KEY_F:
mCamera.strafeCamera(5);
break;
case GLFW_KEY_Q:
mCamera.strafeCamera(6);
break;
case GLFW_KEY_E:
mCamera.strafeCamera(7);
break;
case GLFW_KEY_C:
mCamera.newPosition(glm::vec3(0.0f, 3.0f, 0.0f));
break;
case GLFW_KEY_U:
mSplineManager.showSpline();
break;
case GLFW_KEY_I:
mSplineManager.showControlPoints();
break;
case GLFW_KEY_O:
mSplineManager.showCage();
break;
case GLFW_KEY_P:
mSplineManager.showSplinePoints();
break;
case GLFW_KEY_SPACE:
mIsPlaying = !mIsPlaying;
default:
break;
}
}
}
void ClothScene::screenResizeEvent(int width, int height) {
glViewport(0, 0, width, height);
mProjection = glm::perspective(glm::radians(45.0),(double)width / height, 1.0, 1000.0);
}
void ClothScene::renderScene() {
float grey = 161.0f / 255.0f;
glClearColor(grey, grey, grey, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
mView = mCamera.getCameraMatrix();
mGrid.renderGeometry(mProjection, mView);
mSplineManager.renderGeometry(mProjection, mView);
mBall.renderGeometry(mProjection, mView);
}
void ClothScene::updateScene(double time)
{
mTime.currentTime = (float)time;
mTime.totalTime += (float)time;
if (atlas::core::geq(mTime.currentTime - mLastTime, mTick))
{
mLastTime += mTick;
mTime.deltaTime = mTick;
if (mIsPlaying)
{
mAnimTime += mTick;
mSplineManager.updateGeometry(mTime);
if (mSplineManager.doneInterpolation())
{
mIsPlaying = false;
return;
}
auto point = mSplineManager.getSplinePosition();
mCamera.newPosition(point);
mCamera.lookAt(ballPosition);
auto mat = glm::translate(atlas::math::Matrix4(1.0f), ballPosition);
mBall.transformGeometry(mat);
}
}
}
Here is my SplineManger class. It super simple, it just creates a vector of splines and then applies the exact same functionality iterated through all of the splines in the vector. For some reason this prevents the shader from receiving the uniform data.
#include "SplineManager.hpp"
SplineManager::SplineManager(int totalFrames) :
finishedAllSplines(false),
currentSpline(0)
{
mTotalFrames = totalFrames;
addSplines();
}
SplineManager::~SplineManager() {
}
void SplineManager::addSplines() {
mControlPoints = std::vector<Point>
{
{ -20, -5, 0 },
{ -19, 5, -15 },
{ 12.7f, -5, -1.4f },
{ 20, 8.2f, 4.4f }
};
mSplines.push_back(Spline(mTotalFrames, mControlPoints));
}
void SplineManager::renderGeometry(atlas::math::Matrix4 projection, atlas::math::Matrix4 view) {
for (int i = 0; i < mSplines.size(); ++i) {
mSplines[i].renderGeometry(projection, view);
}
}
void SplineManager::updateGeometry(atlas::utils::Time const& t) {
mSplines[currentSpline].updateGeometry(t);
if (mSplines[currentSpline].doneInterpolation()) {
++currentSpline;
if (currentSpline == mSplines.size()) {
finishedAllSplines = true;
}
}
}
atlas::math::Point SplineManager::getSplinePosition() {
return mSplines[currentSpline].getSplinePosition();
}
void SplineManager::showSpline() {
for (int i = 0; i < mSplines.size(); ++i) {
mSplines[i].showSpline();
}
}
void SplineManager::showControlPoints() {
for (int i = 0; i < mSplines.size(); ++i) {
mSplines[i].showControlPoints();
}
}
void SplineManager::showCage() {
for (int i = 0; i < mSplines.size(); ++i) {
mSplines[i].showCage();
}
}
void SplineManager::showSplinePoints() {
for (int i = 0; i < mSplines.size(); ++i) {
mSplines[i].showSplinePoints();
}
}
bool SplineManager::doneInterpolation() {
return finishedAllSplines;
}
Here is my spline class. Again, this all works totally fine when I directly create an instance of it in the scene class. When instances are created in the SplineManager the uniform variables don't work.
#include "Spline.h"
#include "ShaderPaths.hpp"
#include <atlas/core/Macros.hpp>
Spline::Spline(int totalFrames) :
mResolution(500),
mTotalFrames(totalFrames),
mCurrentFrame(0),
mShowControlPoints(false),
mShowCage(false),
mShowSplinePoints(false),
mShowSpline(false),
mIsInterpolationDone(false)
{
USING_ATLAS_MATH_NS;
USING_ATLAS_GL_NS;
//Bezier
mBasisMatrix = Matrix4(
1.0f, 0.0f, 0.0f, 0.0f,
-3.0f, 3.0f, 0.0f, 0.0f,
3.0f, -6.0f, 3.0f, 0.0f,
-1.0f, 3.0f, -3.0f, 1.0f);
mControlPoints = std::vector<Point>
{
{ -20, -5, 0 },
{ -19, 5, -15 },
{ 12.7f, -5, -1.4f },
{ 20, 8.2f, 4.4f }
};
std::vector<Point> splinePoints;
float scale = 1.0f / mResolution;
for (int res = 0; res < mResolution + 1; ++res)
{
splinePoints.push_back(evaluateSpline(scale * res));
}
generateArcLengthTable();
glGenVertexArrays(1, &mVao);
glBindVertexArray(mVao);
glGenBuffers(1, &mControlBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mControlBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Point) * mControlPoints.size(),
mControlPoints.data(), GL_STATIC_DRAW);
glGenBuffers(1, &mSplineBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mSplineBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Point) * splinePoints.size(), splinePoints.data(), GL_STATIC_DRAW);
std::string shaderDir = generated::ShaderPaths::getShaderDirectory();
std::vector<ShaderInfo> shaders
{
{ GL_VERTEX_SHADER, shaderDir + "spline.vs.glsl" },
{ GL_FRAGMENT_SHADER, shaderDir + "spline.fs.glsl" }
};
mShaders.push_back(ShaderPointer(new Shader));
mShaders[0]->compileShaders(shaders);
mShaders[0]->linkShaders();
GLuint var;
var = mShaders[0]->getUniformVariable("uMVP");
mUniforms.insert(UniformKey("uMVP", var));
var = mShaders[0]->getUniformVariable("fColour");
mUniforms.insert(UniformKey("fColour", var));
mShaders[0]->disableShaders();
glBindVertexArray(0);
}
Spline::~Spline()
{
glDeleteVertexArrays(1, &mVao);
glDeleteVertexArrays(1, &mControlBuffer);
glDeleteVertexArrays(1, &mSplineBuffer);
}
void Spline::renderGeometry(atlas::math::Matrix4 projection,
atlas::math::Matrix4 view)
{
USING_ATLAS_MATH_NS;
mShaders[0]->enableShaders();
glBindVertexArray(mVao);
Matrix4 mvp = projection * view * mModel;
glUniformMatrix4fv(mUniforms["uMVP"], 1, GL_FALSE, &mvp[0][0]);
// Draw the control points first.
glUniform3f(mUniforms["fColour"], 1, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, mControlBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
if (mShowControlPoints)
{
glPointSize(5.0f);
glDrawArrays(GL_POINTS, 0, GLsizei(mControlPoints.size()));
glPointSize(1.0f);
}
if (mShowCage)
{
glDrawArrays(GL_LINE_STRIP, 0, GLsizei(mControlPoints.size()));
}
// Now draw the spline.
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, mSplineBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glUniform3f(mUniforms["fColour"], 0, 1, 0);
if (mShowSpline)
{
glLineWidth(5.0f);
glDrawArrays(GL_LINE_STRIP, 0, mResolution + 1);
glLineWidth(1.0f);
}
if (mShowSplinePoints)
{
glPointSize(8.0f);
glDrawArrays(GL_POINTS, 1, mResolution);
glPointSize(1.0f);
}
glDisableVertexAttribArray(0);
mShaders[0]->disableShaders();
}
void Spline::updateGeometry(atlas::utils::Time const& t)
{
UNUSED(t);
mSplinePosition = interpolateOnSpline();
mCurrentFrame++;
if (mCurrentFrame == mTotalFrames)
{
mIsInterpolationDone = true;
return;
}
}
void Spline::showControlPoints()
{
mShowControlPoints = !mShowControlPoints;
}
void Spline::showCage()
{
mShowCage = !mShowCage;
}
void Spline::showSplinePoints()
{
mShowSplinePoints = !mShowSplinePoints;
}
void Spline::showSpline()
{
mShowSpline = !mShowSpline;
}
bool Spline::doneInterpolation()
{
return mIsInterpolationDone;
}
atlas::math::Point Spline::getSplinePosition()
{
return mSplinePosition;
}
atlas::math::Point Spline::interpolateOnSpline()
{
int n = int(mTable.size());
float totalDistance = mTable[n - 1];
float step = totalDistance / mTotalFrames;
float currDistance = step * mCurrentFrame;
int index = tableLookUp(currDistance);
float t = (1.0f / mResolution) * (index % mResolution);
return evaluateSpline(t);
}
atlas::math::Point Spline::evaluateSpline(float t)
{
USING_ATLAS_MATH_NS;
Vector4 xControls =
{
mControlPoints[0].x, mControlPoints[1].x,
mControlPoints[2].x, mControlPoints[3].x
};
Vector4 yControls =
{
mControlPoints[0].y, mControlPoints[1].y,
mControlPoints[2].y, mControlPoints[3].y
};
Vector4 zControls =
{
mControlPoints[0].z, mControlPoints[1].z,
mControlPoints[2].z, mControlPoints[3].z
};
Vector4 xCoeff = xControls * mBasisMatrix;
Vector4 yCoeff = yControls * mBasisMatrix;
Vector4 zCoeff = zControls * mBasisMatrix;
float xcr, ycr, zcr;
xcr = xCoeff[0] + t * xCoeff[1] + t * t * xCoeff[2] + t * t * t * xCoeff[3];
ycr = yCoeff[0] + t * yCoeff[1] + t * t * yCoeff[2] + t * t * t * yCoeff[3];
zcr = zCoeff[0] + t * zCoeff[1] + t * t * zCoeff[2] + t * t * t * zCoeff[3];
return Point(xcr, ycr, zcr);
}
void Spline::generateArcLengthTable()
{
USING_ATLAS_MATH_NS;
if (!mTable.empty())
{
mTable.clear();
}
float scale = 1.0f / mResolution;
mTable.push_back(0.0f);
for (int i = 1; i < mResolution + 1; ++i)
{
Point p0 = evaluateSpline((i - 1) * scale);
Point p1 = evaluateSpline(i * scale);
Point dist = p0 - p1;
mTable.push_back(mTable[i - 1] + glm::length(dist));
}
}
int Spline::tableLookUp(float distance)
{
// Find the entry in our table that corresponds to the given distance.
float epsilon = chooseEpsilon();
for (int i = 0; i < int(mTable.size()); ++i)
{
if (glm::abs(mTable[i] - distance) < epsilon)
{
return i;
}
}
return -1;
}
float Spline::chooseEpsilon()
{
// Find the largest difference and use that to look up distances
// in our table.
float epsilon = 0.0f;
float diff;
for (int i = 0; i < mTable.size() - 1; ++i)
{
diff = glm::abs(mTable[i] - mTable[i + 1]);
if (diff > epsilon)
{
epsilon = diff;
}
}
return epsilon;
}
void Spline::setSplineCoordinates(std::vector<atlas::math::Point> mControlPoints_) {
mControlPoints = mControlPoints_;
}
The header files for anyone interested.
SplineManager.hpp
#ifndef SPLINEMANAGER_HPP
#define SPLINEMANAGER_HPP
#pragma once
#include <atlas/utils/Geometry.hpp>
#include "Spline.h"
USING_ATLAS_MATH_NS;
USING_ATLAS_GL_NS;
class SplineManager : public atlas::utils::Geometry {
public:
SplineManager(int totalFrames);
~SplineManager();
atlas::math::Point getSplinePosition();
void addSplines();
void showSpline();
void showControlPoints();
void showCage();
void showSplinePoints();
bool doneInterpolation();
void updateGeometry(atlas::utils::Time const& t) override;
void renderGeometry(atlas::math::Matrix4 projection, atlas::math::Matrix4 view) override;
private:
std::vector<Spline> mSplines;
std::vector<atlas::math::Point> mControlPoints;
int mTotalFrames;
int currentSpline;
bool finishedAllSplines;
};
#endif
Spline.h
#ifndef LAB04_INCLUDE_SPLINE_HPP
#define LAB04_INCLUDE_SPLINE_HPP
#pragma once
#include <atlas/utils/Geometry.hpp>
#include <fstream>
class Spline : public atlas::utils::Geometry
{
public:
Spline(int totalFrames, std::vector<atlas::math::Point> mControlPoints_);
Spline(int totalFrames);
~Spline();
void renderGeometry(atlas::math::Matrix4 projection,
atlas::math::Matrix4 view) override;
void updateGeometry(atlas::utils::Time const& t) override;
void showControlPoints();
void showCage();
void showSplinePoints();
void showSpline();
bool doneInterpolation();
atlas::math::Point getSplinePosition();
void setSplineCoordinates(std::vector<atlas::math::Point> mControlPoints_);
private:
atlas::math::Point interpolateOnSpline();
atlas::math::Point evaluateSpline(float t);
void generateArcLengthTable();
int tableLookUp(float distance);
float chooseEpsilon();
atlas::math::Matrix4 mBasisMatrix;
std::vector<atlas::math::Point> mControlPoints;
std::vector<float> mTable;
atlas::math::Point mSplinePosition;
GLuint mVao;
GLuint mControlBuffer;
GLuint mSplineBuffer;
int mResolution;
int mTotalFrames;
int mCurrentFrame;
bool mShowControlPoints;
bool mShowCage;
bool mShowSplinePoints;
bool mShowSpline;
bool mIsInterpolationDone;
};
#endif
ClothScene.hpp
#ifndef SCENE_HPP
#define SCENE_HPP
#pragma once
#include <atlas\utils\Scene.hpp>
#include "ClothCamera.hpp"
#include "SplineManager.hpp"
#include "Grid.hpp"
#include "Spline.h"
#include "Ball.hpp"
//#include "Cloth.hpp"
class ClothScene : public atlas::utils::Scene {
public:
ClothScene();
~ClothScene();
void mousePressEvent(int button, int action, int modifiers, double xPos, double yPos) override;
void mouseMoveEvent(double xPos, double yPos) override;
void keyPressEvent(int key, int scancode, int action, int mods) override;
void screenResizeEvent(int width, int height) override;
void renderScene() override;
void updateScene(double time) override;
private:
bool mIsDragging;
bool mIsPlaying;
float mLastTime;
float mFPS;
float mTick;
float mAnimTime;
float mAnimLength;
glm::vec3 ballPosition;
ClothCamera mCamera;
Grid mGrid;
SplineManager mSplineManager;//, mSpline2;
Ball mBall;
std::vector<atlas::math::Point> mControlPoints;
};
#endif