如何清除我的beziercurve矢量以停止在彼此之上编写坐标?

发布于 2025-01-31 02:12:42 字数 8564 浏览 2 评论 0原文

我已经构建了一个更BE的曲线工具,每次计算每个曲线段的坐标时,它们都存储在向量中。我每帧都一遍又一遍地添加整个曲线的点。也就是说,帧1可能具有{p1,p2,p3}然后帧2,它将具有{p1,p2, p3,p1 ,p2,p3}等。当渲染函数末尾的循环在点P3和P1之间绘制线路时,这将导致线路回循环。我正在努力寻找在框架之间的beziercurve向量的位置和如何清除。 glclear()glswapbuffers()仅显示先前绘制的曲线段,并且在点之间有直线。 我基本上希望在点之间的直线消失,我知道为什么会发生。我的代码下面:

“

#include <iostream>
#include <stdlib.h>
#include <GL/glut.h>
#include <vector>
#include <math.h>

using namespace std;

//Point class for taking the points
class Point {
public:
    float x, y;

    void setxy(float x2, float y2)
    {
        x = x2; y = y2;
    }

    //operator overloading for '=' sign
    const Point& operator=(const Point& rPoint)
    {
        x = rPoint.x;
        y = rPoint.y;
        return *this;
    }

};

int SCREEN_HEIGHT = 500;
vector<Point> Points;
Point Tangent;
Point inverseTangent;
Point cursorLocationLive;
int TangentsSize = 0;
vector<Point> Tangents(TangentsSize);
vector<Point> inverseTangents(TangentsSize);
vector<Point> BezierCurve;
bool MouseReleased = false;

void drawDot(Point p1)
{
    glBegin(GL_POINTS);
    glVertex2i(p1.x, p1.y);
    glEnd();
}

void drawLine(Point p1, Point p2)
{
    glBegin(GL_LINE_STRIP);
    glVertex2f(p1.x, p1.y);
    glVertex2f(p2.x, p2.y);
    glEnd();
}

float interpolate(float n1, float n2, float perc)
{
    float diff = n2 - n1;

    return n1 + (diff * perc);
}

void myMouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON)
    {
        if (state == GLUT_DOWN)
        {
            MouseReleased = false;
            // Store points into Points vector on click
            Point point;
            point.setxy(x, SCREEN_HEIGHT - y);
            Points.push_back(point);

            // Tangents are set to the cursor position
            Tangent.setxy(x, SCREEN_HEIGHT - y);
            inverseTangent.x = (2 * Points[Points.size() - 1].x) - Tangent.x;
            inverseTangent.y = (2 * Points[Points.size() - 1].y) - Tangent.y;

            /*Add new element to Tangent & inverseTangent so when we draw the curve
            the tangents are accessed at the right index*/
            TangentsSize++;
        }
        else if (state == GLUT_UP)
        {
            MouseReleased = true;
            // Upon mouse release store tangent and inverse tangent into separate vectors
            Tangents.push_back(Tangent);
            inverseTangents.push_back(inverseTangent);
        }
    }
}

void passiveMotion(int x, int y)
{
    // Sets the location of cursor while moving with no buttons pressed
    cursorLocationLive.setxy(x, SCREEN_HEIGHT - y);
}

void motion(int x, int y)
{
    // Sets the coordinates of the tangents when mouse moves with a button held down
    Tangent.setxy(x, SCREEN_HEIGHT - y);
    inverseTangent.x = (2 * Points[Points.size() - 1].x) - Tangent.x;
    inverseTangent.y = (2 * Points[Points.size() - 1].y) - Tangent.y;
}

