Entries

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

iGLUでテセレーション

タグ: iPhone Objective-C C++ OpenGL

iGLU: OpenGL Utility Library for iPhone OS

Available features:
  • Matrix manipulation
  • Polygon tessellation

iPhone向けGLUライブラリ。
ちょうどポリゴンをテセレーションしたかったのでありがたい。
早速使ってみる(SDK for iPhone OS 2.2)。

  1. プロジェクトテンプレート「OpenGL ES Application」を選んで新規プロジェクトを作成。
  2. iGLUへのパスを設定。
  3. 一部処理をC++のSTLで楽したいので、「EAGLView.m」を「EAGLView.mm」に改名。
  4. EAGLView.mmにインクルード文を追加。
    #include <vector>
    #include <list>
    #include <algorithm>
    #include <glu.h>
  5. コールバック関数等を定義。
    // 頂点配列(7要素で1頂点)
    
    typedef std::vector<GLfloat> es_vertices;
    typedef std::vector<GLdouble> glu_vertices;
    const int vertex_coord_size = 3;
    const int vertex_color_size = 4;
    const int vertex_size = vertex_coord_size + vertex_color_size;
    
    // ポリゴンの三角形プリミティブ
    
    struct polygon_part
    {
    	GLenum type;
    	es_vertices vertices;
    };
    
    void draw_part(const polygon_part& part)
    {
    	glVertexPointer(
    		vertex_coord_size,
    		GL_FLOAT,
    		sizeof(GLfloat) * vertex_size,
    		&part.vertices[0]
    	);
    	glColorPointer(
    		vertex_color_size,
    		GL_FLOAT,
    		sizeof(GLfloat) * vertex_size,
    		&part.vertices[0] + vertex_coord_size
    	);
    	glDrawArrays(part.type, 0, part.vertices.size() / vertex_size);
    }
    
    // テセレーション用データ
    
    typedef std::vector<polygon_part> polygon_parts;
    
    struct tessellation_data
    {
    	polygon_parts* parts;
    	std::list<glu_vertices> combine_buffer;
    };
    
    // テセレーション用コールバック
    
    void tess_begin_data(
    	GLenum type,
    	tessellation_data* polygon_data
    )
    {
    	polygon_part part;
    	part.type = type;
    	polygon_data->parts->push_back(part);
    }
    
    void tess_vertex_data(
    	const GLdouble* vertex_data,
    	tessellation_data* polygon_data
    )
    {
    	es_vertices& vertices = polygon_data->parts->back().vertices;
    	vertices.insert(vertices.end(), vertex_data, vertex_data + vertex_size);
    }
    
    void tess_combine_data(
    	const GLdouble coords[3],
    	const GLdouble* vertex_data[4],
    	const GLfloat weight[4],
    	const GLdouble** out_data,
    	tessellation_data* polygon_data
    )
    {
    	glu_vertices vertex(vertex_size);
    	std::copy(coords, coords + vertex_coord_size, vertex.begin());
    	for(int i = vertex_coord_size; i < vertex_size; i++)
    	{
    		vertex[i] =
    			weight[0] * vertex_data[0][i] +
    			weight[1] * vertex_data[1][i] +
    			weight[2] * vertex_data[2][i] +
    			weight[3] * vertex_data[3][i];
    	}
    	std::list<glu_vertices>& buffer = polygon_data->combine_buffer;
    	*out_data = &((*buffer.insert(buffer.end(), vertex))[0]);
    }
  6. drawViewの中身を書き換える。
    GLdouble starVertices[][vertex_size] = {
    	{ -0.5, -0.5, 0.0, 1.0, 0.0, 1.0, 1.0 },
    	{ 0.0, 0.5, 0.0, 1.0, 1.0, 0.0, 1.0 },
    	{ 0.5, -0.5, 0.0, 0.0, 1.0, 1.0, 1.0 },
    	{ -0.75, 0.1, 0.0, 1.0, 0.0, 0.0, 1.0 },
    	{ 0.75, 0.1, 0.0, 0.0, 1.0, 0.0, 1.0 },
    };
    
    polygon_parts parts;
    
    GLUtesselator* t = gluNewTess();
    gluTessCallback(t, GLU_TESS_BEGIN_DATA, (GLvoid (*) ())&tess_begin_data);
    gluTessCallback(t, GLU_TESS_VERTEX_DATA, (GLvoid (*) ())&tess_vertex_data);
    gluTessCallback(t, GLU_TESS_COMBINE_DATA, (GLvoid (*) ())&tess_combine_data);
    gluTessProperty(t, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
    tessellation_data data;
    data.parts = &parts;
    gluTessBeginPolygon(t, &data);
    gluTessBeginContour(t);
    for(int i = 0; i < 5; i++)
    {
    	gluTessVertex(t, starVertices[i], starVertices[i]);
    }
    gluTessEndContour(t);
    gluTessEndPolygon(t);
    gluDeleteTess(t);
    
    [EAGLContext setCurrentContext:context];
    
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glViewport(0, 0, backingWidth, backingHeight);
    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrthof(-1.0f, 1.0f, -1.5f, 1.5f, -1.0f, 1.0f);
    glMatrixMode(GL_MODELVIEW);
    glRotatef(3.0f, 0.0f, 0.0f, 1.0f);
    
    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    std::for_each(parts.begin(), parts.end(), &draw_part);
    
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
tessellation.png
スポンサーサイト

コメント

コメントの投稿

コメントの投稿
管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://idlysphere.blog66.fc2.com/tb.php/165-aa9b5a88
この記事にトラックバックする(FC2ブログユーザー)

Appendix

タグ

Blog内検索

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。