Boost.coroutineを使った
コルーチンのエントリー部分から呼ばれるサブ関数以下でyield()をしたかったら、引数で渡すしかないのか・・・
コルーチンは順番がはっきりしているのでcaller_typeをグローバルにしても良いのかしら。
// glew32s.libを使う. #define GLEW_STATIC #include <stdio.h> #include <stdlib.h> #include <boost/coroutine/all.hpp> #include <GL/glew.h> #include <GLFW/glfw3.h> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> #include <FTGL/ftgl.h> #include "Shader.h" #define FONT_FILE "C:\\Windows\\Fonts\\msgothic.ttc" const int g_WindowWidth = 640; const int g_WindowHeight = 480; GLuint g_VBO = 0; GLuint g_Indices = 0; GLFWwindow* g_Window = NULL; glm::mat4 g_World; glm::mat4 g_View; glm::mat4 g_Proj; float g_RotZ = 0.0f; FTPixmapFont* g_Font = NULL; typedef boost::coroutines::coroutine<void()> CoRoutine; int g_Counter = 0; void my_coroutine(CoRoutine::caller_type& yield) { bool isEnd = false; while(!isEnd) { yield(); printf("my_coroutine %d\n", g_Counter++); } } // 初期化. void init() { printf("BOOST VERSION %d.%d.%d\n", BOOST_VERSION/100000, BOOST_VERSION/100 %1000, BOOST_VERSION%100); // 初期化. if(!glfwInit()) { exit(EXIT_FAILURE); } g_Window = glfwCreateWindow(g_WindowWidth, g_WindowHeight, "Test", NULL, NULL); if(!g_Window) { glfwTerminate(); exit(EXIT_FAILURE); } glfwMakeContextCurrent(g_Window); GLenum err = glewInit(); if(err != GLEW_OK) { glfwTerminate(); exit(EXIT_FAILURE); } g_Font = new FTPixmapFont(FONT_FILE); if(g_Font->Error()) { exit(EXIT_FAILURE); } g_Font->FaceSize(32); g_Font->CharMap(ft_encoding_unicode); } int main() { CoRoutine co(my_coroutine); init(); // カメラ設定. float ratio = float(g_WindowWidth)/float(g_WindowHeight); g_Proj = glm::perspective(30.0f, ratio, 1.f, 50.f); g_View = glm::lookAt(glm::vec3(0, 0, 10), glm::vec3(0,0,0), glm::vec3(0,1,0)); // ジオメトリ設定. GLfloat vertexBuffer [] = { 0, 2, 0, -2, -2, 0, 2, -2, 0 }; GLubyte indexBuffer[] = { 0, 1, 2 }; glGenBuffers(1, &g_VBO); glGenBuffers(1, &g_Indices); glBindBuffer(GL_ARRAY_BUFFER, g_VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertexBuffer), vertexBuffer, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_Indices); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexBuffer), indexBuffer, GL_STATIC_DRAW); // シェーダー. GLuint vs, fs, sp; vs = CreateVertexShader("vertex.vert"); fs = CreateFragmentShader("fragment.frag"); sp = glCreateProgram(); glAttachShader(sp, vs); glAttachShader(sp, fs); glBindFragDataLocation(sp, 0, "outColor"); glLinkProgram(sp); glUseProgram(sp); GLint sp_pos = glGetAttribLocation(sp, "pos"); GLint sp_world = glGetUniformLocation(sp, "world"); GLint sp_view = glGetUniformLocation(sp, "view"); GLint sp_proj = glGetUniformLocation(sp, "proj"); static char s_Buff[1024]; // メインループ. while(!glfwWindowShouldClose(g_Window)) { co(); if(glfwGetKey(g_Window, GLFW_KEY_ESCAPE) == GLFW_PRESS) { glfwSetWindowShouldClose(g_Window, GL_TRUE); } glViewport(0, 0, g_WindowWidth, g_WindowHeight); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glm::mat4 identity(1); g_World = glm::rotate(identity, g_RotZ, glm::vec3(0, 0, 1)); glColor3f(1, 0, 0); g_RotZ += 0.5f; glUseProgram(sp); glBindBuffer(GL_ARRAY_BUFFER, g_VBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_Indices); // ユニフォーム. glUniformMatrix4fv(sp_world, 1, GL_FALSE, glm::value_ptr(g_World)); glUniformMatrix4fv(sp_view, 1, GL_FALSE, glm::value_ptr(g_View)); glUniformMatrix4fv(sp_proj, 1, GL_FALSE, glm::value_ptr(g_Proj)); glEnableVertexAttribArray(0); glVertexAttribPointer(sp_pos, 3, GL_FLOAT, GL_FALSE, sizeof(float)*3, 0); glEnableVertexAttribArray(sp_pos); glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, 0); glDisableVertexAttribArray(sp_pos); glUseProgram(0); float front_ambient[4] = { 0.7, 0.7, 0.7, 0.0 }; glDisable(GL_LIGHTING); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(0, g_WindowWidth, g_WindowHeight, 0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glRasterPos2f(32, 32); sprintf(s_Buff, "coroutine counter = %d", g_Counter); g_Font->Render(s_Buff);//L"こんにちは"); glfwSwapBuffers(g_Window); glfwPollEvents(); } // 破棄. glDeleteBuffers(1, &g_VBO); glDeleteBuffers(1, &g_Indices); glDeleteShader(vs); glDeleteShader(fs); glDeleteProgram(sp); glfwDestroyWindow(g_Window); // 終了処理. glfwTerminate(); return 0; }