void myDisplay()
{
    glClear(GL_COLOR_BUFFER_BIT);

    // Draw main points in red
    glColor3f(255, 0, 0);
    for (int i = 0; i < Points.size(); i++)
    {
        drawDot(Points[i]);
    }

    // If there is a starting point draw a line to cursor from last drawn point in passive motion
    if (Points.size() > 0)
    {
        glColor3f(0, 0, 0);
        drawLine(Points[Points.size() - 1], cursorLocationLive);
    }

    // Draw live tangent dots in green
    glColor3f(0, 255, 0);
    drawDot(Tangent);
    drawDot(inverseTangent);
    // Draw live tangent lines in blue
    glColor3f(0, 0, 255);
    drawLine(Tangent, inverseTangent);

    for (int i = 0; i < Tangents.size(); i++)
    {
        // Draw stored tangent dots in green
        glColor3f(0, 255, 0);
        drawDot(Tangents[i]);
        drawDot(inverseTangents[i]);
        // Draw stored tangent lines in blue
        glColor3f(0, 0, 255);
        drawLine(Tangents[i], inverseTangents[i]);
    }

    // Loop through all points
    for (int i = 0; i < Points.size(); i++)
    {
        // If there are two points draw the first segment
        if (Points.size() == 2)
        {
            // p1 is the start of the curve set at first point
            Point p1;
            p1 = Points[0];

            float i;
            // Calculate curve coordinates
            for (float j = 0; j <= 100; j++)
            {
                i = j / 100;
                // The Green Lines
                float xa = interpolate(Points[0].x, inverseTangents[0].x, i);
                float ya = interpolate(Points[0].y, inverseTangents[0].y, i);
                float xb = interpolate(inverseTangents[0].x, inverseTangent.x, i);
                float yb = interpolate(inverseTangents[0].y, inverseTangent.y, i);
                float xc = interpolate(inverseTangent.x, Points[1].x, i);
                float yc = interpolate(inverseTangent.y, Points[1].y, i);

                // The Blue Line
                float xm = interpolate(xa, xb, i);
                float ym = interpolate(ya, yb, i);
                float xn = interpolate(xb, xc, i);
                float yn = interpolate(yb, yc, i);

                // The Black Dot
                float x2 = interpolate(xm, xn, i);
                float y2 = interpolate(ym, yn, i);

                Point p2;
                p2.setxy(x2, y2);

                drawLine(p1, p2);

                p1 = p2;

                // Prevents curves generated during mouse motion from being stored
                if (MouseReleased)
                {
                    // Store curvature into Bezier Points
                    BezierCurve.push_back(p2);
                }
            }
        }
        // Second segment onwards
        else if (Points.size() > 2)
        {
            // p1 is the start of the curve set to second last point
            Point p1;
            p1 = Points[Points.size() - 2];

            float i;
            // Calculate curve coordinates
            for (float j = 0; j <= 100; j++)
            {
                i = j / 100;
                // The Green Lines
                float xa = interpolate(Points[Points.size() - 2].x, Tangents[TangentsSize - 2].x, i);
                float ya = interpolate(Points[Points.size() - 2].y, Tangents[TangentsSize - 2].y, i);
                float xb = interpolate(Tangents[TangentsSize - 2].x, inverseTangent.x, i);
                float yb = interpolate(Tangents[TangentsSize - 2].y, inverseTangent.y, i);
                float xc = interpolate(inverseTangent.x, Points[Points.size() - 1].x, i);
                float yc = interpolate(inverseTangent.y, Points[Points.size() - 1].y, i);

                // The Blue Line
                float xm = interpolate(xa, xb, i);
                float ym = interpolate(ya, yb, i);
                float xn = interpolate(xb, xc, i);
                float yn = interpolate(yb, yc, i);

                // The Black Dot
                float x2 = interpolate(xm, xn, i);
                float y2 = interpolate(ym, yn, i);

                Point p2;
                p2.setxy(x2, y2);

                drawLine(p1, p2);

                p1 = p2;

                // Prevents curves generated during mouse motion from being stored
                if (MouseReleased)
                {
                    // Store curvature into Bezier Points
                    BezierCurve.push_back(p2);
                }
            }
        }
    }

    // Draw all bezier curvature
    for (int i = 1; i < BezierCurve.size(); i++)
    {
        drawLine(BezierCurve[i - 1], BezierCurve[i]);
    }

    glutSwapBuffers();
}

