gluTessCallback(3) テセレーションオブジェクトに対してコールバックを定義する

書式

void gluTessCallback( GLUtesselator* tess,


GLenum which,
_GLUfuncptr CallBackFunc )

delim $$

引き数

tess
テセレーションオブジェクト(gluNewTess を使って作る) を指定する。
which
定義するコールバックを指定する。 有効な値は次の通りである: GLU_TESS_BEGIN, GLU_TESS_BEGIN_DATA, GLU_TESS_EDGE_FLAG, GLU_TESS_EDGE_FLAG_DATA, GLU_TESS_VERTEX, GLU_TESS_VERTEX_DATA, GLU_TESS_END, GLU_TESS_END_DATA, GLU_TESS_COMBINE, GLU_TESS_COMBINE_DATA, GLU_TESS_ERROR, GLU_TESS_ERROR_DATA
CallBackFunc
呼び出される関数を指定する。

説明

gluTessCallback は、テセレーションオブジェクトが 使うコールバックを指示するために使う。 指定されたコールバックが既に定義されている場合、そのコールバックは 置き換えられる。 CallBackFunc が NULL ならば、現在あるコールバックは未定義の 状態にされる。

これらのコールバックはテセレーションオブジェクトが使い、 ユーザが指定したポリゴンをどのように三角形分割するのかを 記述するために使われる。 それぞれのコールバックにはふたつのバージョンがある点に注意すること: ユーザが指定したポリゴンデータを受け取るものと受け取らないものである。 あるコールバックについて両方のバージョンが指定されている場合は、 ユーザが指定したポリゴンデータを受け取るバージョンの方が使われる。 一部の関数に使われる polygon_data 引き数は、 gluTessBeginPolygon が呼び出された時に指定されていたポインタの コピーである点に注意すること。 指定可能なコールバックは以下の通りである:

