Вот простая, но полная и протестированная программа opengl, которая демонстрирует то, что звучит так, как вы ищете. Обратите внимание, что нет единого ответа на вопрос, что такое дуга между двумя точками на радиусе x, поскольку дуга может изгибаться в любом из двух направлений.
Обратите особое внимание на перегрузку функции second createArc , поскольку она представляет собой ядро ответа, хотя она вызывает first createArc Перегрузка функции для завершения работы.
РЕДАКТИРОВАТЬ: я понял, что я не учел неоднозначность «дуги между двумя углами» в моем предыдущем ответе (дуга от 0 до 90 может быть прямой или наоборот). Я обновил код, чтобы определить, интересуетесь ли вы меньшей или большей дугой.
#define GLEW_STATIC
#define _USE_MATH_DEFINES
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <gl/gl.h>
#include <math.h>
#include <iostream>
const int ARC_VERTEX_COUNT = 100;
// Don't use global variables at home, kids!
GLFWwindow* window;
GLuint shader;
GLint shaderLoc_pos;
GLuint vbo_circle;
GLuint vbo_arc;
float normalizeAngleToSmallestPositive(float angle) {
while (angle < 0.0) { angle += M_PI*2; }
while (angle >= M_PI*2) { angle -= M_PI*2; }
return angle;
}
bool startApp() {
if (!glfwInit()) {
return false;
}
window = glfwCreateWindow(500, 500, "Hello World", NULL, NULL);
if (!window) {
glfwTerminate();
return false;
}
glfwMakeContextCurrent(window);
glewInit();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glLineWidth(10.0);
return true;
}
void stopApp() {
glfwTerminate();
}
void createShader() {
const char* vsSrc =
"#version 330 core\n"
"in vec2 pos; void main() { gl_Position = vec4(pos, 0.0, 1.0); }";
const char* fsSrc =
"#version 330 core\n"
"out vec4 color; void main() { color = vec4(1.0,1.0,1.0,0.5); }";
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vsSrc, nullptr);
glCompileShader(vs);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fsSrc, nullptr);
glCompileShader(fs);
shader = glCreateProgram();
glAttachShader(shader, vs);
glAttachShader(shader, fs);
glLinkProgram(shader);
shaderLoc_pos = glGetAttribLocation(shader, "pos");
}
// Create an arc between two given angles, based on the circle described by the given radius and
// center point
GLuint createArc(float angle1, float angle2, float radius, float x, float y, float useBiggerArc) {
// Prepare angles
angle1 = normalizeAngleToSmallestPositive(angle1);
angle2 = normalizeAngleToSmallestPositive(angle2);
if (angle1 > angle2) {
float buffer = angle1;
angle1 = angle2;
angle2 = buffer;
}
if (useBiggerArc != angle2-angle1 > M_PI) {
angle1 += M_PI*2;
}
// Create opengl geometry
GLfloat pos[ARC_VERTEX_COUNT * 2];
for (int i = 0; i < ARC_VERTEX_COUNT; i++) {
pos[i*2] = sin((float)i / (ARC_VERTEX_COUNT-1) * (angle2 - angle1) + angle1) * radius + x;
pos[i*2+1] = cos((float)i / (ARC_VERTEX_COUNT-1) * (angle2 - angle1) + angle1) * radius + y;
}
GLuint result;
glGenBuffers(1, &result);
glBindBuffer(GL_ARRAY_BUFFER, result);
glBufferData(GL_ARRAY_BUFFER, sizeof(pos), pos, GL_STATIC_DRAW);
return result;
}
GLuint createCircle(float radius, float x, float y) {
return createArc(M_PI*0, M_PI*2, radius, x, y, true);
}
// Create an arc between two given points that is based on a circle with the given radius.
GLuint createArc(
float x1, float y1, float x2, float y2, float radius, bool arcDirection, bool useBiggerArc)
{
// distance between points
float distance = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
// halfway point
float xAverage = (x1+x2)/2.0;
float yAverage = (y1+y2)/2.0;
// circle center
float xCenter = sqrt(radius*radius - distance*distance/4.0) * (y1-y2) / distance;
float yCenter = sqrt(radius*radius - distance*distance/4.0) * (x2-x1) / distance;
xCenter = xAverage + (arcDirection ? xCenter : -xCenter);
yCenter = yAverage + (arcDirection ? yCenter : -yCenter);
// angles
float angle1 = atan2(x1-xCenter, y1-yCenter);
float angle2 = atan2(x2-xCenter, y2-yCenter);
// create the arc
return createArc(angle1, angle2, radius, xCenter, yCenter, useBiggerArc);
}
void runMainLoop() {
while (!glfwWindowShouldClose(window)) {
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader);
glEnableVertexAttribArray(shaderLoc_pos);
glBindBuffer(GL_ARRAY_BUFFER, vbo_circle);
glVertexAttribPointer(shaderLoc_pos, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
glDrawArrays(GL_LINE_STRIP, 0, ARC_VERTEX_COUNT);
glBindBuffer(GL_ARRAY_BUFFER, vbo_arc);
glVertexAttribPointer(shaderLoc_pos, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
glDrawArrays(GL_LINE_STRIP, 0, ARC_VERTEX_COUNT);
glfwSwapBuffers(window);
glfwPollEvents();
}
}
int main(void) {
if (startApp())
{
createShader();
vbo_circle = createCircle(0.75, 0.0, 0.0);
vbo_arc = createArc(0.0, 0.75, 0.75, 0.0, 0.75, false, false);
runMainLoop();
stopApp();
return 0;
}
else
{
return -1;
}
}