C++ 用openGL(c+;+;)将椭圆分解为三角形

C++ 用openGL(c+;+;)将椭圆分解为三角形,c++,opengl,drawing,draw,freeglut,C++,Opengl,Drawing,Draw,Freeglut,我必须为大学做作业(在OpenGL中画蝴蝶)。目前我正在研究蝴蝶的身体,这是一个简单的椭圆(这将是一个2D游戏)。我必须用三角形绘制这个填充椭圆,因为我们不能使用其他库(我假设有一个简单的圆()或类似的函数) 现在我可以画一个三角形了,但是从蝴蝶的身体类中创建一个三角形是行不通的。代码如下: class Triangle { unsigned int vao; unsigned int vbo[2]; float phi; float vertexCoords[6

我必须为大学做作业(在OpenGL中画蝴蝶)。目前我正在研究蝴蝶的身体,这是一个简单的椭圆(这将是一个2D游戏)。我必须用三角形绘制这个填充椭圆,因为我们不能使用其他库(我假设有一个简单的圆()或类似的函数)

现在我可以画一个三角形了,但是从蝴蝶的身体类中创建一个三角形是行不通的。代码如下:

class Triangle {
    unsigned int vao;
    unsigned int vbo[2];
    float phi;
    float vertexCoords[6];
    float vertexColors[9] = {1,0,0, 0,1,0,  0,0,1};

public:

    Triangle(float x1,float y1,float x2,float y2,float x3, float y3) {
        vertexCoords[0] = x1;
        vertexCoords[1] = y1;
        vertexCoords[2] = x2;
        vertexCoords[3] = y2;
        vertexCoords[4] = x3;
        vertexCoords[5] = y3;
        Animate(0);
    }

    void setTriangleColor(float r, float g, float b) {
        for (int i = 0; i < 9; i+=3) {
            vertexColors[i] = r;
            vertexColors[i + 1] = g;
            vertexColors[i + 2] = b;        
        }
        Create();
    }

    void setPointColor(float r, float g, float b, int count) {
        vertexColors[count * 3] = r;
        vertexColors[count * 3 + 1] = g;
        vertexColors[count * 3 + 2] = b;
        Create();
    }

    void Create() { 
        glGenVertexArrays(1, &vao);
        glBindVertexArray(vao);
        glGenBuffers(2, &vbo[0]);
        glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
        glBufferData(GL_ARRAY_BUFFER,sizeof(vertexCoords),vertexCoords,GL_STATIC_DRAW);  
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0,2, GL_FLOAT,GL_FALSE,0, NULL);
        glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertexColors), vertexColors, GL_STATIC_DRAW);
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    }

    void Animate(float t) { /*phi = t;*/ phi = 0; }

    void Draw() {
        mat4 ScaleSmaller(
            0.01, 0   , 0   , 0,
            0  , 0.01 , 0   , 0,
            0  , 0   , 0.01 , 0,
            0  , 0   , 0   , 1
        );
        mat4 MVPTransform1(1, 0, 0, 0,
            0, cosf(phi), -sinf(phi), 0,
            0, sinf(phi), cosf(phi), 0,
            0, 0, 0, 1);
        int location = glGetUniformLocation(shaderProgram, "MVP");
        if (location >= 0) glUniformMatrix4fv(location, 1, GL_TRUE, (MVPTransform1*ScaleSmaller)); 
        else printf("uniform MVP cannot be set\n");

        glBindVertexArray(vao); 
        glDrawArrays(GL_TRIANGLES, 0, 3);
    }
};

struct Point {
    float x, y;

    Point(float x,float y):x(x),y(y){}
    Point():x(0),y(0){}
};

class MyEllipse {   
    float width;
    float height;
    Point origo;
    std::vector<Triangle> triangles = std::vector<Triangle>();

public:
    MyEllipse() {}

    MyEllipse(Point origo,float width, float height):origo(origo),width(width),height(height) {
        float px = origo.x + (width / 2) * cosf(90);
        float py = origo.y + (height / 2) * cosf(90);
        float prevX = origo.x + (width / 2) * cosf(0);
        float prevY = origo.y + (height / 2) * cosf(0);
        Triangle elem1(origo.x, origo.y, px, py, prevX, prevY);
        triangles.push_back(elem1);
    }

    void Create() {
        for (Triangle value : triangles) {
            value.Create();
        }
    }

