Rokiのチラ裏

学生による学習のログ

Ubuntu on OpenGL + GLUTで遊んでみた

なんとなく弄りたくなった。導入。

% sudo apt-get install freeglut3 freeglut3-dev

取り敢えず、空のウィンドウを出力してみる。

#include<GL/glut.h>

int main(int argc,char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA);
    glutCreateWindow("test");
    glutDisplayFunc([]{
            glClearColor(0.0, 0.0, 0.0, 1.0);
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            glFlush();
            });
    glutMainLoop();
}
% g++ test.cpp -std=c++1z -lGL -lGLU -lglut

...これだけではつまらないので、球体を、右往左往させてみる。また、無駄にラッパーを作成して、初期化などの前処理を、覆ってみた。

#include<GL/glut.h>
#include<GL/gl.h>
#include<GL/glu.h>

#include<array>
#include<map>
#include<functional>
#include<boost/utility.hpp>

namespace glut{

float x=0.0f;

class _Color:boost::noncopyable{
    std::array<GLfloat,4> data;
public:
    _Color(GLfloat r,GLfloat g,GLfloat b,GLfloat a)
        :data{r,g,b,a}{};
    const GLfloat* get()const{return data.data();}
};
struct _LightPos final:_Color{
    _LightPos(GLfloat a,GLfloat b,GLfloat c,GLfloat d)
        :_Color(a,b,c,d){};
};

template<class _Tp>
struct _two_value:private boost::noncopyable{
    std::pair<_Tp,_Tp> data{static_cast<_Tp>(0),static_cast<_Tp>(0)};
    explicit _two_value(_Tp l=0,_Tp r=0):data(l,r){};
};
struct _Position final:_two_value<int>{
    explicit _Position(int x,int y):_two_value(x,y){}
};
struct _WindowSize final:_two_value<std::size_t>{
    explicit _WindowSize(std::size_t width,std::size_t height):_two_value(width,height){}
    std::size_t width()const{return data.first;}
    std::size_t height()const{return data.second;}
};


struct _Title final:private boost::noncopyable{
    const char* title;
    explicit _Title(const char* s):title(s){}
};


struct _DisplayFunc:private boost::noncopyable{
    void (*func_ptr)();
    explicit _DisplayFunc(void (*arg)()):func_ptr(arg){}
};
struct _IdleFunc final:_DisplayFunc{
    explicit _IdleFunc(void (*arg)()):_DisplayFunc(arg){}
};


template<int MODE>
struct Draw final{
    const glut::_WindowSize size;

    explicit Draw(int& argc,char* argv[],
            glut::_WindowSize&& ws,
            glut::_Position&& pt,
            glut::_Title&& tl,
            glut::_DisplayFunc&& df,
            glut::_IdleFunc&& ifu,
            std::function<void()>&& initialize_function)
        :size(ws.data.first,ws.data.second)
    {
        glutInitWindowPosition(pt.data.first,pt.data.second);
        glutInitWindowSize(size.data.first,size.data.second);
        glutInit(&argc,argv);
        glutInitDisplayMode(MODE);
        glutCreateWindow(tl.title);
        glutDisplayFunc(df.func_ptr);
        glutIdleFunc(ifu.func_ptr);
        initialize_function();
    }

    inline void do_main_loop()const{glutMainLoop();}
};
}

int main(int argc,char *argv[])
{
    auto init=[]{
        glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);
    };
    
    auto display=[]{
        const glut::_Color rgba(0.0,1.0,0.0,1.0);
        const glut::_LightPos lightpos(200.0,150.0,-500.0,1.0);
        const glut::_WindowSize wsize(320,240);

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glViewport(0,0,wsize.width(),wsize.height());
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(30.0,static_cast<double>(wsize.width())/static_cast<double>(wsize.height()),1.0,1000.0);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        gluLookAt(150.0,100.0,-200.0,0.0,0.0,0.0,0.0,1.0,0.0);
        glLightfv(GL_LIGHT0, GL_POSITION, lightpos.get());
        glMaterialfv(GL_FRONT, GL_DIFFUSE,rgba.get());
        glTranslatef(glut::x,0.0f,0.0f);
        glutSolidSphere(40.0,16,16);
        glutSwapBuffers();
    };

    auto idle=[]{
        static bool flag=false;
        if(flag)
            glut::x-=0.5f;
        else
            glut::x+=0.5f;
        if(glut::x>50.0f)flag=true;
        if(glut::x<-50.0f)flag=false;
        glutPostRedisplay();
    };
    

    const glut::_WindowSize wsize(320,240);
    const glut::Draw<GLUT_RGBA|GLUT_DOUBLE> 
        glut(argc,argv,
                glut::_WindowSize(wsize.width(),wsize.height()),
                glut::_Position(100,100),
                glut::_Title("test"),
                glut::_DisplayFunc(display),
                glut::_IdleFunc(idle),
                std::move(init));

    glut.do_main_loop();
}

C言語向きのライブラリなので、使っていると、グローバル領域感に少々気持ち悪くなってくる。

余談

実はこのエントリ内にも掲載しているようなGIFキャプチャ画像を、GNU/Linux上で撮りたいと思い、少しばかり検索をかけてみたのだが、使い勝手の良いツールが、exeしかない。これはしょうがない、wineでエミュレートしようと

sudo apt-get install -y wine

と打ったのだが、なんだかよくわからない動きをした。

要するに、wineをインストールしようとして、ファイルシステムが破壊されたという事だ。もはや、恐怖でしかない。
ただ、これに関しては、また別途再現テストをするつもりである。
因みに、このエントリに掲載されているGIF画像は、泣く泣くWindows上のVirtual Machineにてコードを実行し、キャプチャしたものだ。