【问题标题】:OpenGL - Help restricting curves to never go out of boundsOpenGL - 帮助限制曲线永远不会越界
【发布时间】:2014-04-18 17:44:03
【问题描述】:

我有以下使用贝塞尔曲线绘制弧线的程序:

#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;

谢谢!

【问题讨论】:

  • 你能告诉我们更多细节吗?截图?你想到了什么样的代码?给我们一些东西来解决,你也不会发现很多人花时间为你的程序下载任何依赖项并自己构建它,所以解释它就好像我们不能 自己运行程序
  • 感谢您纠正我的错误帖子。我添加了更多细节、代码和图片。
  • 您是专门控制特定的行,还是只想要屏幕内的所有行?
  • 贝塞尔曲线由其控制点的凸包包围。所以一个包含所有控制点的矩形将完全包含曲线。您可以将贝塞尔曲线细分为两条独立的贝塞尔曲线,并递归应用此过程。
  • 好吧,正如我的回答所暗示的那样,您不能在抽签前应用glTranslatef 来解决越界问题吗?

标签: c++ opengl bezier curves


【解决方案1】:

我不确定这是否真的符合 OpenGL 问题 - 但更多的是解决问题的问题。

取决于你想要什么(以及从上面看你的 cmets) -

1) 您可以评估贝塞尔曲线的大小(如果矩形包含曲线,则找出矩形的大小),然后查看它是否会超过窗口大小。调整曲线大小或移动曲线以使其重新适合。

2) 在计算点时评估它们。如果它们似乎超出了窗口,则将该点的坐标设置为窗口的边缘。

3) 学习 GLSL 并弄清楚顶点着色器如何能够完成 #2。

基本上,您可以做很多事情。再试一次!

【讨论】:

  • 我已经尝试了选项 2,它看起来很简单,很容易开始工作,但它没有。反正我要再试一次
  • 如果您的坐标空间设置正确(比如说 - 应用程序中的一个“单位”== 窗口中的一个像素),那么 #2 应该很容易。尝试检查是否可以简单地在窗口边缘绘制一条直线,然后从那里开始。
猜你喜欢
  • 2014-01-15
  • 1970-01-01
  • 1970-01-01
  • 2012-04-27
  • 1970-01-01
  • 1970-01-01
  • 2017-01-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多