bate's blog

調べたこと実装したことなどを取りとめもなく書きます。

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;
}