pdf09

9- 1
9.
自由曲線・自由曲面
9.1. NURBSによる描画
OpenGLではNURBS(Non Uniform Rational B-Spline)による曲線・曲面がサ
ポートされている.これは自由曲線から円や楕円のような解析的な曲線も統一
的に表現できる.
N
NURBS曲線
P(t ) =
∑B
i =0
N
i,K
∑B
M
NURBS曲面
(t ) wi
i,K
i =0
S (u , v) =
(t ) wi Pi
K,Lはノットベクトルの次元
N
∑ ∑B
i =0
M
j =0
i,K
(u ) B j , L (v) wi , j Pi , j
N
∑ ∑B
i =0
j =0
i,K
(u ) B j , L (v) wi , j
数式的な詳しいことはおき,直感的にいうと
1)大元の関数Bで表される曲線に重みwをつけて1つの曲線をつくる
2)それを空間上の制御点という引力でさらに変形させる
9- 2
P31
P30
P20
P33
P32 P
22
P21
P12
P11
P02
P10
P01
u
P00
v
x(u,v)=Sx(u,v)
y(u,v)=Sy(u,v)
z(u,v)=Sz(u,v)
P23
9- 3
9.2. 自由曲線の描画
前章までの描画と異なり,1つの曲線を1つのオブジェクトと考える.
ファイルポインタと対応づけるとわかりやすい.
1)オブジェクトの生成
a)ポインタ変数を宣言する
GLUnurbsobj *nrb_obj;
(FILE *file;のように)
b)ポインタを生成する
nrb_obj= gluNewNurbsRenderer(); (file=open(“test.c”…)と類似)
gluNurbsProperty(nrb_obj, GLU_SAMPLING_TOLERANCE,
25.0);
GLU_SAMPLING_TOLERANCE:その後の数字で描画に使用される
多角形の線分や辺の最大長を ピクセルで定義する(線分やポリゴンで曲線や
曲面を近似する際の分割の大きさの目安)
9- 4
void gluNurbsProperty( GLUnurbs* nurb,
GLenum property, GLfloat value )
nurb: NRUBS オブジェクト
property: 属性
GLU_SAMPLING_TOLERANCE
GLU_DISPLAY_MODE
GLU_CULLING
GLU_AUTO_LOAD_MATRIX
GLU_PARAMETRIC_TOLERANCE
GLU_SAMPLING_METHOD
GLU_U_STEP, GLU_V_STEP
GLU_NURBS_MODE_EXT
9- 5
2)オブジェクトの記述
gluBeginCurve(nrb_obj);
gluNurbsCurve(nrb_obj,8,knotvec,4,
&cpoint[0][0],4, GL_MAP1_VERTEX_4);
gluEndCurve(nrb_obj);
void gluNurbsCurve(GLUnurbsObj* nobj,
GLint uknot_number, GLfloat* uknot,
GLint u_stride, GLfloat* ctlarray,
GLint uorder, GLenum type);
9- 6
void gluNurbsCurve(GLUnurbsObj* nrb_obj,
GLint uknot_number, GLfloat* uknot,
GLint u_stride, GLfloat* ctlarray,
GLint uorder, GLenum type);
uknot_number:u方向のノットの数 =8=
uknot:u方向ノットの値を持った配列 =8次元=
u_stride:制御点の配列ctlarrayでu方向へ添え字 =4=
が1つ増えたとき, GLfloatいくつ分移動
すれば次の配列要素へアクセスできる
かを指定する
ctlarray:制御点の座標を格納してある配列
uorder:u方向の階数(曲線の次数+1)=4=
type: 曲線の形を指定する.
GL_MAP1_VERTEX_4 x,y,z,w有理制御点の場合
制御点のデータが曲面上の点ではなく,各制御点における法線の値
を指定している場合はGL_MAP1_NORMALを指定する
c9-1.c
c9-1a.c :z,xキーでweightを変える
9- 7
9.3. 自由曲面の描画
自由曲線と同様に考える.
1)オブジェクトの生成
a)ポインタを宣言する
GLUnurbsobj *nrb_obj;
(FILE *file;のように)
b)ポインタを生成する
nrb_obj= gluNewNurbsRenderer(); (file=open(“test.c…)と類似)
gluNurbsProperty(nrb_obj, GLU_SAMPLING_TOLERANCE,
25.0);
gluNurbsProperty(nrb_obj, GLU_DISPLAY_MODE,
GLU_FILL);
GLU_FILL:陰影画
GLU_OUTLINE_POLYGON:線画表示
9- 8
2)オブジェクトの記述
gluBeginSurface(nrb_obj);
gluNurbsSurface(nrb_obj,
8,knotvec_u,
8,knotvec_v,
4*4,
4,
&cpoint[0][0][0],
4,4,
GL_MAP2_VERTEX_4
);
gluEndSurface(nrb_obj);
c9-2.c
c9-2a.c (x座標,z座標を選択し,右ボタン,中ボタン
で制御点移動)
9- 9
gluNurbsSurface(GLUnurbsObj* nobj,
GLint uknot_number, GLfloat* uknot,
GLint vknot_number, GLfloat* vknot,
GLint u_stride, GLint v_stride,
GLfloat* ctlarray, GLint uorder,
GLint vorder, GLenum type);
uknot_number,vknot_number:u方向とv方向のノットの数
uknot,vknot:u方向とv方向のノットの値を持った配列
u_stride,v_stride:ctlarrayでu方向とv方向へそれぞれ添え字が1つ
増えたとき, GLfloatいくつ分移動すれば次の配列要素へアクセスで
きるかを指定する
ctlarray:制御点の座標を格納してある配列
uorder,vorder:u方向とv方向の階数(次数+1)
9- 10
9.4. 重みの変更方法
gluBeginCurve(nrb_obj);
gluNurbsCurve(nrb_obj,
8,knotvec,
4,
&cpoint[0][0],
4,
GL_MAP1_VERTEX_4
);
gluEndCurve(nrb_obj);
通常のスプライン曲線(曲面)とするには,この関数の最後のパラメータを
GL_MAP1_VERTEX_3 として,cpoint[i][0],cpoint[i][1], cpoint[i][2]に各制御点の
x,y,z座標を入れる.
重みによって曲線を変化させる有理スプラインとするにはGL_MAP1_VERTEX_4
として第4パラメータcpoint[i][3]に重みを入れる.
Sampleプログラムでは同次座標系を使って重みによって座標値を割り算している
ため,重みを変えた場合はその分だけ掛け合わせる.
9- 11
練習問題に対応するサンプルプログラム
c9-3.c
(練習問題2-2 c9-2を改造し,制御点を移動させることで曲面
形状を変形させるアニメーションを作成する.インタラクティブにしなくても
よい.どれか1つの制御点を変えるアニメーション)
c9-4.c
(練習問題2-3 制御点の重みを変えることで曲面形状を変形
させるアニメーション.インタラクティブにしなくてもよい.どれか1つの重み
を変えてみる)
c9-5.c
(課題1 制御点を増やした曲面)