void timer(int)
{
    glutTimerFunc(1000 / 60, timer, 0);
    glutPostRedisplay();
}

int main(int argc, char* argv[]) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(640, 500);
    glutInitWindowPosition(100, 150);
    glutCreateWindow("Bezier Curve");
    glutDisplayFunc(myDisplay);
    glutIdleFunc(myDisplay);
    glutTimerFunc(0, timer, 0);
    glutMouseFunc(myMouse);
    glutPassiveMotionFunc(passiveMotion);
    glutMotionFunc(motion);
    glClearColor(255, 255, 255, 0.0);
    glPointSize(3);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, 640.0, 0.0, 500.0);
    glutMainLoop();

    return 0;
}

I have built a Bezier Curve tool and each time the coordinates for each curve segment are calculated they are stored in a vector. Every single frame I am adding the entire curve's points on it over and over again. That is, frame 1, might have { p1, p2, p3 } then frame 2, it would have { p1, p2, p3, p1, p2, p3 } and so on. This would cause the line to loop back on itself when the loop at the end of the render function draws lines between the points p3 and p1. I am struggling to find where and how I should clear my BezierCurve vector between frames. Clearing after glClear() or before glSwapBuffers() only shows the previously drawn curve segment and has a straight line between points.
I basically want the straight line in between points to go away and I know why it is happening. My code is below:

enter image description here

#include <iostream>
#include <stdlib.h>
#include <GL/glut.h>
#include <vector>
#include <math.h>

using namespace std;

//Point class for taking the points
class Point {
public:
    float x, y;

    void setxy(float x2, float y2)
    {
        x = x2; y = y2;
    }

    //operator overloading for '=' sign
    const Point& operator=(const Point& rPoint)
    {
        x = rPoint.x;
        y = rPoint.y;
        return *this;
    }

};

int SCREEN_HEIGHT = 500;
vector<Point> Points;
Point Tangent;
Point inverseTangent;
Point cursorLocationLive;
int TangentsSize = 0;
vector<Point> Tangents(TangentsSize);
vector<Point> inverseTangents(TangentsSize);
vector<Point> BezierCurve;
bool MouseReleased = false;

void drawDot(Point p1)
{
    glBegin(GL_POINTS);
    glVertex2i(p1.x, p1.y);
    glEnd();
}

void drawLine(Point p1, Point p2)
{
    glBegin(GL_LINE_STRIP);
    glVertex2f(p1.x, p1.y);
    glVertex2f(p2.x, p2.y);
    glEnd();
}

float interpolate(float n1, float n2, float perc)
{
    float diff = n2 - n1;

    return n1 + (diff * perc);
}

void myMouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON)
    {
        if (state == GLUT_DOWN)
        {
            MouseReleased = false;
            // Store points into Points vector on click
            Point point;
            point.setxy(x, SCREEN_HEIGHT - y);
            Points.push_back(point);

            // Tangents are set to the cursor position
            Tangent.setxy(x, SCREEN_HEIGHT - y);
            inverseTangent.x = (2 * Points[Points.size() - 1].x) - Tangent.x;
            inverseTangent.y = (2 * Points[Points.size() - 1].y) - Tangent.y;

            /*Add new element to Tangent & inverseTangent so when we draw the curve
            the tangents are accessed at the right index*/
            TangentsSize++;
        }
        else if (state == GLUT_UP)
        {
            MouseReleased = true;
            // Upon mouse release store tangent and inverse tangent into separate vectors
            Tangents.push_back(Tangent);
            inverseTangents.push_back(inverseTangent);
        }
    }
}

void passiveMotion(int x, int y)
{
    // Sets the location of cursor while moving with no buttons pressed
    cursorLocationLive.setxy(x, SCREEN_HEIGHT - y);
}

