編集:あなたは実験していると思いましたが、コードはOpenGLチュートリアルからのものであることがわかります。私はそれをちらりと見て、あなたのポイントを今理解しました。そこから基礎を学ぶのは難しい。
NURBS バックグラウンド
NURBS を理解する最善の方法は、インタラクティブに操作することです。次に、エッジを定義するポイント (エッジ上)、形状を定義するポイント (その他すべて)、それらの間の接線関係、および連続性についての直感を得ることができます。NURBS はパッチで構成され、エッジで縫い合わされ、連続性が高度に制御されます。つまり、車の本体には G3 を、安価なゲーム モデルには C1 を求めることができます。どんな説明からでもコンセプトを理解するのは本当に難しいです。この方法で取得したい場合は、Rhino Nurbs Modellerのトライアルを強くお勧めします。. 何年も前に使用しましたが、今では放棄されたように見えますが、それでも最高の NURBS サポートの 1 つを備えたソフトウェアです (Autodesk 3d Studio MAX と MAYA はさらに悪い)。少し時間がかかるかもしれませんが、最初はもっと単純なもので遊ぶことをお勧めします。「Simple Bezier Curve Editor」ページからアプレットを取り出して試してみてください。
NURBS を理解するには、ウィキペディアの Bezier Curves に関する記事も参考にしてください。点の位置と最終的な曲線形状との関係を把握したら、それを曲面に簡単に一般化できます。このアニメーションは非常に直感的です。
例のサーフェスは、布が張られた 4 つの曲線のセットとして想像できます。先ほどリンクしたアプレットを使用すると、位置を操作して、結果の形状に関するフィードバックを即座に得ることができます。パラメータに注意してt
ください。これは曲線に沿った座標であり、範囲は [0, 1] です。NURBS サーフェスには、慣例により と と呼ばれる 2 つの座標がu
ありますv
(これは描画機能にとって重要です)。
したがって、ctrlpoints
コードの構造体はすべてのポイント座標を保持します。説明を簡略化すると、これらは 4 つの 3 次ベジエ曲線 (アニメーションのもの) です。曲線ごとに、3 次元内に 4 つの点があります。Y 軸を無視すると、それらはすべてグリッド上にあり、X と Z は -1.5、-1.0、1.0、1.5 です。これは、合計 32 個の値 (X の 4x4 と Z の 4x4) を説明しています。
残りは高さ、Y 値です。あなたの場合、それは のすべてのポイントの 2 番目の値ですctrlpoints
。期待どおりの結果を得るには、すべての Y 値をエッジ (外側) で等しくし、中央 (4 内側) でわずかに高くします。あなたは得るでしょう:
上の画像をレンダリングするために使用されるポイント:
GLfloat ctrlpoints[4][4][3] = {
{{-1.5, 1.0, -1.5}, {-0.5, 1.0,-1.5 }, {0.5, 1.0, -1.5 }, {1.5, 1.0,-1.5}},
{{-1.5, 1.0, -0.5}, {-0.5, 2.0,-0.5 }, {0.5, 2.0, -0.5 }, {1.5, 1.0,-0.5}},
{{-1.5, 1.0, 0.5}, {-0.5, 2.0, 0.5 }, {0.5, 2.0, 0.5 }, {1.5, 1.0, 0.5}},
{{-1.5, 1.0, 1.5}, {-0.5, 1.0, 1.5 }, {0.5, 1.0, 1.5 }, {1.5, 1.0, 1.5}}
};
// ^ ^ ^ ^
// | | | |
// | | | |
// \_________ Those are most relevant - Y-coord, height ______/
GLUT を使用した OpenGL の NURBS - API ウォークスルー
OpenGL API が非常に関連性の高い詳細を隠していることがわかります。NURBS サーフェスは を使用して描画Evaluator
され、関数で定義されMap
ます。
init(void)
次のように、関数で制御点を定義することになっています。
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4,
0, 1, 12, 4, &ctrlpoints[0][0][0]);
関数の適切な説明は、glMap2f の MSDN サイトにあります。コントロール ポイント、そのタイプ、および配列のストライドや順序などの詳細を渡します。
関数を使用して描画できEvaluator
ます。引数として 2 つの座標を取り、3 次元空間の点を返します。これらの入力座標はまさに、アニメーションの下で前述したu
ものです。v
この例では:
glBegin(GL_LINE_STRIP); // we'll draw a line
// take 31 samples of a cross-section of the surface
for (i = 0; i <= 30; i++)
// for each sample, evaluate a 3d point
glEvalCoord2f((GLfloat)i/30.0, (GLfloat)j/8.0);
// notice j is constant in the loop here, but
// is being changed by the outer loop.
//
// j is iterated in 9 steps, so we'll end up
// with 9 lines
glEnd();
ここで説明する外側のループを意図的に省略しました。
// we want 9 lines
for (j = 0; j <= 8; j++) {
// OpenGL state machine will be used to draw lines
glBegin(GL_LINE_STRIP);
// inner loop for j-th line along X
glBegin(GL_LINE_STRIP);
// inner loop for j-th line along Z
glEnd(); // done with the lines
}
実施例
#include <stdlib.h>
#include <GL/glut.h>
GLfloat ctrlpoints[4][4][3] = {
{{-1.5, 1.0, -1.5}, {-0.5, 1.0,-1.5 }, {0.5, 1.0, -1.5 }, {1.5, 1.0,-1.5}},
{{-1.5, 1.0, -0.5}, {-0.5, 2.0,-0.5 }, {0.5, 2.0, -0.5 }, {1.5, 1.0,-0.5}},
{{-1.5, 1.0, 0.5}, {-0.5, 2.0, 0.5 }, {0.5, 2.0, 0.5 }, {1.5, 1.0, 0.5}},
{{-1.5, 1.0, 1.5}, {-0.5, 1.0, 1.5 }, {0.5, 1.0, 1.5 }, {1.5, 1.0, 1.5}}
};
void display(void)
{
int i, j;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glPushMatrix();
glRotatef(25.0, 1.0, 1.0, 1.0);
for (j = 0; j <= 8; j++) {
glBegin(GL_LINE_STRIP);
for (i = 0; i <= 30; i++)
glEvalCoord2f((GLfloat)i/30.0, (GLfloat)j/8.0);
glEnd();
glBegin(GL_LINE_STRIP);
for (i = 0; i <= 30; i++)
glEvalCoord2f((GLfloat)j/8.0, (GLfloat)i/30.0);
glEnd();
}
glPopMatrix();
glFlush();
}
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4,
0, 1, 12, 4, &ctrlpoints[0][0][0]);
glEnable(GL_MAP2_VERTEX_3);
glMapGrid2f(20, 0.0, 1.0, 20, 0.0, 1.0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_FLAT);
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w,
5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0);
else
glOrtho(-5.0*(GLfloat)w/(GLfloat)h,
5.0*(GLfloat)w/(GLfloat)h, -5.0, 5.0, -5.0, 5.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}