GLU_TESS_BEGIN
開始コールバックは glBegin のように呼ばれ、(三角形)プリミティブ の開始を示す。 この関数は GLenum 型の引き数をひとつ取る。 GLU_TESS_BOUNDARY_ONLY 属性に GL_FALSE が設定されてい る場合は、引き数には GL_TRIANGLE_FAN, GL_TRIANGLE_STRIP, GL_TRIANGLES のいずれかが設定される。 GLU_TESS_BOUNDARY_ONLY 属性に GL_TRUE が設定されている 場合は、引き数には GL_LINE_LOOP が設定される。 このコールバックの関数プロトタイプを以下に示す:
void begin ( GLenum type );
GLU_TESS_BEGIN_DATA
GLU_TESS_BEGIN コールバックとほぼ同じであるが、ポインタ引き数 をひとつ多く取る点が異なる。 このポインタは gluTessBeginPolygon が呼ばれたときに与えられた opaque なポインタと同一のものである。 このコールバックの関数プロトタイプを以下に示す:
void beginData ( GLenum type, void *polygon_data );
GLU_TESS_EDGE_FLAG
稜線フラグコールバックは glEdgeFlag に似ている。 この関数は真偽値をひとつ引き数として取り、この引き数はどの稜線が ポリゴンの境界上にあるのかを示す。 このフラグが GL_TRUE ならば、その後に続くそれぞれの頂点は ポリゴン境界上にある稜線を開始する。つまり、内部領域を外部領域と区別 する稜線を開始する。 このフラグが GL_FALSE ならば、その後に続くそれぞれの頂点は ポリゴン内部にある稜線を開始する。 稜線フラグコールバックは(もし定義されていれば)最初の頂点コールバックの 前に呼び出される。
三角形要素によるファン形状と三角形要素によるストリップ形状は稜線フラグ に対応していないので、NULL でない稜線フラグコールバックが指定されている 場合にも開始コールバックは GL_TRIANGLE_FANGL_TRIANGLE_STRIP を引き数に呼ばれることはない。 (このコールバックが NULL に初期化されていれば、性能への影響はない。) その代わりに、ファン形状やストリップ形状は独立した三角形群に変換される。 このコールバックの関数プロトタイプを以下に示す:
void edgeFlag ( GLboolean flag );
GLU_TESS_EDGE_FLAG_DATA
GLU_TESS_EDGE_FLAG コールバックに似ているが、ポインタ引き数を ひとつ多く取る点が異なる。 このポインタは gluTessBeginPolygon が呼ばれたときに与えられた opaque なポインタと同一のものである。 このコールバックの関数プロトタイプを以下に示す:
void edgeFlagData ( GLboolean flag, void *polygon_data );
GLU_TESS_VERTEX
頂点コールバックは開始コールバックと終了コールバックの間で呼ばれる。 このコールバックは glVertex に似ており、テセレーション処理で 作られた三角形群の頂点を定義する。 この関数はポインタ引き数をひとつだけ取る。 このポインタは、頂点が記述された(gluTessVertex を参照)ときに ユーザが指定した opaque なポインタと同一のものである。 このコールバックの関数プロトタイプを以下に示す:
void vertex ( void *vertex_data );
GLU_TESS_VERTEX_DATA
GLU_TESS_VERTEX コールバックとほぼ同じであるが、ポインタ引き数 をひとつ多く取る点が異なる。 このポインタは gluTessBeginPolygon が呼ばれたときに与えられた opaque なポインタと同一のものである。 このコールバックの関数プロトタイプを以下に示す:
void vertexData ( void *vertex_data, void *polygon_data );
GLU_TESS_END
終了コールバックの用途は glEnd と同じである。 このコールバックはプリミティブの終わりを示し、引き数は取らない。 このコールバックの関数プロトタイプを以下に示す:
void end ( void );
GLU_TESS_END_DATA
GLU_TESS_END コールバックとほぼ同じであるが、ポインタ引き数 をひとつ多く取る点が異なる。 このポインタは gluTessBeginPolygon が呼ばれたときに与えられた opaque なポインタと同一のものである。 このコールバックの関数プロトタイプを以下に示す:
void endData ( void *polygon_data);
GLU_TESS_COMBINE
結合コールバックは、テセレーションが干渉を検出した時や 形状特徴をマージしようとした時に、新しい頂点を作るために呼び出される。 この関数は次の 4 つの引き数を取る: GLdouble 型の要素 3 つの配列、 4 つのポインタの配列、GLfloat 型の要素 4 つの配列、ポインタへのポインタ である。 関数プロトタイプを以下に示す:
void combine( GLdouble coords[3], void *vertex_data[4],
              GLfloat weight[4], void **outData );
頂点は、既存の 4 つまでの頂点の線形結合として定義される。 この頂点は vertex_data に格納される。 線形結合の係数は weight で与える。 この重み付けにおいては、係数の合計は必ず 1 でなければならない。 いくつかの重みの値が 0 であっても、頂点を指す全てのポインタは有効である。 coords は新しい頂点の座標を与える。
ユーザは新しい頂点を割り当て、vertex_dataweight を 使ってパラメータを補間し、新しい頂点を指すポインタを outData に 返さなければならない。 この処理はレンダリングコールバックの間に与えられる。 gluTessEndPolygon が呼ばれてからしばらく後に メモリを解放するのはユーザの責任である。
例えば、ポリゴンが 3 次元空間内の任意の平面内にあり、 各頂点に色が割り当てられている場合には、GLU_TESS_COMBINE コールバックは以下のようになる:
void myCombine( GLdouble coords[3], VERTEX *d[4],
                GLfloat w[4], VERTEX **dataOut ) {
   VERTEX *new = new_vertex();


   new->x = coords[0];
   new->y = coords[1];
   new->z = coords[2];
   new->r = w[0]*d[0]->r + w[1]*d[1]->r + w[2]*d[2]->r + w[3]*d[3]->r;
   new->g = w[0]*d[0]->g + w[1]*d[1]->g + w[2]*d[2]->g + w[3]*d[3]->g;
   new->b = w[0]*d[0]->b + w[1]*d[1]->b + w[2]*d[2]->b + w[3]*d[3]->b;
   new->a = w[0]*d[0]->a + w[1]*d[1]->a + w[2]*d[2]->a + w[3]*d[3]->a;
   *dataOut = new; }

