前回の記事でOpenGLを使ってウインドウを表示してみたが、味気なさ過ぎるのでとりあえず2Dの何かを描いてみることにした。直線とか四角を描くのも少し物足りないので円にする。
OpenGLの描画は基本的に頂点を指定してつないでいくというものなので、円は細かい直線の連続として表すことになる。基本的な描画方法は次のようになる。
- glColor3d(GLdoubleR, GLdouble G, GLdouble B);←この後描くものの色を指定
- glBegin(GL_POLYGON);←ポリゴンで描く、他にも線で囲むだけのGL_LINE_LOOPとかを指定できる。
- glVertex3d(GLdouble x, GLdouble y, GLdouble z);←頂点を指定
- glVertex3dを繰り返して必要な頂点を順番に指定する。
- glEnd();
以上のような処理を描画関数の中に書くといいらしい。
どうも一つずつ頂点を指定して、形を指定しなければならないようでとてもめんどくさい。というわけで、よく使いそうな図形のクラスを作成することにした。とりあえず今回描こうとしている円クラスを作ることにする。将来的に四角とか三角を作るためにGLObjectクラスを作成し、それを継承することにした。
GLObjectクラス
- class GLObject{
- protected:
- int mode_;←描画モード
- GLColor color_;←塗りつぶす色
- public:
- GLObject():mode_(GL_POLYGON){};←デフォルトはポリゴン
- GLObject(int mode):mode_(mode){};
- virtual void setColor(GLColor Color) = 0;←色指定メンバ関数
- virtual void setObject() = 0;←配置メンバ関数
- }
GLObjectクラスは抽象クラスとした。オブジェクトなんて曖昧なものを実体化できるわけがない。デフォルトでポリゴンモードで描画して、色をメンバ偏すに持っている。色指定と配置関数を用意した。こいつを継承する形でGLCircleクラスを作成する。
GLCircleクラス
- class GLCircle : GLObject{
- private:
- GLdouble center_[2];←中心座標
- GLdouble radius_;←直径
- int nPoint_;←描画する直線の数
- public:
- GLCircle():
- radius_(0.5),nPoint_(20)←デフォルトはウインドウの半分の直径で20本の直線で描画
- {
- this->center_[0] = 0.5;
- this->center_[1] = 0.5;←中心座標はウインドウの中心
- }
- GLCircle(int mode):←モード指定できるコンストラクタ、他のはデフォルトと同じ
- GLObject(mode),
- radius_(0.5),
- nPoint_(20)
- {
- this->center_[0] = 0.5;
- this->center_[1] = 0.5;
- }
- GLCircle(int mode, GLdouble x, GLdouble y, GLdouble r, int n):←全部指定のコンストラクタ
- GLObject(mode),
- radius_(r),
- nPoint_(n)
- {
- this->center_[0] = x;
- this->center_[1] = y;
- }
- virtual void setColor(GLColor Color){←色設定メンバ関数の実装
- this->color_ = Color;
- }
- virtual void setObject()←配置関数の実装
- {
- glColor3d(this->color_.r(), this->color_.g(), this->color_.b());←色指定
- glBegin(this->mode_);
- for(int i = 0; i < this->nPoint_; i++){←要は直線数で分割して点を指定していくということ
- double rate = (double)i / nPoint_;
- double x = this->radius_ * cos(2.0 * M_PI * rate) + this->center_[0];←i番目のx座標
- double y = this->radius_ * sin(2.0 * M_PI * rate) + this->center_[1];←i番目のy座標
- glVertex3d(x, y, 0.0);
- }
- glEnd();
- }
- void setCenter(GLdouble x, GLdouble y)←中心座標設定メンバ関数
- {
- this->center_[0] = x;
- this->center_[1] = y;
- }
- void setNPoint(int n)←直線数の指定メンバ関数
- {
- this->nPoint_ = n;
- }
- void setRadius(GLdouble r)←直径指定メンバ関数
- {
- this->radius_ = r;
- }
- }
GLObjectのメンバに加えて、中心座標と半径と何本の直線で表示するの変数とそれぞれのset関数を用意した。直径指定なのに変数名が半径なのは途中まで半径と思い込んでいたためで、気にしないでほしい。
ついでに、所々に出てくるGLColorなるものは、色指定でいちいち3つも値を描くのが面倒なため、クラス化したもの。中身はこんな感じ。
- class GLColor{
- private:
- GLdouble r_;
- GLdouble g_;
- GLdouble b_;
- public: GLColor():
- r_(0.0),g_(0.0),b_(0.0){}
- GLColor(GLdouble r, GLdouble g, GLdouble b):
- r_(r),g_(g),b_(b){}
- ~GLColor(){}
- GLdouble r(){ return this->r_; }
- GLdouble g(){ return this->g_; }
- GLdouble b(){ return this->b_; }
- }
メンバ変数にRGBそれぞれの値を持っていて、メンバ関数から呼び出せるというもの。
前回作成した描画関数にこんな感じで書き足す
- void display(){
- GLCircle circle;←円オブジェクトを作成
- GLColor color(0.0, 1.0,0.0);←緑色を作る
- circle.setColor(color);←色指定
- circle.setNPoint(100);←分割数
- circle.setCenter(0.1, 0.1);←中心座標指定
- glClear(GL_COLOR_BUFFER_BIT);
- circle.setObject();←配置
- glFlush();
- }
メイン関数とかは前回と変わらない。これを実行すると次のようになる。
いくら何でも色のセンスが悪すぎだとは思う。が、気にしない。全体のソースはこちら→ WindowClass2.cpp
これはもはや円ではないと思う。円を描くクラスと言うより、正n角形を描画するクラスってことでおおような気もしてきた。今回はここまで。
コメント