void motion(int x, int y)
{
    // Sets the coordinates of the tangents when mouse moves with a button held down
    Tangent.setxy(x, SCREEN_HEIGHT - y);
    inverseTangent.x = (2 * Points[Points.size() - 1].x) - Tangent.x;
    inverseTangent.y = (2 * Points[Points.size() - 1].y) - Tangent.y;
}

void myDisplay()
{
    glClear(GL_COLOR_BUFFER_BIT);

    // Draw main points in red
    glColor3f(255, 0, 0);
    for (int i = 0; i < Points.size(); i++)
    {
        drawDot(Points[i]);
    }

    // If there is a starting point draw a line to cursor from last drawn point in passive motion
    if (Points.size() > 0)
    {
        glColor3f(0, 0, 0);
        drawLine(Points[Points.size() - 1], cursorLocationLive);
    }

    // Draw live tangent dots in green
    glColor3f(0, 255, 0);
    drawDot(Tangent);
    drawDot(inverseTangent);
    // Draw live tangent lines in blue
    glColor3f(0, 0, 255);
    drawLine(Tangent, inverseTangent);

    for (int i = 0; i < Tangents.size(); i++)
    {
        // Draw stored tangent dots in green
        glColor3f(0, 255, 0);
        drawDot(Tangents[i]);
        drawDot(inverseTangents[i]);
        // Draw stored tangent lines in blue
        glColor3f(0, 0, 255);
        drawLine(Tangents[i], inverseTangents[i]);
    }

    // Loop through all points
    for (int i = 0; i < Points.size(); i++)
    {
        // If there are two points draw the first segment
        if (Points.size() == 2)
        {
            // p1 is the start of the curve set at first point
            Point p1;
            p1 = Points[0];

            float i;
            // Calculate curve coordinates
            for (float j = 0; j <= 100; j++)
            {
                i = j / 100;
                // The Green Lines
                float xa = interpolate(Points[0].x, inverseTangents[0].x, i);
                float ya = interpolate(Points[0].y, inverseTangents[0].y, i);
                float xb = interpolate(inverseTangents[0].x, inverseTangent.x, i);
                float yb = interpolate(inverseTangents[0].y, inverseTangent.y, i);
                float xc = interpolate(inverseTangent.x, Points[1].x, i);
                float yc = interpolate(inverseTangent.y, Points[1].y, i);

                // The Blue Line
                float xm = interpolate(xa, xb, i);
                float ym = interpolate(ya, yb, i);
                float xn = interpolate(xb, xc, i);
                float yn = interpolate(yb, yc, i);

                // The Black Dot
                float x2 = interpolate(xm, xn, i);
                float y2 = interpolate(ym, yn, i);

                Point p2;
                p2.setxy(x2, y2);

                drawLine(p1, p2);

                p1 = p2;

                // Prevents curves generated during mouse motion from being stored
                if (MouseReleased)
                {
                    // Store curvature into Bezier Points
                    BezierCurve.push_back(p2);
                }
            }
        }
        // Second segment onwards
        else if (Points.size() > 2)
        {
            // p1 is the start of the curve set to second last point
            Point p1;
            p1 = Points[Points.size() - 2];

            float i;
            // Calculate curve coordinates
            for (float j = 0; j <= 100; j++)
            {
                i = j / 100;
                // The Green Lines
                float xa = interpolate(Points[Points.size() - 2].x, Tangents[TangentsSize - 2].x, i);
                float ya = interpolate(Points[Points.size() - 2].y, Tangents[TangentsSize - 2].y, i);
                float xb = interpolate(Tangents[TangentsSize - 2].x, inverseTangent.x, i);
                float yb = interpolate(Tangents[TangentsSize - 2].y, inverseTangent.y, i);
                float xc = interpolate(inverseTangent.x, Points[Points.size() - 1].x, i);
                float yc = interpolate(inverseTangent.y, Points[Points.size() - 1].y, i);

                // The Blue Line
                float xm = interpolate(xa, xb, i);
                float ym = interpolate(ya, yb, i);
                float xn = interpolate(xb, xc, i);
                float yn = interpolate(yb, yc, i);

                // The Black Dot
                float x2 = interpolate(xm, xn, i);
                float y2 = interpolate(ym, yn, i);

                Point p2;
                p2.setxy(x2, y2);

                drawLine(p1, p2);

                p1 = p2;

                // Prevents curves generated during mouse motion from being stored
                if (MouseReleased)
                {
                    // Store curvature into Bezier Points
                    BezierCurve.push_back(p2);
                }
            }
        }
    }

    // Draw all bezier curvature
    for (int i = 1; i < BezierCurve.size(); i++)
    {
        drawLine(BezierCurve[i - 1], BezierCurve[i]);
    }

    glutSwapBuffers();
}

