我有以下程序使用Bézier曲线绘制弧线:
#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;
}
这里的曲线是用Bézier曲线制作的,所以每条曲线都是一系列直线,使它看起来像弧/曲线。正如你在最右边的弧线所看到的那样,它超越了窗户界限。当这样的事情发生时,我想限制它并将超出的线保持在窗口内(或者至少沿着窗口的边缘)。
我对这个问题的看法是减去超出点距离窗口边缘的距离,但这似乎不起作用。它是这样的:
double dist = exceedingPoint - boundaryValue;
exceedingPoint = exceedingPoint - dist;
谢谢!
答案 0 :(得分:0)
我不确定这是否真的有资格作为OpenGL问题 - 但更多的是解决问题。
取决于您的需求(以及查看上述评论) -
1)您可以评估贝塞尔曲线的大小(找出矩形的大小,如果它包含曲线),然后查看它是否会超出窗口大小。调整大小或移动曲线以使其适应。
2)在计算点时评估点。如果它们看起来像是在窗口之外,那么将点的坐标设置为窗口的边缘。
3)学习GLSL并弄清楚Vertex Shader如何能够做到#2。
基本上,你可以做很多事情。再试一次!