テセレーション処理が干渉を見つけた場合には、GLU_TESS_COMBINE コールバックまたは GLU_TESS_COMBINE_DATA コールバック(後述)が 定義されていなければならず、さらにこのコールバックは NULL でない ポインタを dataOut に書き込まなければならない。 そうでない場合は、GLU_TESS_NEED_COMBINE_CALLBACK エラー が起こり、出力はまったく行われない。
GLU_TESS_COMBINE コールバックとほぼ同じであるが、ポインタ引き数 をひとつ多く取る点が異なる。 このポインタは gluTessBeginPolygon が呼ばれたときに与えられた opaque なポインタと同一のものである。 このコールバックの関数プロトタイプを以下に示す:
void combineData ( GLdouble coords[3], void *vertex_data[4],
                   GLfloat weight[4], void **outData, 
                   void *polygon_data );
GLU_TESS_ERROR
エラーコールバックはエラーが起きたときに呼び出される。 このコールバックは GLenum 型の引き数をひとつ取る。 この引き数は起こったエラーを示し、 GLU_TESS_MISSING_BEGIN_POLYGON, GLU_TESS_MISSING_END_POLYGON, GLU_TESS_MISSING_BEGIN_CONTOUR, GLU_TESS_MISSING_END_CONTOUR, GLU_TESS_COORD_TOO_LARGE, GLU_TESS_NEED_COMBINE_CALLBACK, GLU_OUT_OF_MEMORY のいずれかが設定される。 これらのエラーを表す文字列は、gluErrorString の呼び出しで取得 できる。 このコールバックの関数プロトタイプを以下に示す:
void error ( GLenum errno );
GLU ライブラリは、足りない呼び出しを挿入することにより、 最初の 4 つのエラーからは復帰する。 GLU_TESS_COORD_TOO_LARGE は、座標の絶対値が 予め定義されている定数である GLU_TESS_MAX_COORD を超えている 頂点があり、その座標値が束縛を受けたことを示す。 (座標値は、ふたつの座標値を掛け合わせてもオーバーフローしない程度に 小さくなければならない。) GLU_TESS_NEED_COMBINE_CALLBACK は、テセレーション処理が 入力データ中のふたつの稜線の干渉が検出され、 GLU_TESS_COMBINE コールバックや GLU_TESS_COMBINE_DATA コールバックが与えられなかったことを示す。 この場合には出力はまったく行われない。 GLU_OUT_OF_MEMORY は、出力結果を生成するために必要なメモリが 不足していたことを示す。
GLU_TESS_ERROR_DATA
GLU_TESS_ERROR コールバックとほぼ同じであるが、ポインタ引き数 をひとつ多く取る点が異なる。 このポインタは gluTessBeginPolygon が呼ばれたときに与えられた opaque なポインタと同一のものである。 このコールバックの関数プロトタイプを以下に示す:
void errorData ( GLenum errno, void *polygon_data );

使用例

テセレーション処理されたポリゴンは次のようにすると 直接レンダリングできる:

gluTessCallback(tobj, GLU_TESS_BEGIN, glBegin); gluTessCallback(tobj, GLU_TESS_VERTEX, glVertex3dv); gluTessCallback(tobj, GLU_TESS_END, glEnd); gluTessCallback(tobj, GLU_TESS_COMBINE, myCombine); gluTessBeginPolygon(tobj, NULL);
  gluTessBeginContour(tobj);
    gluTessVertex(tobj, v, v);
    ...
  gluTessEndContour(tobj); gluTessEndPolygon(tobj);

普通は、テセレーション処理で得たポリゴンはディスプレイリストに格納 すべきである。そうすれば、レンダリングするたびに毎回テセレーション処理 をやり直す必要がないからである。