void timer(int)
{
    glutTimerFunc(1000 / 60, timer, 0);
    glutPostRedisplay();
}

int main(int argc, char* argv[]) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(640, 500);
    glutInitWindowPosition(100, 150);
    glutCreateWindow("Bezier Curve");
    glutDisplayFunc(myDisplay);
    glutIdleFunc(myDisplay);
    glutTimerFunc(0, timer, 0);
    glutMouseFunc(myMouse);
    glutPassiveMotionFunc(passiveMotion);
    glutMotionFunc(motion);
    glClearColor(255, 255, 255, 0.0);
    glPointSize(3);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, 640.0, 0.0, 500.0);
    glutMainLoop();

    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

巴黎夜雨 2025-02-07 02:12:42

您将要检测到鼠标单击何时从向下更改为止:

bool prevMouse;
...
// at the end of Display()
prevMouse = MouseReleased;

然后,我们检查鼠标何时从按下单击更改为释放,并将行添加到bezierCurve

if (PrevMouse == 0 && MouseReleased)
{
    // Store curvature into Bezier Points
    BezierCurve.push_back(p2);
}

这两个代码路径,if(点)。 size()== 2)else if(points.size()&gt; 2)在for loop内部可以简化为if(points.size()) &gt; = 2),为此,for循环是无关的,我们不需要更新以前的任何点的bezier曲线,只有两个最新点之间的曲线,点[ points.size()-2]点[points.size() - 1]

最终代码:

#include <iostream>
#include <stdlib.h>
#include <GL/glut.h>
#include <vector>
#include <math.h>

using namespace std;

//Point class for taking the points
class Point {
public:
    float x, y;

    void setxy(float x2, float y2)
    {
        x = x2; y = y2;
    }

    //operator overloading for '=' sign
    const Point& operator=(const Point& rPoint)
    {
        x = rPoint.x;
        y = rPoint.y;
        return *this;
    }

};

int SCREEN_HEIGHT = 500;
vector<Point> Points;
Point Tangent;
Point inverseTangent;
Point cursorLocationLive;
int TangentsSize = 0;
vector<Point> Tangents(TangentsSize);
vector<Point> inverseTangents(TangentsSize);
vector<Point> BezierCurve;
bool MouseReleased = false;
bool PrevMouse = false;

void drawDot(Point p1)
{
    glBegin(GL_POINTS);
    glVertex2i(p1.x, p1.y);
    glEnd();
}

void drawLine(Point p1, Point p2)
{
    glBegin(GL_LINE_STRIP);
    glVertex2f(p1.x, p1.y);
    glVertex2f(p2.x, p2.y);
    glEnd();
}

float interpolate(float n1, float n2, float perc)
{
    float diff = n2 - n1;

    return n1 + (diff * perc);
}

void myMouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON)
    {
        if (state == GLUT_DOWN)
        {
            MouseReleased = false;
            // Store points into Points vector on click
            Point point;
            point.setxy(x, SCREEN_HEIGHT - y);
            Points.push_back(point);

            // Tangents are set to the cursor position
            Tangent.setxy(x, SCREEN_HEIGHT - y);
            inverseTangent.x = (2 * Points[Points.size() - 1].x) - Tangent.x;
            inverseTangent.y = (2 * Points[Points.size() - 1].y) - Tangent.y;

            /*Add new element to Tangent & inverseTangent so when we draw the curve
            the tangents are accessed at the right index*/
            TangentsSize++;
        }
        else if (state == GLUT_UP)
        {
            MouseReleased = true;
            // Upon mouse release store tangent and inverse tangent into separate vectors
            Tangents.push_back(Tangent);
            inverseTangents.push_back(inverseTangent);
        }
    }
}

