2

クラスを使用して OpenGL を簡単に管理できるものを作成しようとしています。

私は Drawable クラスを作成し (shapes/etc は描画関数を継承し、オーバーライドします)、次に Controller クラスを使用して Drawable クラスのテーブルを反復処理し、それらすべてを描画するというアプローチを取りました。draw() メソッドが Rectangle クラスではなく Drawable クラスから呼び出されていることに気付いた唯一の問題。??

    class Drawable {
        public:
            void draw();
    };
    class Rectangle : public Drawable {
        public:
            void draw();
    };
    class Controller {
        public:
            Drawable ents[200];
            int ent_count;
            void frame();
            void append(Drawable item); // this will add an object onto the list
            Controller();
    };
    void Drawable::draw() {
        // this is the default drawing function, which should be overridden
    }
    void Rectangle::draw() {
        // gl functions here
    }
    void Controller::frame() {
        for(int i=0;i<ent_count,i++) {
            ents[i].draw(); // draw all entities on the list
        }
        // here, a timer would loop back the frame() function
    }
    void Controller::append(Drawable item) {
         ents[ent_count++]=item;
    }
    int main(void) {
         Controller main_controller; // create a controller
         Rectangle rect; // create a rectangle
         main_controller.append(rect); // insert rectangle into controller list
         main_controller.frame(); // start the frame loop
    }

[その中で軽微なタイプミスがある場合、それはメソッドの要約として書かれているためです。] 私が使用しようとしたこのメソッドはあまり成功していません。継承。何か案は?ソースコード全体:

#include <iostream>
#include <GL/glfw.h>
#include <GL/gl.h>
class Drawable {
      public:
             int x,y;
             void draw();
             void frame();
             void create();
             void destroy(); 
};
void Drawable::create() {

}
void Drawable::draw() {
}
class Rectangle : public Drawable {
      public:
      int w,h;
      unsigned short r,g,b;
      Rectangle(int x,int y, int w, int h, unsigned short r, unsigned short g, unsigned short b);
      void draw();
};
void Rectangle::draw() {
     glColor3ub(r,g,b);
     glBegin(GL_QUADS);
     glVertex2i(x,y);
     glVertex2i(x+w,y);
     glVertex2i(x+w,y+h);
     glVertex2i(x,y+h);
     glEnd();
}
Rectangle::Rectangle(int x,int y, int w, int h, unsigned short r, unsigned short g, unsigned short b) {
                         this->x=x;
                         this->y=y;
                         this->w=w;
                         this->r=r;
                         this->g=g;
                         this->b=b;
}
class Controller {
public:
       Controller(int w,int h,int fsaa,bool fs,bool vsync,const char* title);
       bool running;
       int frame_limit;
       Drawable entity[200];
       int entity_count;
       void fev();
       void begin();
       void bind();
       void append(Drawable item);
      };
Controller::Controller(int w,int h,int fsaa,bool fs,bool vsync,const char* title) {
                          int fullscreen= (fs ? GLFW_FULLSCREEN : GLFW_WINDOW);
                          bool window=glfwOpenWindow(w,h,0,0,0,0,10,10,fullscreen);
                          glfwSetWindowTitle(title);
                          frame_limit=120;
                          entity_count=0;
                          std::cout << (window ? "Successfully initialized a window.\n" : "Error initializing window!\n");
       }
void Controller::begin() {
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     glOrtho(0,640,480,0,0,5);
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
     glClearColor(0.4f,0.4f,0.4f,1.0f);
     running=true;
     fev();
}
void Controller::append(Drawable item) {
     entity[entity_count++]=item;
}
void Controller::fev() {
     glClear(GL_COLOR_BUFFER_BIT);
     for (int i=0;i<entity_count;++i) {
          entity[i].draw();
          }
     glfwSwapBuffers();
     if (frame_limit>0) {
        glfwSleep(1000/frame_limit*0.001);
     }
     if (running) {
        if (glfwGetKey(GLFW_KEY_ESC) || !glfwGetWindowParam(GLFW_OPENED)) {
           running=false;
        }
        fev();
     } else {
       std::cout << "terminated!";
}
}
int main(void) {
    glfwInit();
    Controller main(640,480,0,false,false,"WindTitle");
    Rectangle rect(50,50,50,50,50,50,50);
    main.append(rect);
    main.begin();
}
4

3 に答える 3

4

クラスを使用して OpenGL を簡単に管理できるものを作成しようとしています。

初心者はよくこれを試します。しかし、OpenGL は実際には OOP にうまく変換されません。問題は、それが有限状態マシンであり、OOP に適切にマップするには、さまざまなクラスとインスタンス間で多くの状態を追跡する必要があることです。

私自身、OpenGL を OOP スキームに抽象化するために少なくとも 3 回試みました。いつもどこかで壊れていました。

OpenGL で OOP を使用できないというわけではありません。OpenGL の概念を 1 対 1 でクラスにマッピングすることはできません。


実際の問題について:仮想関数を使用してください。

于 2013-01-02T00:34:55.410 に答える
3

他の人が述べたように、既存のラッパーのいくつかを使用することをお勧めします。

つまり、エンティティのリストにはポインターを使用する必要があります。スライスに問題があります。

Drawable::draw()いくつかのコメントが言及したように、仮想にする必要があるためdraw()、 aDrawableを呼び出すと、子実装が呼び出されます。つまり、Drawableオブジェクトへのポインターのリストではなく、オブジェクトのリストに s を追加しているため、オブジェクトはスライスされています。これは、子の型からオブジェクトに変換され、Drawable特定の型に関する追加情報が削除されていることを意味します。

したがって、これの代わりに:

Drawable ents[200];

次のようにする必要があります。

std::vector<Drawable*> ents;

または、C++11 または Boost を使用している場合:

std::vector<std::shared_ptr<Drawable>> ents;

そして、追加メソッドは参照を取ります。

void Controller::append(Drawable &item) {
     ents[ent_count++] = &item;
}

また

void Controller::append(Drawable &item) {
  ents.push_back(&item);
}

また

void Controller::append(std::shared_ptr<Drawable> item) {
  ents.push_back(item);
}

レンダー ループは次のようになります。

for (int i = 0; i < ents.size(); ++i) {
  ents[i]->draw();
}

このループは、使用するためにクリーンアップすることもできますiterator

于 2013-01-02T00:32:26.433 に答える
0

Coin3Dをご覧になることをお勧めします。これは、OpenGL に関する豊富な C++ クラス ラッパーのセットです。あなたは彼らがそれをどのように使用するかを見ることができます。さまざまなウィンドウ システム (Qt、Windows、Cocoa など) と統合するためのライブラリがあります。

于 2013-01-02T00:54:49.427 に答える