OpenGL — помогите ограничить кривые, чтобы никогда не выходить за пределы

У меня есть следующая программа для рисования дуг, используя кривые Безье:

#include <GL/gl.h>
#include <GL/glu.h>
#include <stdlib.h>
#include <GL/openglut.h>
#include <math.h>
#include <stdio.h>
#include <iostream>
#include <time.h>
#include <ctime>
#include <cstdlib>
#include <fstream>
#include <sstream>std::ofstream nul("/dev/null");
std::ostream * err=&std::cerr;

class Point {
public:
int _id;
GLfloat _x;
GLfloat _y;
GLfloat _z;

Point(int id, GLfloat x, GLfloat y, GLfloat z) :
_id(id),
_x(x),
_y(y),
_z(z) {
}

void PrintPoint() {
printf("Point %d = <%f, %f, %f>\n", _id, _x, _y, _z);
}
};

Point getControl(Point a, Point b){

if(a._x < b._x && a._y < b._y){
Point ctrl(10, ((a._x+b._x)/2)+(0.25*(b._x-a._x)), ((a._y+b._y)/2)-(0.25*(b._x-a._x)), 0.0);
return ctrl;
} else if(a._x < b._x && a._y > b._y){
Point ctrl(10, ((a._x+b._x)/2)+(0.25*(b._x-a._x)), ((a._y+b._y)/2)-(0.25*(b._x-a._x)), 0.0);
return ctrl;
} else if(b._x < a._x && b._y < a._y){
Point ctrl(10, ((a._x+b._x)/2)+(0.25*(b._x-a._x)), ((a._y+b._y)/2)-(0.25*(b._x-a._x)), 0.0);
return ctrl;
} else if(b._x < a._x && b._y > a._y){
Point ctrl(10, ((a._x+b._x)/2)+(0.25*(b._x-a._x)), ((a._y+b._y)/2)-(0.25*(b._x-a._x)), 0.0);
return ctrl;
} else if(a._x == b._x && a._y != b._y){
Point ctrl(10, ((a._x+b._x)/2) + (0.25*a._x), (a._y+b._y)/2, 0.0);
return ctrl;
} else if(a._x != b._x && a._y == b._y){
Point ctrl(10, ((a._x+b._x)/2), ((a._y+b._y)/2) + (0.25*a._y), 0.0);
return ctrl;
}
return a;
}

GLfloat bezierP(float t, GLfloat P0, GLfloat P1, GLfloat P2, GLfloat P3) {
GLfloat point = (pow((1-t), 3.0) * P0) +
(3 * pow((1-t),2) * t * P1) +
(3 * (1-t) * t * t * P2) +
(pow(t, 3) * P3);
return point;
}

void drawBezierArc(Point start, Point end){

Point ctrl = getControl(start, end);
start.PrintPoint();
end.PrintPoint();
ctrl.PrintPoint();

int i;

glColor3f(1.0, 1.0, 0.0);
glBegin(GL_LINE_STRIP);
int t = 60;
for (i = 0; i <= t; i++) {
float pos = (float) i / (float) t;
GLfloat x = bezierP(pos, start._x, ctrl._x, ctrl._x, end._x);
GLfloat y = bezierP(pos, start._y, ctrl._y, ctrl._y, end._y);
GLfloat z = bezierP(pos, start._z, ctrl._z, ctrl._z, end._z);

glVertex3f(x, y, z);
}
glEnd();

glFlush();
}

void display(void) {

Point start1(0, 6, -2, 0);
Point end1(0, 6, 4, 0);

Point start2(0, 0, 2, 0);
Point end2(0, 4, 3, 0);

Point start3(0, -2, 0, 0);
Point end3(0, 1, 0, 0);

Point start4(0, -4, 3, 0);
Point end4(0, -4, -2, 0);

drawBezierArc(start1, end1);
drawBezierArc(start2, end2);
drawBezierArc(start3, end3);
drawBezierArc(start4, end4);

glFlush();
}

void reshape(int w, int h) {
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

if (w <= h) {
glOrtho(-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w, 5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0);
} else {
glOrtho(-5.0*(GLfloat)w/(GLfloat)h, 5.0*(GLfloat)w/(GLfloat)h, -5.0, 5.0, -5.0, 5.0);
}

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

int main(int argc, char** argv){
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (640, 480);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);

glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glShadeModel(GL_FLAT);

glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}

проблема

Кривые здесь сделаны с помощью кривых Безье, поэтому каждая кривая представляет собой серию из множества прямых линий, которые делают ее похожей на дугу / кривую. Как вы можете видеть по дуге справа, она выходит за границы окон. Когда что-то подобное происходит, я хотел бы ограничить это и сохранить лишние линии внутри окна (или, по крайней мере, идти вдоль края окна).

Моя задача была в том, чтобы вычесть расстояние, на котором точки превышения находятся от края окна, но это, похоже, не сработало. Это было что-то вроде этого:

double dist = exceedingPoint - boundaryValue;
exceedingPoint = exceedingPoint - dist;

Спасибо!

1

Решение

Я не уверен, действительно ли это квалифицируется как вопрос OpenGL — но это скорее вопрос решения проблем.

В зависимости от того, что вы хотите (и от просмотра ваших комментариев выше) —

1) Вы можете оценить размер кривой Безье (узнать, насколько большим будет прямоугольник, если он содержит кривую), а затем посмотреть, не превысит ли он размер окна. Измените размер или переместите кривую, чтобы подогнать ее обратно.

2) Оцените баллы по мере их расчета. Если они выходят за пределы окна, установите координату точки на краю окна.

3) Изучите GLSL и выясните, как вершинный шейдер также может выполнять # 2.

В принципе, есть много вещей, которые вы можете сделать. Попробуйте снова!

0

Другие решения