void passiveMotion(int x, int y)
{
    // Sets the location of cursor while moving with no buttons pressed
    cursorLocationLive.setxy(x, SCREEN_HEIGHT - y);
}

void motion(int x, int y)
{
    // Sets the coordinates of the tangents when mouse moves with a button held down
    Tangent.setxy(x, SCREEN_HEIGHT - y);
    inverseTangent.x = (2 * Points[Points.size() - 1].x) - Tangent.x;
    inverseTangent.y = (2 * Points[Points.size() - 1].y) - Tangent.y;
}

void myDisplay()
{
    glClear(GL_COLOR_BUFFER_BIT);

    // Draw main points in red
    glColor3f(255, 0, 0);
    for (int i = 0; i < Points.size(); i++)
    {
        drawDot(Points[i]);
    }

    // If there is a starting point draw a line to cursor from last drawn point in passive motion
    if (Points.size() > 0)
    {
        glColor3f(0, 0, 0);
        drawLine(Points[Points.size() - 1], cursorLocationLive);
    }

    // Draw live tangent dots in green
    glColor3f(0, 255, 0);
    drawDot(Tangent);
    drawDot(inverseTangent);
    // Draw live tangent lines in blue
    glColor3f(0, 0, 255);
    drawLine(Tangent, inverseTangent);

    for (int i = 0; i < Tangents.size(); i++)
    {
        // Draw stored tangent dots in green
        glColor3f(0, 255, 0);
        drawDot(Tangents[i]);
        drawDot(inverseTangents[i]);
        // Draw stored tangent lines in blue
        glColor3f(0, 0, 255);
        drawLine(Tangents[i], inverseTangents[i]);
    }

    // Loop through all points
    if (Points.size() >= 2)
    {
        // p1 is the start of the curve set to second last point
        Point p1;
        p1 = Points[Points.size() - 2];

        float i;
        // Calculate curve coordinates
        for (float j = 0; j <= 100; j++)
        {
            i = j / 100;
            // The Green Lines
            float xa = interpolate(Points[Points.size() - 2].x, Tangents[TangentsSize - 2].x, i);
            float ya = interpolate(Points[Points.size() - 2].y, Tangents[TangentsSize - 2].y, i);
            float xb = interpolate(Tangents[TangentsSize - 2].x, inverseTangent.x, i);
            float yb = interpolate(Tangents[TangentsSize - 2].y, inverseTangent.y, i);
            float xc = interpolate(inverseTangent.x, Points[Points.size() - 1].x, i);
            float yc = interpolate(inverseTangent.y, Points[Points.size() - 1].y, i);

            // The Blue Line
            float xm = interpolate(xa, xb, i);
            float ym = interpolate(ya, yb, i);
            float xn = interpolate(xb, xc, i);
            float yn = interpolate(yb, yc, i);

            // The Black Dot
            float x2 = interpolate(xm, xn, i);
            float y2 = interpolate(ym, yn, i);

            Point p2;
            p2.setxy(x2, y2);

            drawLine(p1, p2);

            p1 = p2;

            // Prevents curves generated during mouse motion from being stored
            if (PrevMouse == 0 && MouseReleased)
            {
                // Store curvature into Bezier Points
                BezierCurve.push_back(p2);
            }
        }
    }
    std::cout << BezierCurve.size() << std::endl;
    
    PrevMouse = MouseReleased;

    // Draw all bezier curvature
    for (int i = 1; i < BezierCurve.size(); i++)
    {
        drawLine(BezierCurve[i - 1], BezierCurve[i]);
    }

    glutSwapBuffers();
}