    void Draw() {
        for (Triangle value : triangles) {
            value.Draw();
        }
    }
};
(稍后我将向向量添加更多三角形,现在我只是测试。)问题是,我可以看到三角形,但如果我删除三角形创建线,我什么也看不到。在代码的另一部分,当我调用triangle.Create()或triangle.Draw()时,我没有忘记添加适当的Draw()和Create()函数调用,之后我立即调用test1.Create()和test1.Draw()函数


有谁能告诉我有关这个问题的任何信息,因为我恐怕不知道如何解决这个问题。

在methodes
MyEllipse::Create
MyEllipse::Draw
中,迭代三角形时会创建每个三角形的副本:

for (Triangle value : triangles) // <- the "content" of "triangles" is copied to "value"
{
    value.Create();
}
进一步计算arg的余弦(以弧度为单位)

这意味着你必须使用

#define _USE_MATH_DEFINES
#include <math.h>

float angle_in_degree = ....;
cosf(angle_in_degree * M_PI/180.0f);

但是为每个三角形创建单独的顶点缓冲区和顶点数组对象是一个非常糟糕的主意。为网格创建一个顶点缓冲区和一个顶点数组对象。

我建议以如下方式创建顶点缓冲区和顶点数组对象:

float a = 0.2f;
float b = 0.5f;
int   no_of_triangles = 20;
std::vector<float> varray{ 0.0f, 0.0f, 0.5f, 0.5f, 0.5f };
for ( int i = 0; i <= no_of_triangles; ++i )
{
    float angle = (float)i/(float)no_of_triangles * 2.0f * M_PI;
    float x     = cos( angle );
    float y     = sin( angle );
    varray.push_back( x * a );
    varray.push_back( y * b );
    varray.push_back( 0.5f - x * 0.5f );
    varray.push_back( 0.5f - y * 0.5f );
    varray.push_back( (0.5f*x+0.5f)*(0.5f*y+0.5f) );
}

GLuint vbo;
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, varray.size()*sizeof(*varray.data()), varray.data(), GL_STATIC_DRAW );

GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 5*sizeof(*varray.data()), 0 );
glEnableVertexAttribArray( 0 );
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 5*sizeof(*varray.data()), (void*)(2*sizeof(*varray.data())) );
glEnableVertexAttribArray( 1 );

glBindBuffer( GL_ARRAY_BUFFER, 0 );
glBindVertexArray( 0 );
预览:


cosf最有可能采用弧度,而不是度,因此通过90看起来是错误的。只是为了记录:为每个三角形创建vao/vbo不是使用现代opengl的预期方式。为所有三角形的所有位置创建一个VBO,依此类推。然后一次将它们全部绘制出来。我将尝试使用弧度数,但问题是,我在直接创建三角形类时使用了cosf(),并且它是可见的。诀窍是
for(Triangle&value:triangles)
,重点是
&
!(在
Create
)中创建。是否修改了两个循环?在创作和绘画中?是的,就是这样!!!最后一个是钥匙,它帮助我最终解决了这个问题!!!!非常感谢,我是你的部门!他的问题是坐标,如果你看,我用cos()函数计算了所有坐标,结果坐标几乎相同!此外,是的,我必须更改为iTreator或参考资料!真的谢谢你们大家!
#define _USE_MATH_DEFINES
#include <math.h>

float angle_in_degree = ....;
cosf(angle_in_degree * M_PI/180.0f);
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); 
glDrawArrays(GL_TRIANGLES, 0, 3);
float a = 0.2f;
float b = 0.5f;
int   no_of_triangles = 20;
std::vector<float> varray{ 0.0f, 0.0f, 0.5f, 0.5f, 0.5f };
for ( int i = 0; i <= no_of_triangles; ++i )
{
    float angle = (float)i/(float)no_of_triangles * 2.0f * M_PI;
    float x     = cos( angle );
    float y     = sin( angle );
    varray.push_back( x * a );
    varray.push_back( y * b );
    varray.push_back( 0.5f - x * 0.5f );
    varray.push_back( 0.5f - y * 0.5f );
    varray.push_back( (0.5f*x+0.5f)*(0.5f*y+0.5f) );
}

GLuint vbo;
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, varray.size()*sizeof(*varray.data()), varray.data(), GL_STATIC_DRAW );

GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 5*sizeof(*varray.data()), 0 );
glEnableVertexAttribArray( 0 );
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 5*sizeof(*varray.data()), (void*)(2*sizeof(*varray.data())) );
glEnableVertexAttribArray( 1 );

glBindBuffer( GL_ARRAY_BUFFER, 0 );
glBindVertexArray( 0 );
glBindVertexArray( vao );
glDrawArrays( GL_TRIANGLE_FAN, 0, (GLsizei)varray.size()/5 );
glBindVertexArray( 0 );