Я новичок в OpenGl, сейчас мой код может перемещать большой круг с маленьким внутри него вокруг окна. Подскажите, пожалуйста, как переместить маленький круг отдельно от большого, а также как вытащить его из большого круга.
И когда, например: маленький круг находится внутри большого, когда они движутся, они движутся вместе, и есть линия, которая соединяет центр окна с маленьким вихрем.
Вот мой код:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "glm/glm.hpp"
#include <array>
#include <iostream>
#include <string>
#include <fstream>
#define PI 3.14159265359
using namespace std;
#define numVAOs 1
GLuint VBO;
GLuint VAO;
GLfloat radius = 0.2;
GLfloat centerx = 0.3;
GLfloat centery = 0;
GLfloat novX = 0.009;
GLfloat novY = 0.005;
GLdouble updateFrequency = 0.01, lastUpdate;
GLfloat s_vertices[600];
void updateVertexData()
{
for (int i = 0; i < 100; i++)
{
s_vertices[3 * i] = centerx + radius * cos(i * (2 * PI / 100));
s_vertices[3 * i + 1] = centery + radius * sin(i * (2 * PI / 100));
s_vertices[3 * i + 2] = 0;
}
}
void updateVertexData1()
{
for (int j = 100; j < 200; j++) {
s_vertices[3 * j] = centerx + radius * (cos(j * (2 * PI / 100))) / 5;
s_vertices[3 * j + 1] = centery + radius * (sin(j * (2 * PI / 100))) / 5;
s_vertices[3 * j + 2] = 0;
}
}
void updateVBO() {
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(s_vertices), s_vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
GLuint renderingProgram;
GLuint vao[numVAOs];
bool checkOpenGLError() {
bool foundError = false;
int glErr = glGetError();
while (glErr != GL_NO_ERROR) {
cout << "glError: " << glErr << endl;
foundError = true;
glErr = glGetError();
}
return foundError;
}
void printShaderLog(GLuint shader) {
int len = 0;
int chWrittn = 0;
char* log;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
if (len > 0) {
log = (char*)malloc(len);
glGetShaderInfoLog(shader, len, &chWrittn, log);
cout << "Shader Info Log: " << log << endl;
free(log);
}
}
void printProgramLog(int prog) {
int len = 0;
int chWrittn = 0;
char* log;
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len);
if (len > 0) {
log = (char*)malloc(len);
glGetProgramInfoLog(prog, len, &chWrittn, log);
cout << "Program Info Log: " << log << endl;
free(log);
}
}
string readShaderSource(const char* filePath) {
string content;
ifstream fileStream(filePath, ios::in);
string line = "";
while (!fileStream.eof()) {
getline(fileStream, line);
content.append(line + "\n");
}
fileStream.close();
return content;
}
GLuint createShaderProgram() {
GLint vertCompiled;
GLint fragCompiled;
GLint linked;
string vertShaderStr = readShaderSource("vertexShader.glsl");
string fragShaderStr = readShaderSource("fragmentShader.glsl");
GLuint vShader = glCreateShader(GL_VERTEX_SHADER);
GLuint fShader = glCreateShader(GL_FRAGMENT_SHADER);
const char* vertShaderSrc = vertShaderStr.c_str();
const char* fragShaderSrc = fragShaderStr.c_str();
glShaderSource(vShader, 1, &vertShaderSrc, NULL);
glShaderSource(fShader, 1, &fragShaderSrc, NULL);
glCompileShader(vShader);
checkOpenGLError();
glGetShaderiv(vShader, GL_COMPILE_STATUS, &vertCompiled);
if (vertCompiled != 1) {
cout << "vertex compilation failed" << endl;
printShaderLog(vShader);
}
glCompileShader(fShader);
checkOpenGLError();
glGetShaderiv(vShader, GL_COMPILE_STATUS, &fragCompiled);
if (fragCompiled != 1) {
cout << "fragment compilation failed" << endl;
printShaderLog(fShader);
}
GLuint vfProgram = glCreateProgram();
glAttachShader(vfProgram, vShader);
glAttachShader(vfProgram, fShader);
glLinkProgram(vfProgram);
checkOpenGLError();
glGetProgramiv(vfProgram, GL_LINK_STATUS, &linked);
if (linked != 1) {
cout << "linking failed" << endl;
printProgramLog(vfProgram);
}
glDeleteShader(vShader);
glDeleteShader(fShader);
return vfProgram;
}
void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action == GLFW_PRESS)
{
switch (key) {
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, GLFW_TRUE);
break;
case GLFW_KEY_L:
novX *= -1;
break;
case GLFW_KEY_R:
radius += 0.01;
updateVertexData();
updateVertexData1();
updateVBO();
break;
}
}
}
void cursorPosCallback(GLFWwindow* window, double xPos, double yPos)
{
}
void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
{
}
void init() {
renderingProgram = createShaderProgram();
glGenBuffers(1, &VBO);
glGenVertexArrays(1, &VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(s_vertices), s_vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void cleanUpScene()
{
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(renderingProgram);
}
void display(GLFWwindow* window, double currentTime) {
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT); // fontos lehet minden egyes alkalommal törölni!
glUseProgram(renderingProgram);
glBindVertexArray(VAO);
glPointSize(8.0);
glDrawArrays(GL_LINE_LOOP, 0, 99);
glDrawArrays(GL_LINE_LOOP, 100, 200);
if (currentTime - lastUpdate >= updateFrequency) {
centerx += novX;
centery += novY;
if (centerx + radius > 1 - abs(novX) || centerx - radius < -1 + abs(novX))
novX *= -1;
if (centery + radius > 1 - abs(novY) || centery - radius < -1 + abs(novY))
novY *= -1;
lastUpdate = currentTime;
updateVertexData();
updateVertexData1();
updateVBO();
}
glBindVertexArray(0);
}
int main(void) {
updateVertexData();
updateVertexData1();
if (!glfwInit()) { exit(EXIT_FAILURE); }
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
GLFWwindow* window = glfwCreateWindow(600, 600, "VAO VBO", NULL, NULL);
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, keyCallback);
if (glewInit() != GLEW_OK) { exit(EXIT_FAILURE); }
glfwSwapInterval(1);
init();
lastUpdate = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
display(window, glfwGetTime());
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
cleanUpScene();
glfwTerminate();
exit(EXIT_SUCCESS);
}