void timer(int)
{
    glutTimerFunc(1000 / 60, timer, 0);
    glutPostRedisplay();
}

int main(int argc, char* argv[]) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(640, 500);
    glutInitWindowPosition(100, 150);
    glutCreateWindow("Bezier Curve");
    glutDisplayFunc(myDisplay);
    glutIdleFunc(myDisplay);
    glutTimerFunc(0, timer, 0);
    glutMouseFunc(myMouse);
    glutPassiveMotionFunc(passiveMotion);
    glutMotionFunc(motion);
    glClearColor(255, 255, 255, 0.0);
    glPointSize(3);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, 640.0, 0.0, 500.0);
    glutMainLoop();

    return 0;
}

You will want to detect when mouse click changes from down to up:

bool prevMouse;
...
// at the end of Display()
prevMouse = MouseReleased;

Then we check when mouse click changes from pressed to released and add lines to BezierCurve:

if (PrevMouse == 0 && MouseReleased)
{
    // Store curvature into Bezier Points
    BezierCurve.push_back(p2);
}

The two code paths, if (Points.size() == 2), and else if (Points.size() > 2) inside the for loop can be simplified to if (Points.size() >= 2) and for that matter the for loop is extraneous, we don't need to update the bezier curve for any of the previous points, just the curve between the two newest points, Points[Points.size() - 2] and Points[Points.size() - 1].

The final code:

#include <iostream>
#include <stdlib.h>
#include <GL/glut.h>
#include <vector>
#include <math.h>

using namespace std;

//Point class for taking the points
class Point {
public:
    float x, y;

    void setxy(float x2, float y2)
    {
        x = x2; y = y2;
    }

    //operator overloading for '=' sign
    const Point& operator=(const Point& rPoint)
    {
        x = rPoint.x;
        y = rPoint.y;
        return *this;
    }

};

int SCREEN_HEIGHT = 500;
vector<Point> Points;
Point Tangent;
Point inverseTangent;
Point cursorLocationLive;
int TangentsSize = 0;
vector<Point> Tangents(TangentsSize);
vector<Point> inverseTangents(TangentsSize);
vector<Point> BezierCurve;
bool MouseReleased = false;
bool PrevMouse = false;

void drawDot(Point p1)
{
    glBegin(GL_POINTS);
    glVertex2i(p1.x, p1.y);
    glEnd();
}

void drawLine(Point p1, Point p2)
{
    glBegin(GL_LINE_STRIP);
    glVertex2f(p1.x, p1.y);
    glVertex2f(p2.x, p2.y);
    glEnd();
}

float interpolate(float n1, float n2, float perc)
{
    float diff = n2 - n1;

    return n1 + (diff * perc);
}

void myMouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON)
    {
        if (state == GLUT_DOWN)
        {
            MouseReleased = false;
            // Store points into Points vector on click
            Point point;
            point.setxy(x, SCREEN_HEIGHT - y);
            Points.push_back(point);

            // Tangents are set to the cursor position
            Tangent.setxy(x, SCREEN_HEIGHT - y);
            inverseTangent.x = (2 * Points[Points.size() - 1].x) - Tangent.x;
            inverseTangent.y = (2 * Points[Points.size() - 1].y) - Tangent.y;

            /*Add new element to Tangent & inverseTangent so when we draw the curve
            the tangents are accessed at the right index*/
            TangentsSize++;
        }
        else if (state == GLUT_UP)
        {
            MouseReleased = true;
            // Upon mouse release store tangent and inverse tangent into separate vectors
            Tangents.push_back(Tangent);
            inverseTangents.push_back(inverseTangent);
        }
    }
}

void passiveMotion(int x, int y)
{
    // Sets the location of cursor while moving with no buttons pressed
    cursorLocationLive.setxy(x, SCREEN_HEIGHT - y);
}

void motion(int x, int y)
{
    // Sets the coordinates of the tangents when mouse moves with a button held down
    Tangent.setxy(x, SCREEN_HEIGHT - y);
    inverseTangent.x = (2 * Points[Points.size() - 1].x) - Tangent.x;
    inverseTangent.y = (2 * Points[Points.size() - 1].y) - Tangent.y;
}

void myDisplay()
{
    glClear(GL_COLOR_BUFFER_BIT);

    // Draw main points in red
    glColor3f(255, 0, 0);
    for (int i = 0; i < Points.size(); i++)
    {
        drawDot(Points[i]);
    }

    // If there is a starting point draw a line to cursor from last drawn point in passive motion
    if (Points.size() > 0)
    {
        glColor3f(0, 0, 0);
        drawLine(Points[Points.size() - 1], cursorLocationLive);
    }

    // Draw live tangent dots in green
    glColor3f(0, 255, 0);
    drawDot(Tangent);
    drawDot(inverseTangent);
    // Draw live tangent lines in blue
    glColor3f(0, 0, 255);
    drawLine(Tangent, inverseTangent);

    for (int i = 0; i < Tangents.size(); i++)
    {
        // Draw stored tangent dots in green
        glColor3f(0, 255, 0);
        drawDot(Tangents[i]);
        drawDot(inverseTangents[i]);
        // Draw stored tangent lines in blue
        glColor3f(0, 0, 255);
        drawLine(Tangents[i], inverseTangents[i]);
    }

    // Loop through all points
    if (Points.size() >= 2)
    {
        // p1 is the start of the curve set to second last point
        Point p1;
        p1 = Points[Points.size() - 2];

        float i;
        // Calculate curve coordinates
        for (float j = 0; j <= 100; j++)
        {
            i = j / 100;
            // The Green Lines
            float xa = interpolate(Points[Points.size() - 2].x, Tangents[TangentsSize - 2].x, i);
            float ya = interpolate(Points[Points.size() - 2].y, Tangents[TangentsSize - 2].y, i);
            float xb = interpolate(Tangents[TangentsSize - 2].x, inverseTangent.x, i);
            float yb = interpolate(Tangents[TangentsSize - 2].y, inverseTangent.y, i);
            float xc = interpolate(inverseTangent.x, Points[Points.size() - 1].x, i);
            float yc = interpolate(inverseTangent.y, Points[Points.size() - 1].y, i);

            // The Blue Line
            float xm = interpolate(xa, xb, i);
            float ym = interpolate(ya, yb, i);
            float xn = interpolate(xb, xc, i);
            float yn = interpolate(yb, yc, i);

            // The Black Dot
            float x2 = interpolate(xm, xn, i);
            float y2 = interpolate(ym, yn, i);

            Point p2;
            p2.setxy(x2, y2);

            drawLine(p1, p2);

            p1 = p2;

            // Prevents curves generated during mouse motion from being stored
            if (PrevMouse == 0 && MouseReleased)
            {
                // Store curvature into Bezier Points
                BezierCurve.push_back(p2);
            }
        }
    }
    std::cout << BezierCurve.size() << std::endl;
    
    PrevMouse = MouseReleased;

    // Draw all bezier curvature
    for (int i = 1; i < BezierCurve.size(); i++)
    {
        drawLine(BezierCurve[i - 1], BezierCurve[i]);
    }

    glutSwapBuffers();
}

void timer(int)
{
    glutTimerFunc(1000 / 60, timer, 0);
    glutPostRedisplay();
}

int main(int argc, char* argv[]) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(640, 500);
    glutInitWindowPosition(100, 150);
    glutCreateWindow("Bezier Curve");
    glutDisplayFunc(myDisplay);
    glutIdleFunc(myDisplay);
    glutTimerFunc(0, timer, 0);
    glutMouseFunc(myMouse);
    glutPassiveMotionFunc(passiveMotion);
    glutMotionFunc(motion);
    glClearColor(255, 255, 255, 0.0);
    glPointSize(3);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, 640.0, 0.0, 500.0);
    glutMainLoop();

    return 0;
}

bezier

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文